6f071add14a8121cfafee6d1d23239001e19cb3a
[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, [],
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.  To transfer large files you should use
4708 FTP."
4709
4710 let danger_will_robinson =
4711   "B<This command is dangerous.  Without careful use you
4712 can easily destroy all your data>."
4713
4714 let deprecation_notice flags =
4715   try
4716     let alt =
4717       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4718     let txt =
4719       sprintf "This function is deprecated.
4720 In new code, use the C<%s> call instead.
4721
4722 Deprecated functions will not be removed from the API, but the
4723 fact that they are deprecated indicates that there are problems
4724 with correct use of these functions." alt in
4725     Some txt
4726   with
4727     Not_found -> None
4728
4729 (* Create list of optional groups. *)
4730 let optgroups =
4731   let h = Hashtbl.create 13 in
4732   List.iter (
4733     fun (name, _, _, flags, _, _, _) ->
4734       List.iter (
4735         function
4736         | Optional group ->
4737             let names = try Hashtbl.find h group with Not_found -> [] in
4738             Hashtbl.replace h group (name :: names)
4739         | _ -> ()
4740       ) flags
4741   ) daemon_functions;
4742   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4743   let groups =
4744     List.map (
4745       fun group -> group, List.sort compare (Hashtbl.find h group)
4746     ) groups in
4747   List.sort (fun x y -> compare (fst x) (fst y)) groups
4748
4749 (* Check function names etc. for consistency. *)
4750 let check_functions () =
4751   let contains_uppercase str =
4752     let len = String.length str in
4753     let rec loop i =
4754       if i >= len then false
4755       else (
4756         let c = str.[i] in
4757         if c >= 'A' && c <= 'Z' then true
4758         else loop (i+1)
4759       )
4760     in
4761     loop 0
4762   in
4763
4764   (* Check function names. *)
4765   List.iter (
4766     fun (name, _, _, _, _, _, _) ->
4767       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4768         failwithf "function name %s does not need 'guestfs' prefix" name;
4769       if name = "" then
4770         failwithf "function name is empty";
4771       if name.[0] < 'a' || name.[0] > 'z' then
4772         failwithf "function name %s must start with lowercase a-z" name;
4773       if String.contains name '-' then
4774         failwithf "function name %s should not contain '-', use '_' instead."
4775           name
4776   ) all_functions;
4777
4778   (* Check function parameter/return names. *)
4779   List.iter (
4780     fun (name, style, _, _, _, _, _) ->
4781       let check_arg_ret_name n =
4782         if contains_uppercase n then
4783           failwithf "%s param/ret %s should not contain uppercase chars"
4784             name n;
4785         if String.contains n '-' || String.contains n '_' then
4786           failwithf "%s param/ret %s should not contain '-' or '_'"
4787             name n;
4788         if n = "value" then
4789           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;
4790         if n = "int" || n = "char" || n = "short" || n = "long" then
4791           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4792         if n = "i" || n = "n" then
4793           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4794         if n = "argv" || n = "args" then
4795           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4796
4797         (* List Haskell, OCaml and C keywords here.
4798          * http://www.haskell.org/haskellwiki/Keywords
4799          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4800          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4801          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4802          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4803          * Omitting _-containing words, since they're handled above.
4804          * Omitting the OCaml reserved word, "val", is ok,
4805          * and saves us from renaming several parameters.
4806          *)
4807         let reserved = [
4808           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4809           "char"; "class"; "const"; "constraint"; "continue"; "data";
4810           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4811           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4812           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4813           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4814           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4815           "interface";
4816           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4817           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4818           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4819           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4820           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4821           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4822           "volatile"; "when"; "where"; "while";
4823           ] in
4824         if List.mem n reserved then
4825           failwithf "%s has param/ret using reserved word %s" name n;
4826       in
4827
4828       (match fst style with
4829        | RErr -> ()
4830        | RInt n | RInt64 n | RBool n
4831        | RConstString n | RConstOptString n | RString n
4832        | RStringList n | RStruct (n, _) | RStructList (n, _)
4833        | RHashtable n | RBufferOut n ->
4834            check_arg_ret_name n
4835       );
4836       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4837   ) all_functions;
4838
4839   (* Check short descriptions. *)
4840   List.iter (
4841     fun (name, _, _, _, _, shortdesc, _) ->
4842       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4843         failwithf "short description of %s should begin with lowercase." name;
4844       let c = shortdesc.[String.length shortdesc-1] in
4845       if c = '\n' || c = '.' then
4846         failwithf "short description of %s should not end with . or \\n." name
4847   ) all_functions;
4848
4849   (* Check long dscriptions. *)
4850   List.iter (
4851     fun (name, _, _, _, _, _, longdesc) ->
4852       if longdesc.[String.length longdesc-1] = '\n' then
4853         failwithf "long description of %s should not end with \\n." name
4854   ) all_functions;
4855
4856   (* Check proc_nrs. *)
4857   List.iter (
4858     fun (name, _, proc_nr, _, _, _, _) ->
4859       if proc_nr <= 0 then
4860         failwithf "daemon function %s should have proc_nr > 0" name
4861   ) daemon_functions;
4862
4863   List.iter (
4864     fun (name, _, proc_nr, _, _, _, _) ->
4865       if proc_nr <> -1 then
4866         failwithf "non-daemon function %s should have proc_nr -1" name
4867   ) non_daemon_functions;
4868
4869   let proc_nrs =
4870     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4871       daemon_functions in
4872   let proc_nrs =
4873     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4874   let rec loop = function
4875     | [] -> ()
4876     | [_] -> ()
4877     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4878         loop rest
4879     | (name1,nr1) :: (name2,nr2) :: _ ->
4880         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4881           name1 name2 nr1 nr2
4882   in
4883   loop proc_nrs;
4884
4885   (* Check tests. *)
4886   List.iter (
4887     function
4888       (* Ignore functions that have no tests.  We generate a
4889        * warning when the user does 'make check' instead.
4890        *)
4891     | name, _, _, _, [], _, _ -> ()
4892     | name, _, _, _, tests, _, _ ->
4893         let funcs =
4894           List.map (
4895             fun (_, _, test) ->
4896               match seq_of_test test with
4897               | [] ->
4898                   failwithf "%s has a test containing an empty sequence" name
4899               | cmds -> List.map List.hd cmds
4900           ) tests in
4901         let funcs = List.flatten funcs in
4902
4903         let tested = List.mem name funcs in
4904
4905         if not tested then
4906           failwithf "function %s has tests but does not test itself" name
4907   ) all_functions
4908
4909 (* 'pr' prints to the current output file. *)
4910 let chan = ref Pervasives.stdout
4911 let lines = ref 0
4912 let pr fs =
4913   ksprintf
4914     (fun str ->
4915        let i = count_chars '\n' str in
4916        lines := !lines + i;
4917        output_string !chan str
4918     ) fs
4919
4920 let copyright_years =
4921   let this_year = 1900 + (localtime (time ())).tm_year in
4922   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4923
4924 (* Generate a header block in a number of standard styles. *)
4925 type comment_style =
4926     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4927 type license = GPLv2plus | LGPLv2plus
4928
4929 let generate_header ?(extra_inputs = []) comment license =
4930   let inputs = "src/generator.ml" :: extra_inputs in
4931   let c = match comment with
4932     | CStyle ->         pr "/* "; " *"
4933     | CPlusPlusStyle -> pr "// "; "//"
4934     | HashStyle ->      pr "# ";  "#"
4935     | OCamlStyle ->     pr "(* "; " *"
4936     | HaskellStyle ->   pr "{- "; "  " in
4937   pr "libguestfs generated file\n";
4938   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4939   List.iter (pr "%s   %s\n" c) inputs;
4940   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4941   pr "%s\n" c;
4942   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4943   pr "%s\n" c;
4944   (match license with
4945    | GPLv2plus ->
4946        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4947        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4948        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4949        pr "%s (at your option) any later version.\n" c;
4950        pr "%s\n" c;
4951        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4952        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4953        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4954        pr "%s GNU General Public License for more details.\n" c;
4955        pr "%s\n" c;
4956        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4957        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4958        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4959
4960    | LGPLv2plus ->
4961        pr "%s This library is free software; you can redistribute it and/or\n" c;
4962        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4963        pr "%s License as published by the Free Software Foundation; either\n" c;
4964        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4965        pr "%s\n" c;
4966        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4967        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4968        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4969        pr "%s Lesser General Public License for more details.\n" c;
4970        pr "%s\n" c;
4971        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4972        pr "%s License along with this library; if not, write to the Free Software\n" c;
4973        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4974   );
4975   (match comment with
4976    | CStyle -> pr " */\n"
4977    | CPlusPlusStyle
4978    | HashStyle -> ()
4979    | OCamlStyle -> pr " *)\n"
4980    | HaskellStyle -> pr "-}\n"
4981   );
4982   pr "\n"
4983
4984 (* Start of main code generation functions below this line. *)
4985
4986 (* Generate the pod documentation for the C API. *)
4987 let rec generate_actions_pod () =
4988   List.iter (
4989     fun (shortname, style, _, flags, _, _, longdesc) ->
4990       if not (List.mem NotInDocs flags) then (
4991         let name = "guestfs_" ^ shortname in
4992         pr "=head2 %s\n\n" name;
4993         pr " ";
4994         generate_prototype ~extern:false ~handle:"handle" name style;
4995         pr "\n\n";
4996         pr "%s\n\n" longdesc;
4997         (match fst style with
4998          | RErr ->
4999              pr "This function returns 0 on success or -1 on error.\n\n"
5000          | RInt _ ->
5001              pr "On error this function returns -1.\n\n"
5002          | RInt64 _ ->
5003              pr "On error this function returns -1.\n\n"
5004          | RBool _ ->
5005              pr "This function returns a C truth value on success or -1 on error.\n\n"
5006          | RConstString _ ->
5007              pr "This function returns a string, or NULL on error.
5008 The string is owned by the guest handle and must I<not> be freed.\n\n"
5009          | RConstOptString _ ->
5010              pr "This function returns a string which may be NULL.
5011 There is way to return an error from this function.
5012 The string is owned by the guest handle and must I<not> be freed.\n\n"
5013          | RString _ ->
5014              pr "This function returns a string, or NULL on error.
5015 I<The caller must free the returned string after use>.\n\n"
5016          | RStringList _ ->
5017              pr "This function returns a NULL-terminated array of strings
5018 (like L<environ(3)>), or NULL if there was an error.
5019 I<The caller must free the strings and the array after use>.\n\n"
5020          | RStruct (_, typ) ->
5021              pr "This function returns a C<struct guestfs_%s *>,
5022 or NULL if there was an error.
5023 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5024          | RStructList (_, typ) ->
5025              pr "This function returns a C<struct guestfs_%s_list *>
5026 (see E<lt>guestfs-structs.hE<gt>),
5027 or NULL if there was an error.
5028 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5029          | RHashtable _ ->
5030              pr "This function returns a NULL-terminated array of
5031 strings, or NULL if there was an error.
5032 The array of strings will always have length C<2n+1>, where
5033 C<n> keys and values alternate, followed by the trailing NULL entry.
5034 I<The caller must free the strings and the array after use>.\n\n"
5035          | RBufferOut _ ->
5036              pr "This function returns a buffer, or NULL on error.
5037 The size of the returned buffer is written to C<*size_r>.
5038 I<The caller must free the returned buffer after use>.\n\n"
5039         );
5040         if List.mem ProtocolLimitWarning flags then
5041           pr "%s\n\n" protocol_limit_warning;
5042         if List.mem DangerWillRobinson flags then
5043           pr "%s\n\n" danger_will_robinson;
5044         match deprecation_notice flags with
5045         | None -> ()
5046         | Some txt -> pr "%s\n\n" txt
5047       )
5048   ) all_functions_sorted
5049
5050 and generate_structs_pod () =
5051   (* Structs documentation. *)
5052   List.iter (
5053     fun (typ, cols) ->
5054       pr "=head2 guestfs_%s\n" typ;
5055       pr "\n";
5056       pr " struct guestfs_%s {\n" typ;
5057       List.iter (
5058         function
5059         | name, FChar -> pr "   char %s;\n" name
5060         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5061         | name, FInt32 -> pr "   int32_t %s;\n" name
5062         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5063         | name, FInt64 -> pr "   int64_t %s;\n" name
5064         | name, FString -> pr "   char *%s;\n" name
5065         | name, FBuffer ->
5066             pr "   /* The next two fields describe a byte array. */\n";
5067             pr "   uint32_t %s_len;\n" name;
5068             pr "   char *%s;\n" name
5069         | name, FUUID ->
5070             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5071             pr "   char %s[32];\n" name
5072         | name, FOptPercent ->
5073             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5074             pr "   float %s;\n" name
5075       ) cols;
5076       pr " };\n";
5077       pr " \n";
5078       pr " struct guestfs_%s_list {\n" typ;
5079       pr "   uint32_t len; /* Number of elements in list. */\n";
5080       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5081       pr " };\n";
5082       pr " \n";
5083       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5084       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5085         typ typ;
5086       pr "\n"
5087   ) structs
5088
5089 and generate_availability_pod () =
5090   (* Availability documentation. *)
5091   pr "=over 4\n";
5092   pr "\n";
5093   List.iter (
5094     fun (group, functions) ->
5095       pr "=item B<%s>\n" group;
5096       pr "\n";
5097       pr "The following functions:\n";
5098       List.iter (pr "L</guestfs_%s>\n") functions;
5099       pr "\n"
5100   ) optgroups;
5101   pr "=back\n";
5102   pr "\n"
5103
5104 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5105  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5106  *
5107  * We have to use an underscore instead of a dash because otherwise
5108  * rpcgen generates incorrect code.
5109  *
5110  * This header is NOT exported to clients, but see also generate_structs_h.
5111  *)
5112 and generate_xdr () =
5113   generate_header CStyle LGPLv2plus;
5114
5115   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5116   pr "typedef string str<>;\n";
5117   pr "\n";
5118
5119   (* Internal structures. *)
5120   List.iter (
5121     function
5122     | typ, cols ->
5123         pr "struct guestfs_int_%s {\n" typ;
5124         List.iter (function
5125                    | name, FChar -> pr "  char %s;\n" name
5126                    | name, FString -> pr "  string %s<>;\n" name
5127                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5128                    | name, FUUID -> pr "  opaque %s[32];\n" name
5129                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5130                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5131                    | name, FOptPercent -> pr "  float %s;\n" name
5132                   ) cols;
5133         pr "};\n";
5134         pr "\n";
5135         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5136         pr "\n";
5137   ) structs;
5138
5139   List.iter (
5140     fun (shortname, style, _, _, _, _, _) ->
5141       let name = "guestfs_" ^ shortname in
5142
5143       (match snd style with
5144        | [] -> ()
5145        | args ->
5146            pr "struct %s_args {\n" name;
5147            List.iter (
5148              function
5149              | Pathname n | Device n | Dev_or_Path n | String n ->
5150                  pr "  string %s<>;\n" n
5151              | OptString n -> pr "  str *%s;\n" n
5152              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5153              | Bool n -> pr "  bool %s;\n" n
5154              | Int n -> pr "  int %s;\n" n
5155              | Int64 n -> pr "  hyper %s;\n" n
5156              | FileIn _ | FileOut _ -> ()
5157            ) args;
5158            pr "};\n\n"
5159       );
5160       (match fst style with
5161        | RErr -> ()
5162        | RInt n ->
5163            pr "struct %s_ret {\n" name;
5164            pr "  int %s;\n" n;
5165            pr "};\n\n"
5166        | RInt64 n ->
5167            pr "struct %s_ret {\n" name;
5168            pr "  hyper %s;\n" n;
5169            pr "};\n\n"
5170        | RBool n ->
5171            pr "struct %s_ret {\n" name;
5172            pr "  bool %s;\n" n;
5173            pr "};\n\n"
5174        | RConstString _ | RConstOptString _ ->
5175            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5176        | RString n ->
5177            pr "struct %s_ret {\n" name;
5178            pr "  string %s<>;\n" n;
5179            pr "};\n\n"
5180        | RStringList n ->
5181            pr "struct %s_ret {\n" name;
5182            pr "  str %s<>;\n" n;
5183            pr "};\n\n"
5184        | RStruct (n, typ) ->
5185            pr "struct %s_ret {\n" name;
5186            pr "  guestfs_int_%s %s;\n" typ n;
5187            pr "};\n\n"
5188        | RStructList (n, typ) ->
5189            pr "struct %s_ret {\n" name;
5190            pr "  guestfs_int_%s_list %s;\n" typ n;
5191            pr "};\n\n"
5192        | RHashtable n ->
5193            pr "struct %s_ret {\n" name;
5194            pr "  str %s<>;\n" n;
5195            pr "};\n\n"
5196        | RBufferOut n ->
5197            pr "struct %s_ret {\n" name;
5198            pr "  opaque %s<>;\n" n;
5199            pr "};\n\n"
5200       );
5201   ) daemon_functions;
5202
5203   (* Table of procedure numbers. *)
5204   pr "enum guestfs_procedure {\n";
5205   List.iter (
5206     fun (shortname, _, proc_nr, _, _, _, _) ->
5207       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5208   ) daemon_functions;
5209   pr "  GUESTFS_PROC_NR_PROCS\n";
5210   pr "};\n";
5211   pr "\n";
5212
5213   (* Having to choose a maximum message size is annoying for several
5214    * reasons (it limits what we can do in the API), but it (a) makes
5215    * the protocol a lot simpler, and (b) provides a bound on the size
5216    * of the daemon which operates in limited memory space.  For large
5217    * file transfers you should use FTP.
5218    *)
5219   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5220   pr "\n";
5221
5222   (* Message header, etc. *)
5223   pr "\
5224 /* The communication protocol is now documented in the guestfs(3)
5225  * manpage.
5226  */
5227
5228 const GUESTFS_PROGRAM = 0x2000F5F5;
5229 const GUESTFS_PROTOCOL_VERSION = 1;
5230
5231 /* These constants must be larger than any possible message length. */
5232 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5233 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5234
5235 enum guestfs_message_direction {
5236   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5237   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5238 };
5239
5240 enum guestfs_message_status {
5241   GUESTFS_STATUS_OK = 0,
5242   GUESTFS_STATUS_ERROR = 1
5243 };
5244
5245 const GUESTFS_ERROR_LEN = 256;
5246
5247 struct guestfs_message_error {
5248   string error_message<GUESTFS_ERROR_LEN>;
5249 };
5250
5251 struct guestfs_message_header {
5252   unsigned prog;                     /* GUESTFS_PROGRAM */
5253   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5254   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5255   guestfs_message_direction direction;
5256   unsigned serial;                   /* message serial number */
5257   guestfs_message_status status;
5258 };
5259
5260 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5261
5262 struct guestfs_chunk {
5263   int cancel;                        /* if non-zero, transfer is cancelled */
5264   /* data size is 0 bytes if the transfer has finished successfully */
5265   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5266 };
5267 "
5268
5269 (* Generate the guestfs-structs.h file. *)
5270 and generate_structs_h () =
5271   generate_header CStyle LGPLv2plus;
5272
5273   (* This is a public exported header file containing various
5274    * structures.  The structures are carefully written to have
5275    * exactly the same in-memory format as the XDR structures that
5276    * we use on the wire to the daemon.  The reason for creating
5277    * copies of these structures here is just so we don't have to
5278    * export the whole of guestfs_protocol.h (which includes much
5279    * unrelated and XDR-dependent stuff that we don't want to be
5280    * public, or required by clients).
5281    *
5282    * To reiterate, we will pass these structures to and from the
5283    * client with a simple assignment or memcpy, so the format
5284    * must be identical to what rpcgen / the RFC defines.
5285    *)
5286
5287   (* Public structures. *)
5288   List.iter (
5289     fun (typ, cols) ->
5290       pr "struct guestfs_%s {\n" typ;
5291       List.iter (
5292         function
5293         | name, FChar -> pr "  char %s;\n" name
5294         | name, FString -> pr "  char *%s;\n" name
5295         | name, FBuffer ->
5296             pr "  uint32_t %s_len;\n" name;
5297             pr "  char *%s;\n" name
5298         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5299         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5300         | name, FInt32 -> pr "  int32_t %s;\n" name
5301         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5302         | name, FInt64 -> pr "  int64_t %s;\n" name
5303         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5304       ) cols;
5305       pr "};\n";
5306       pr "\n";
5307       pr "struct guestfs_%s_list {\n" typ;
5308       pr "  uint32_t len;\n";
5309       pr "  struct guestfs_%s *val;\n" typ;
5310       pr "};\n";
5311       pr "\n";
5312       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5313       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5314       pr "\n"
5315   ) structs
5316
5317 (* Generate the guestfs-actions.h file. *)
5318 and generate_actions_h () =
5319   generate_header CStyle LGPLv2plus;
5320   List.iter (
5321     fun (shortname, style, _, _, _, _, _) ->
5322       let name = "guestfs_" ^ shortname in
5323       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5324         name style
5325   ) all_functions
5326
5327 (* Generate the guestfs-internal-actions.h file. *)
5328 and generate_internal_actions_h () =
5329   generate_header CStyle LGPLv2plus;
5330   List.iter (
5331     fun (shortname, style, _, _, _, _, _) ->
5332       let name = "guestfs__" ^ shortname in
5333       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5334         name style
5335   ) non_daemon_functions
5336
5337 (* Generate the client-side dispatch stubs. *)
5338 and generate_client_actions () =
5339   generate_header CStyle LGPLv2plus;
5340
5341   pr "\
5342 #include <stdio.h>
5343 #include <stdlib.h>
5344 #include <stdint.h>
5345 #include <inttypes.h>
5346
5347 #include \"guestfs.h\"
5348 #include \"guestfs-internal.h\"
5349 #include \"guestfs-internal-actions.h\"
5350 #include \"guestfs_protocol.h\"
5351
5352 #define error guestfs_error
5353 //#define perrorf guestfs_perrorf
5354 #define safe_malloc guestfs_safe_malloc
5355 #define safe_realloc guestfs_safe_realloc
5356 //#define safe_strdup guestfs_safe_strdup
5357 #define safe_memdup guestfs_safe_memdup
5358
5359 /* Check the return message from a call for validity. */
5360 static int
5361 check_reply_header (guestfs_h *g,
5362                     const struct guestfs_message_header *hdr,
5363                     unsigned int proc_nr, unsigned int serial)
5364 {
5365   if (hdr->prog != GUESTFS_PROGRAM) {
5366     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5367     return -1;
5368   }
5369   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5370     error (g, \"wrong protocol version (%%d/%%d)\",
5371            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5372     return -1;
5373   }
5374   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5375     error (g, \"unexpected message direction (%%d/%%d)\",
5376            hdr->direction, GUESTFS_DIRECTION_REPLY);
5377     return -1;
5378   }
5379   if (hdr->proc != proc_nr) {
5380     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5381     return -1;
5382   }
5383   if (hdr->serial != serial) {
5384     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5385     return -1;
5386   }
5387
5388   return 0;
5389 }
5390
5391 /* Check we are in the right state to run a high-level action. */
5392 static int
5393 check_state (guestfs_h *g, const char *caller)
5394 {
5395   if (!guestfs__is_ready (g)) {
5396     if (guestfs__is_config (g) || guestfs__is_launching (g))
5397       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5398         caller);
5399     else
5400       error (g, \"%%s called from the wrong state, %%d != READY\",
5401         caller, guestfs__get_state (g));
5402     return -1;
5403   }
5404   return 0;
5405 }
5406
5407 ";
5408
5409   (* Generate code to generate guestfish call traces. *)
5410   let trace_call shortname style =
5411     pr "  if (guestfs__get_trace (g)) {\n";
5412
5413     let needs_i =
5414       List.exists (function
5415                    | StringList _ | DeviceList _ -> true
5416                    | _ -> false) (snd style) in
5417     if needs_i then (
5418       pr "    int i;\n";
5419       pr "\n"
5420     );
5421
5422     pr "    printf (\"%s\");\n" shortname;
5423     List.iter (
5424       function
5425       | String n                        (* strings *)
5426       | Device n
5427       | Pathname n
5428       | Dev_or_Path n
5429       | FileIn n
5430       | FileOut n ->
5431           (* guestfish doesn't support string escaping, so neither do we *)
5432           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5433       | OptString n ->                  (* string option *)
5434           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5435           pr "    else printf (\" null\");\n"
5436       | StringList n
5437       | DeviceList n ->                 (* string list *)
5438           pr "    putchar (' ');\n";
5439           pr "    putchar ('\"');\n";
5440           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5441           pr "      if (i > 0) putchar (' ');\n";
5442           pr "      fputs (%s[i], stdout);\n" n;
5443           pr "    }\n";
5444           pr "    putchar ('\"');\n";
5445       | Bool n ->                       (* boolean *)
5446           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5447       | Int n ->                        (* int *)
5448           pr "    printf (\" %%d\", %s);\n" n
5449       | Int64 n ->
5450           pr "    printf (\" %%\" PRIi64, %s);\n" n
5451     ) (snd style);
5452     pr "    putchar ('\\n');\n";
5453     pr "  }\n";
5454     pr "\n";
5455   in
5456
5457   (* For non-daemon functions, generate a wrapper around each function. *)
5458   List.iter (
5459     fun (shortname, style, _, _, _, _, _) ->
5460       let name = "guestfs_" ^ shortname in
5461
5462       generate_prototype ~extern:false ~semicolon:false ~newline:true
5463         ~handle:"g" name style;
5464       pr "{\n";
5465       trace_call shortname style;
5466       pr "  return guestfs__%s " shortname;
5467       generate_c_call_args ~handle:"g" style;
5468       pr ";\n";
5469       pr "}\n";
5470       pr "\n"
5471   ) non_daemon_functions;
5472
5473   (* Client-side stubs for each function. *)
5474   List.iter (
5475     fun (shortname, style, _, _, _, _, _) ->
5476       let name = "guestfs_" ^ shortname in
5477
5478       (* Generate the action stub. *)
5479       generate_prototype ~extern:false ~semicolon:false ~newline:true
5480         ~handle:"g" name style;
5481
5482       let error_code =
5483         match fst style with
5484         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5485         | RConstString _ | RConstOptString _ ->
5486             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5487         | RString _ | RStringList _
5488         | RStruct _ | RStructList _
5489         | RHashtable _ | RBufferOut _ ->
5490             "NULL" in
5491
5492       pr "{\n";
5493
5494       (match snd style with
5495        | [] -> ()
5496        | _ -> pr "  struct %s_args args;\n" name
5497       );
5498
5499       pr "  guestfs_message_header hdr;\n";
5500       pr "  guestfs_message_error err;\n";
5501       let has_ret =
5502         match fst style with
5503         | RErr -> false
5504         | RConstString _ | RConstOptString _ ->
5505             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5506         | RInt _ | RInt64 _
5507         | RBool _ | RString _ | RStringList _
5508         | RStruct _ | RStructList _
5509         | RHashtable _ | RBufferOut _ ->
5510             pr "  struct %s_ret ret;\n" name;
5511             true in
5512
5513       pr "  int serial;\n";
5514       pr "  int r;\n";
5515       pr "\n";
5516       trace_call shortname style;
5517       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5518       pr "  guestfs___set_busy (g);\n";
5519       pr "\n";
5520
5521       (* Send the main header and arguments. *)
5522       (match snd style with
5523        | [] ->
5524            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5525              (String.uppercase shortname)
5526        | args ->
5527            List.iter (
5528              function
5529              | Pathname n | Device n | Dev_or_Path n | String n ->
5530                  pr "  args.%s = (char *) %s;\n" n n
5531              | OptString n ->
5532                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5533              | StringList n | DeviceList n ->
5534                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5535                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5536              | Bool n ->
5537                  pr "  args.%s = %s;\n" n n
5538              | Int n ->
5539                  pr "  args.%s = %s;\n" n n
5540              | Int64 n ->
5541                  pr "  args.%s = %s;\n" n n
5542              | FileIn _ | FileOut _ -> ()
5543            ) args;
5544            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5545              (String.uppercase shortname);
5546            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5547              name;
5548       );
5549       pr "  if (serial == -1) {\n";
5550       pr "    guestfs___end_busy (g);\n";
5551       pr "    return %s;\n" error_code;
5552       pr "  }\n";
5553       pr "\n";
5554
5555       (* Send any additional files (FileIn) requested. *)
5556       let need_read_reply_label = ref false in
5557       List.iter (
5558         function
5559         | FileIn n ->
5560             pr "  r = guestfs___send_file (g, %s);\n" n;
5561             pr "  if (r == -1) {\n";
5562             pr "    guestfs___end_busy (g);\n";
5563             pr "    return %s;\n" error_code;
5564             pr "  }\n";
5565             pr "  if (r == -2) /* daemon cancelled */\n";
5566             pr "    goto read_reply;\n";
5567             need_read_reply_label := true;
5568             pr "\n";
5569         | _ -> ()
5570       ) (snd style);
5571
5572       (* Wait for the reply from the remote end. *)
5573       if !need_read_reply_label then pr " read_reply:\n";
5574       pr "  memset (&hdr, 0, sizeof hdr);\n";
5575       pr "  memset (&err, 0, sizeof err);\n";
5576       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5577       pr "\n";
5578       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5579       if not has_ret then
5580         pr "NULL, NULL"
5581       else
5582         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5583       pr ");\n";
5584
5585       pr "  if (r == -1) {\n";
5586       pr "    guestfs___end_busy (g);\n";
5587       pr "    return %s;\n" error_code;
5588       pr "  }\n";
5589       pr "\n";
5590
5591       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5592         (String.uppercase shortname);
5593       pr "    guestfs___end_busy (g);\n";
5594       pr "    return %s;\n" error_code;
5595       pr "  }\n";
5596       pr "\n";
5597
5598       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5599       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5600       pr "    free (err.error_message);\n";
5601       pr "    guestfs___end_busy (g);\n";
5602       pr "    return %s;\n" error_code;
5603       pr "  }\n";
5604       pr "\n";
5605
5606       (* Expecting to receive further files (FileOut)? *)
5607       List.iter (
5608         function
5609         | FileOut n ->
5610             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5611             pr "    guestfs___end_busy (g);\n";
5612             pr "    return %s;\n" error_code;
5613             pr "  }\n";
5614             pr "\n";
5615         | _ -> ()
5616       ) (snd style);
5617
5618       pr "  guestfs___end_busy (g);\n";
5619
5620       (match fst style with
5621        | RErr -> pr "  return 0;\n"
5622        | RInt n | RInt64 n | RBool n ->
5623            pr "  return ret.%s;\n" n
5624        | RConstString _ | RConstOptString _ ->
5625            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5626        | RString n ->
5627            pr "  return ret.%s; /* caller will free */\n" n
5628        | RStringList n | RHashtable n ->
5629            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5630            pr "  ret.%s.%s_val =\n" n n;
5631            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5632            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5633              n n;
5634            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5635            pr "  return ret.%s.%s_val;\n" n n
5636        | RStruct (n, _) ->
5637            pr "  /* caller will free this */\n";
5638            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5639        | RStructList (n, _) ->
5640            pr "  /* caller will free this */\n";
5641            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5642        | RBufferOut n ->
5643            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5644            pr "   * _val might be NULL here.  To make the API saner for\n";
5645            pr "   * callers, we turn this case into a unique pointer (using\n";
5646            pr "   * malloc(1)).\n";
5647            pr "   */\n";
5648            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5649            pr "    *size_r = ret.%s.%s_len;\n" n n;
5650            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5651            pr "  } else {\n";
5652            pr "    free (ret.%s.%s_val);\n" n n;
5653            pr "    char *p = safe_malloc (g, 1);\n";
5654            pr "    *size_r = ret.%s.%s_len;\n" n n;
5655            pr "    return p;\n";
5656            pr "  }\n";
5657       );
5658
5659       pr "}\n\n"
5660   ) daemon_functions;
5661
5662   (* Functions to free structures. *)
5663   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5664   pr " * structure format is identical to the XDR format.  See note in\n";
5665   pr " * generator.ml.\n";
5666   pr " */\n";
5667   pr "\n";
5668
5669   List.iter (
5670     fun (typ, _) ->
5671       pr "void\n";
5672       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5673       pr "{\n";
5674       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5675       pr "  free (x);\n";
5676       pr "}\n";
5677       pr "\n";
5678
5679       pr "void\n";
5680       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5681       pr "{\n";
5682       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5683       pr "  free (x);\n";
5684       pr "}\n";
5685       pr "\n";
5686
5687   ) structs;
5688
5689 (* Generate daemon/actions.h. *)
5690 and generate_daemon_actions_h () =
5691   generate_header CStyle GPLv2plus;
5692
5693   pr "#include \"../src/guestfs_protocol.h\"\n";
5694   pr "\n";
5695
5696   List.iter (
5697     fun (name, style, _, _, _, _, _) ->
5698       generate_prototype
5699         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5700         name style;
5701   ) daemon_functions
5702
5703 (* Generate the linker script which controls the visibility of
5704  * symbols in the public ABI and ensures no other symbols get
5705  * exported accidentally.
5706  *)
5707 and generate_linker_script () =
5708   generate_header HashStyle GPLv2plus;
5709
5710   let globals = [
5711     "guestfs_create";
5712     "guestfs_close";
5713     "guestfs_get_error_handler";
5714     "guestfs_get_out_of_memory_handler";
5715     "guestfs_last_error";
5716     "guestfs_set_error_handler";
5717     "guestfs_set_launch_done_callback";
5718     "guestfs_set_log_message_callback";
5719     "guestfs_set_out_of_memory_handler";
5720     "guestfs_set_subprocess_quit_callback";
5721
5722     (* Unofficial parts of the API: the bindings code use these
5723      * functions, so it is useful to export them.
5724      *)
5725     "guestfs_safe_calloc";
5726     "guestfs_safe_malloc";
5727   ] in
5728   let functions =
5729     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5730       all_functions in
5731   let structs =
5732     List.concat (
5733       List.map (fun (typ, _) ->
5734                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5735         structs
5736     ) in
5737   let globals = List.sort compare (globals @ functions @ structs) in
5738
5739   pr "{\n";
5740   pr "    global:\n";
5741   List.iter (pr "        %s;\n") globals;
5742   pr "\n";
5743
5744   pr "    local:\n";
5745   pr "        *;\n";
5746   pr "};\n"
5747
5748 (* Generate the server-side stubs. *)
5749 and generate_daemon_actions () =
5750   generate_header CStyle GPLv2plus;
5751
5752   pr "#include <config.h>\n";
5753   pr "\n";
5754   pr "#include <stdio.h>\n";
5755   pr "#include <stdlib.h>\n";
5756   pr "#include <string.h>\n";
5757   pr "#include <inttypes.h>\n";
5758   pr "#include <rpc/types.h>\n";
5759   pr "#include <rpc/xdr.h>\n";
5760   pr "\n";
5761   pr "#include \"daemon.h\"\n";
5762   pr "#include \"c-ctype.h\"\n";
5763   pr "#include \"../src/guestfs_protocol.h\"\n";
5764   pr "#include \"actions.h\"\n";
5765   pr "\n";
5766
5767   List.iter (
5768     fun (name, style, _, _, _, _, _) ->
5769       (* Generate server-side stubs. *)
5770       pr "static void %s_stub (XDR *xdr_in)\n" name;
5771       pr "{\n";
5772       let error_code =
5773         match fst style with
5774         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5775         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5776         | RBool _ -> pr "  int r;\n"; "-1"
5777         | RConstString _ | RConstOptString _ ->
5778             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5779         | RString _ -> pr "  char *r;\n"; "NULL"
5780         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5781         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5782         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5783         | RBufferOut _ ->
5784             pr "  size_t size = 1;\n";
5785             pr "  char *r;\n";
5786             "NULL" in
5787
5788       (match snd style with
5789        | [] -> ()
5790        | args ->
5791            pr "  struct guestfs_%s_args args;\n" name;
5792            List.iter (
5793              function
5794              | Device n | Dev_or_Path n
5795              | Pathname n
5796              | String n -> ()
5797              | OptString n -> pr "  char *%s;\n" n
5798              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5799              | Bool n -> pr "  int %s;\n" n
5800              | Int n -> pr "  int %s;\n" n
5801              | Int64 n -> pr "  int64_t %s;\n" n
5802              | FileIn _ | FileOut _ -> ()
5803            ) args
5804       );
5805       pr "\n";
5806
5807       (match snd style with
5808        | [] -> ()
5809        | args ->
5810            pr "  memset (&args, 0, sizeof args);\n";
5811            pr "\n";
5812            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5813            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5814            pr "    return;\n";
5815            pr "  }\n";
5816            let pr_args n =
5817              pr "  char *%s = args.%s;\n" n n
5818            in
5819            let pr_list_handling_code n =
5820              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5821              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5822              pr "  if (%s == NULL) {\n" n;
5823              pr "    reply_with_perror (\"realloc\");\n";
5824              pr "    goto done;\n";
5825              pr "  }\n";
5826              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5827              pr "  args.%s.%s_val = %s;\n" n n n;
5828            in
5829            List.iter (
5830              function
5831              | Pathname n ->
5832                  pr_args n;
5833                  pr "  ABS_PATH (%s, goto done);\n" n;
5834              | Device n ->
5835                  pr_args n;
5836                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5837              | Dev_or_Path n ->
5838                  pr_args n;
5839                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5840              | String n -> pr_args n
5841              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5842              | StringList n ->
5843                  pr_list_handling_code n;
5844              | DeviceList n ->
5845                  pr_list_handling_code n;
5846                  pr "  /* Ensure that each is a device,\n";
5847                  pr "   * and perform device name translation. */\n";
5848                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5849                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5850                  pr "  }\n";
5851              | Bool n -> pr "  %s = args.%s;\n" n n
5852              | Int n -> pr "  %s = args.%s;\n" n n
5853              | Int64 n -> pr "  %s = args.%s;\n" n n
5854              | FileIn _ | FileOut _ -> ()
5855            ) args;
5856            pr "\n"
5857       );
5858
5859
5860       (* this is used at least for do_equal *)
5861       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5862         (* Emit NEED_ROOT just once, even when there are two or
5863            more Pathname args *)
5864         pr "  NEED_ROOT (goto done);\n";
5865       );
5866
5867       (* Don't want to call the impl with any FileIn or FileOut
5868        * parameters, since these go "outside" the RPC protocol.
5869        *)
5870       let args' =
5871         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5872           (snd style) in
5873       pr "  r = do_%s " name;
5874       generate_c_call_args (fst style, args');
5875       pr ";\n";
5876
5877       (match fst style with
5878        | RErr | RInt _ | RInt64 _ | RBool _
5879        | RConstString _ | RConstOptString _
5880        | RString _ | RStringList _ | RHashtable _
5881        | RStruct (_, _) | RStructList (_, _) ->
5882            pr "  if (r == %s)\n" error_code;
5883            pr "    /* do_%s has already called reply_with_error */\n" name;
5884            pr "    goto done;\n";
5885            pr "\n"
5886        | RBufferOut _ ->
5887            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5888            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5889            pr "   */\n";
5890            pr "  if (size == 1 && r == %s)\n" error_code;
5891            pr "    /* do_%s has already called reply_with_error */\n" name;
5892            pr "    goto done;\n";
5893            pr "\n"
5894       );
5895
5896       (* If there are any FileOut parameters, then the impl must
5897        * send its own reply.
5898        *)
5899       let no_reply =
5900         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5901       if no_reply then
5902         pr "  /* do_%s has already sent a reply */\n" name
5903       else (
5904         match fst style with
5905         | RErr -> pr "  reply (NULL, NULL);\n"
5906         | RInt n | RInt64 n | RBool n ->
5907             pr "  struct guestfs_%s_ret ret;\n" name;
5908             pr "  ret.%s = r;\n" n;
5909             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5910               name
5911         | RConstString _ | RConstOptString _ ->
5912             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5913         | RString n ->
5914             pr "  struct guestfs_%s_ret ret;\n" name;
5915             pr "  ret.%s = r;\n" n;
5916             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5917               name;
5918             pr "  free (r);\n"
5919         | RStringList n | RHashtable n ->
5920             pr "  struct guestfs_%s_ret ret;\n" name;
5921             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5922             pr "  ret.%s.%s_val = r;\n" n n;
5923             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5924               name;
5925             pr "  free_strings (r);\n"
5926         | RStruct (n, _) ->
5927             pr "  struct guestfs_%s_ret ret;\n" name;
5928             pr "  ret.%s = *r;\n" n;
5929             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5930               name;
5931             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5932               name
5933         | RStructList (n, _) ->
5934             pr "  struct guestfs_%s_ret ret;\n" name;
5935             pr "  ret.%s = *r;\n" n;
5936             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5937               name;
5938             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5939               name
5940         | RBufferOut n ->
5941             pr "  struct guestfs_%s_ret ret;\n" name;
5942             pr "  ret.%s.%s_val = r;\n" n n;
5943             pr "  ret.%s.%s_len = size;\n" n n;
5944             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5945               name;
5946             pr "  free (r);\n"
5947       );
5948
5949       (* Free the args. *)
5950       (match snd style with
5951        | [] ->
5952            pr "done: ;\n";
5953        | _ ->
5954            pr "done:\n";
5955            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5956              name
5957       );
5958
5959       pr "}\n\n";
5960   ) daemon_functions;
5961
5962   (* Dispatch function. *)
5963   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5964   pr "{\n";
5965   pr "  switch (proc_nr) {\n";
5966
5967   List.iter (
5968     fun (name, style, _, _, _, _, _) ->
5969       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5970       pr "      %s_stub (xdr_in);\n" name;
5971       pr "      break;\n"
5972   ) daemon_functions;
5973
5974   pr "    default:\n";
5975   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";
5976   pr "  }\n";
5977   pr "}\n";
5978   pr "\n";
5979
5980   (* LVM columns and tokenization functions. *)
5981   (* XXX This generates crap code.  We should rethink how we
5982    * do this parsing.
5983    *)
5984   List.iter (
5985     function
5986     | typ, cols ->
5987         pr "static const char *lvm_%s_cols = \"%s\";\n"
5988           typ (String.concat "," (List.map fst cols));
5989         pr "\n";
5990
5991         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5992         pr "{\n";
5993         pr "  char *tok, *p, *next;\n";
5994         pr "  int i, j;\n";
5995         pr "\n";
5996         (*
5997           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5998           pr "\n";
5999         *)
6000         pr "  if (!str) {\n";
6001         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6002         pr "    return -1;\n";
6003         pr "  }\n";
6004         pr "  if (!*str || c_isspace (*str)) {\n";
6005         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6006         pr "    return -1;\n";
6007         pr "  }\n";
6008         pr "  tok = str;\n";
6009         List.iter (
6010           fun (name, coltype) ->
6011             pr "  if (!tok) {\n";
6012             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6013             pr "    return -1;\n";
6014             pr "  }\n";
6015             pr "  p = strchrnul (tok, ',');\n";
6016             pr "  if (*p) next = p+1; else next = NULL;\n";
6017             pr "  *p = '\\0';\n";
6018             (match coltype with
6019              | FString ->
6020                  pr "  r->%s = strdup (tok);\n" name;
6021                  pr "  if (r->%s == NULL) {\n" name;
6022                  pr "    perror (\"strdup\");\n";
6023                  pr "    return -1;\n";
6024                  pr "  }\n"
6025              | FUUID ->
6026                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6027                  pr "    if (tok[j] == '\\0') {\n";
6028                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6029                  pr "      return -1;\n";
6030                  pr "    } else if (tok[j] != '-')\n";
6031                  pr "      r->%s[i++] = tok[j];\n" name;
6032                  pr "  }\n";
6033              | FBytes ->
6034                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6035                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6036                  pr "    return -1;\n";
6037                  pr "  }\n";
6038              | FInt64 ->
6039                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6040                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6041                  pr "    return -1;\n";
6042                  pr "  }\n";
6043              | FOptPercent ->
6044                  pr "  if (tok[0] == '\\0')\n";
6045                  pr "    r->%s = -1;\n" name;
6046                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6047                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6048                  pr "    return -1;\n";
6049                  pr "  }\n";
6050              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6051                  assert false (* can never be an LVM column *)
6052             );
6053             pr "  tok = next;\n";
6054         ) cols;
6055
6056         pr "  if (tok != NULL) {\n";
6057         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6058         pr "    return -1;\n";
6059         pr "  }\n";
6060         pr "  return 0;\n";
6061         pr "}\n";
6062         pr "\n";
6063
6064         pr "guestfs_int_lvm_%s_list *\n" typ;
6065         pr "parse_command_line_%ss (void)\n" typ;
6066         pr "{\n";
6067         pr "  char *out, *err;\n";
6068         pr "  char *p, *pend;\n";
6069         pr "  int r, i;\n";
6070         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6071         pr "  void *newp;\n";
6072         pr "\n";
6073         pr "  ret = malloc (sizeof *ret);\n";
6074         pr "  if (!ret) {\n";
6075         pr "    reply_with_perror (\"malloc\");\n";
6076         pr "    return NULL;\n";
6077         pr "  }\n";
6078         pr "\n";
6079         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6080         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6081         pr "\n";
6082         pr "  r = command (&out, &err,\n";
6083         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
6084         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6085         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6086         pr "  if (r == -1) {\n";
6087         pr "    reply_with_error (\"%%s\", err);\n";
6088         pr "    free (out);\n";
6089         pr "    free (err);\n";
6090         pr "    free (ret);\n";
6091         pr "    return NULL;\n";
6092         pr "  }\n";
6093         pr "\n";
6094         pr "  free (err);\n";
6095         pr "\n";
6096         pr "  /* Tokenize each line of the output. */\n";
6097         pr "  p = out;\n";
6098         pr "  i = 0;\n";
6099         pr "  while (p) {\n";
6100         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6101         pr "    if (pend) {\n";
6102         pr "      *pend = '\\0';\n";
6103         pr "      pend++;\n";
6104         pr "    }\n";
6105         pr "\n";
6106         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6107         pr "      p++;\n";
6108         pr "\n";
6109         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6110         pr "      p = pend;\n";
6111         pr "      continue;\n";
6112         pr "    }\n";
6113         pr "\n";
6114         pr "    /* Allocate some space to store this next entry. */\n";
6115         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6116         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6117         pr "    if (newp == NULL) {\n";
6118         pr "      reply_with_perror (\"realloc\");\n";
6119         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6120         pr "      free (ret);\n";
6121         pr "      free (out);\n";
6122         pr "      return NULL;\n";
6123         pr "    }\n";
6124         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6125         pr "\n";
6126         pr "    /* Tokenize the next entry. */\n";
6127         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6128         pr "    if (r == -1) {\n";
6129         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6130         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6131         pr "      free (ret);\n";
6132         pr "      free (out);\n";
6133         pr "      return NULL;\n";
6134         pr "    }\n";
6135         pr "\n";
6136         pr "    ++i;\n";
6137         pr "    p = pend;\n";
6138         pr "  }\n";
6139         pr "\n";
6140         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6141         pr "\n";
6142         pr "  free (out);\n";
6143         pr "  return ret;\n";
6144         pr "}\n"
6145
6146   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6147
6148 (* Generate a list of function names, for debugging in the daemon.. *)
6149 and generate_daemon_names () =
6150   generate_header CStyle GPLv2plus;
6151
6152   pr "#include <config.h>\n";
6153   pr "\n";
6154   pr "#include \"daemon.h\"\n";
6155   pr "\n";
6156
6157   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6158   pr "const char *function_names[] = {\n";
6159   List.iter (
6160     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6161   ) daemon_functions;
6162   pr "};\n";
6163
6164 (* Generate the optional groups for the daemon to implement
6165  * guestfs_available.
6166  *)
6167 and generate_daemon_optgroups_c () =
6168   generate_header CStyle GPLv2plus;
6169
6170   pr "#include <config.h>\n";
6171   pr "\n";
6172   pr "#include \"daemon.h\"\n";
6173   pr "#include \"optgroups.h\"\n";
6174   pr "\n";
6175
6176   pr "struct optgroup optgroups[] = {\n";
6177   List.iter (
6178     fun (group, _) ->
6179       pr "  { \"%s\", optgroup_%s_available },\n" group group
6180   ) optgroups;
6181   pr "  { NULL, NULL }\n";
6182   pr "};\n"
6183
6184 and generate_daemon_optgroups_h () =
6185   generate_header CStyle GPLv2plus;
6186
6187   List.iter (
6188     fun (group, _) ->
6189       pr "extern int optgroup_%s_available (void);\n" group
6190   ) optgroups
6191
6192 (* Generate the tests. *)
6193 and generate_tests () =
6194   generate_header CStyle GPLv2plus;
6195
6196   pr "\
6197 #include <stdio.h>
6198 #include <stdlib.h>
6199 #include <string.h>
6200 #include <unistd.h>
6201 #include <sys/types.h>
6202 #include <fcntl.h>
6203
6204 #include \"guestfs.h\"
6205 #include \"guestfs-internal.h\"
6206
6207 static guestfs_h *g;
6208 static int suppress_error = 0;
6209
6210 static void print_error (guestfs_h *g, void *data, const char *msg)
6211 {
6212   if (!suppress_error)
6213     fprintf (stderr, \"%%s\\n\", msg);
6214 }
6215
6216 /* FIXME: nearly identical code appears in fish.c */
6217 static void print_strings (char *const *argv)
6218 {
6219   int argc;
6220
6221   for (argc = 0; argv[argc] != NULL; ++argc)
6222     printf (\"\\t%%s\\n\", argv[argc]);
6223 }
6224
6225 /*
6226 static void print_table (char const *const *argv)
6227 {
6228   int i;
6229
6230   for (i = 0; argv[i] != NULL; i += 2)
6231     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6232 }
6233 */
6234
6235 ";
6236
6237   (* Generate a list of commands which are not tested anywhere. *)
6238   pr "static void no_test_warnings (void)\n";
6239   pr "{\n";
6240
6241   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6242   List.iter (
6243     fun (_, _, _, _, tests, _, _) ->
6244       let tests = filter_map (
6245         function
6246         | (_, (Always|If _|Unless _), test) -> Some test
6247         | (_, Disabled, _) -> None
6248       ) tests in
6249       let seq = List.concat (List.map seq_of_test tests) in
6250       let cmds_tested = List.map List.hd seq in
6251       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6252   ) all_functions;
6253
6254   List.iter (
6255     fun (name, _, _, _, _, _, _) ->
6256       if not (Hashtbl.mem hash name) then
6257         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6258   ) all_functions;
6259
6260   pr "}\n";
6261   pr "\n";
6262
6263   (* Generate the actual tests.  Note that we generate the tests
6264    * in reverse order, deliberately, so that (in general) the
6265    * newest tests run first.  This makes it quicker and easier to
6266    * debug them.
6267    *)
6268   let test_names =
6269     List.map (
6270       fun (name, _, _, flags, tests, _, _) ->
6271         mapi (generate_one_test name flags) tests
6272     ) (List.rev all_functions) in
6273   let test_names = List.concat test_names in
6274   let nr_tests = List.length test_names in
6275
6276   pr "\
6277 int main (int argc, char *argv[])
6278 {
6279   char c = 0;
6280   unsigned long int n_failed = 0;
6281   const char *filename;
6282   int fd;
6283   int nr_tests, test_num = 0;
6284
6285   setbuf (stdout, NULL);
6286
6287   no_test_warnings ();
6288
6289   g = guestfs_create ();
6290   if (g == NULL) {
6291     printf (\"guestfs_create FAILED\\n\");
6292     exit (EXIT_FAILURE);
6293   }
6294
6295   guestfs_set_error_handler (g, print_error, NULL);
6296
6297   guestfs_set_path (g, \"../appliance\");
6298
6299   filename = \"test1.img\";
6300   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6301   if (fd == -1) {
6302     perror (filename);
6303     exit (EXIT_FAILURE);
6304   }
6305   if (lseek (fd, %d, SEEK_SET) == -1) {
6306     perror (\"lseek\");
6307     close (fd);
6308     unlink (filename);
6309     exit (EXIT_FAILURE);
6310   }
6311   if (write (fd, &c, 1) == -1) {
6312     perror (\"write\");
6313     close (fd);
6314     unlink (filename);
6315     exit (EXIT_FAILURE);
6316   }
6317   if (close (fd) == -1) {
6318     perror (filename);
6319     unlink (filename);
6320     exit (EXIT_FAILURE);
6321   }
6322   if (guestfs_add_drive (g, filename) == -1) {
6323     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6324     exit (EXIT_FAILURE);
6325   }
6326
6327   filename = \"test2.img\";
6328   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6329   if (fd == -1) {
6330     perror (filename);
6331     exit (EXIT_FAILURE);
6332   }
6333   if (lseek (fd, %d, SEEK_SET) == -1) {
6334     perror (\"lseek\");
6335     close (fd);
6336     unlink (filename);
6337     exit (EXIT_FAILURE);
6338   }
6339   if (write (fd, &c, 1) == -1) {
6340     perror (\"write\");
6341     close (fd);
6342     unlink (filename);
6343     exit (EXIT_FAILURE);
6344   }
6345   if (close (fd) == -1) {
6346     perror (filename);
6347     unlink (filename);
6348     exit (EXIT_FAILURE);
6349   }
6350   if (guestfs_add_drive (g, filename) == -1) {
6351     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6352     exit (EXIT_FAILURE);
6353   }
6354
6355   filename = \"test3.img\";
6356   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6357   if (fd == -1) {
6358     perror (filename);
6359     exit (EXIT_FAILURE);
6360   }
6361   if (lseek (fd, %d, SEEK_SET) == -1) {
6362     perror (\"lseek\");
6363     close (fd);
6364     unlink (filename);
6365     exit (EXIT_FAILURE);
6366   }
6367   if (write (fd, &c, 1) == -1) {
6368     perror (\"write\");
6369     close (fd);
6370     unlink (filename);
6371     exit (EXIT_FAILURE);
6372   }
6373   if (close (fd) == -1) {
6374     perror (filename);
6375     unlink (filename);
6376     exit (EXIT_FAILURE);
6377   }
6378   if (guestfs_add_drive (g, filename) == -1) {
6379     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6380     exit (EXIT_FAILURE);
6381   }
6382
6383   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6384     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6385     exit (EXIT_FAILURE);
6386   }
6387
6388   if (guestfs_launch (g) == -1) {
6389     printf (\"guestfs_launch FAILED\\n\");
6390     exit (EXIT_FAILURE);
6391   }
6392
6393   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6394   alarm (600);
6395
6396   /* Cancel previous alarm. */
6397   alarm (0);
6398
6399   nr_tests = %d;
6400
6401 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6402
6403   iteri (
6404     fun i test_name ->
6405       pr "  test_num++;\n";
6406       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6407       pr "  if (%s () == -1) {\n" test_name;
6408       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6409       pr "    n_failed++;\n";
6410       pr "  }\n";
6411   ) test_names;
6412   pr "\n";
6413
6414   pr "  guestfs_close (g);\n";
6415   pr "  unlink (\"test1.img\");\n";
6416   pr "  unlink (\"test2.img\");\n";
6417   pr "  unlink (\"test3.img\");\n";
6418   pr "\n";
6419
6420   pr "  if (n_failed > 0) {\n";
6421   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6422   pr "    exit (EXIT_FAILURE);\n";
6423   pr "  }\n";
6424   pr "\n";
6425
6426   pr "  exit (EXIT_SUCCESS);\n";
6427   pr "}\n"
6428
6429 and generate_one_test name flags i (init, prereq, test) =
6430   let test_name = sprintf "test_%s_%d" name i in
6431
6432   pr "\
6433 static int %s_skip (void)
6434 {
6435   const char *str;
6436
6437   str = getenv (\"TEST_ONLY\");
6438   if (str)
6439     return strstr (str, \"%s\") == NULL;
6440   str = getenv (\"SKIP_%s\");
6441   if (str && STREQ (str, \"1\")) return 1;
6442   str = getenv (\"SKIP_TEST_%s\");
6443   if (str && STREQ (str, \"1\")) return 1;
6444   return 0;
6445 }
6446
6447 " test_name name (String.uppercase test_name) (String.uppercase name);
6448
6449   (match prereq with
6450    | Disabled | Always -> ()
6451    | If code | Unless code ->
6452        pr "static int %s_prereq (void)\n" test_name;
6453        pr "{\n";
6454        pr "  %s\n" code;
6455        pr "}\n";
6456        pr "\n";
6457   );
6458
6459   pr "\
6460 static int %s (void)
6461 {
6462   if (%s_skip ()) {
6463     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6464     return 0;
6465   }
6466
6467 " test_name test_name test_name;
6468
6469   (* Optional functions should only be tested if the relevant
6470    * support is available in the daemon.
6471    *)
6472   List.iter (
6473     function
6474     | Optional group ->
6475         pr "  {\n";
6476         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6477         pr "    int r;\n";
6478         pr "    suppress_error = 1;\n";
6479         pr "    r = guestfs_available (g, (char **) groups);\n";
6480         pr "    suppress_error = 0;\n";
6481         pr "    if (r == -1) {\n";
6482         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6483         pr "      return 0;\n";
6484         pr "    }\n";
6485         pr "  }\n";
6486     | _ -> ()
6487   ) flags;
6488
6489   (match prereq with
6490    | Disabled ->
6491        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6492    | If _ ->
6493        pr "  if (! %s_prereq ()) {\n" test_name;
6494        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6495        pr "    return 0;\n";
6496        pr "  }\n";
6497        pr "\n";
6498        generate_one_test_body name i test_name init test;
6499    | Unless _ ->
6500        pr "  if (%s_prereq ()) {\n" test_name;
6501        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6502        pr "    return 0;\n";
6503        pr "  }\n";
6504        pr "\n";
6505        generate_one_test_body name i test_name init test;
6506    | Always ->
6507        generate_one_test_body name i test_name init test
6508   );
6509
6510   pr "  return 0;\n";
6511   pr "}\n";
6512   pr "\n";
6513   test_name
6514
6515 and generate_one_test_body name i test_name init test =
6516   (match init with
6517    | InitNone (* XXX at some point, InitNone and InitEmpty became
6518                * folded together as the same thing.  Really we should
6519                * make InitNone do nothing at all, but the tests may
6520                * need to be checked to make sure this is OK.
6521                *)
6522    | InitEmpty ->
6523        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6524        List.iter (generate_test_command_call test_name)
6525          [["blockdev_setrw"; "/dev/sda"];
6526           ["umount_all"];
6527           ["lvm_remove_all"]]
6528    | InitPartition ->
6529        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6530        List.iter (generate_test_command_call test_name)
6531          [["blockdev_setrw"; "/dev/sda"];
6532           ["umount_all"];
6533           ["lvm_remove_all"];
6534           ["part_disk"; "/dev/sda"; "mbr"]]
6535    | InitBasicFS ->
6536        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6537        List.iter (generate_test_command_call test_name)
6538          [["blockdev_setrw"; "/dev/sda"];
6539           ["umount_all"];
6540           ["lvm_remove_all"];
6541           ["part_disk"; "/dev/sda"; "mbr"];
6542           ["mkfs"; "ext2"; "/dev/sda1"];
6543           ["mount_options"; ""; "/dev/sda1"; "/"]]
6544    | InitBasicFSonLVM ->
6545        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6546          test_name;
6547        List.iter (generate_test_command_call test_name)
6548          [["blockdev_setrw"; "/dev/sda"];
6549           ["umount_all"];
6550           ["lvm_remove_all"];
6551           ["part_disk"; "/dev/sda"; "mbr"];
6552           ["pvcreate"; "/dev/sda1"];
6553           ["vgcreate"; "VG"; "/dev/sda1"];
6554           ["lvcreate"; "LV"; "VG"; "8"];
6555           ["mkfs"; "ext2"; "/dev/VG/LV"];
6556           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6557    | InitISOFS ->
6558        pr "  /* InitISOFS for %s */\n" test_name;
6559        List.iter (generate_test_command_call test_name)
6560          [["blockdev_setrw"; "/dev/sda"];
6561           ["umount_all"];
6562           ["lvm_remove_all"];
6563           ["mount_ro"; "/dev/sdd"; "/"]]
6564   );
6565
6566   let get_seq_last = function
6567     | [] ->
6568         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6569           test_name
6570     | seq ->
6571         let seq = List.rev seq in
6572         List.rev (List.tl seq), List.hd seq
6573   in
6574
6575   match test with
6576   | TestRun seq ->
6577       pr "  /* TestRun for %s (%d) */\n" name i;
6578       List.iter (generate_test_command_call test_name) seq
6579   | TestOutput (seq, expected) ->
6580       pr "  /* TestOutput for %s (%d) */\n" name i;
6581       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6582       let seq, last = get_seq_last seq in
6583       let test () =
6584         pr "    if (STRNEQ (r, expected)) {\n";
6585         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6586         pr "      return -1;\n";
6587         pr "    }\n"
6588       in
6589       List.iter (generate_test_command_call test_name) seq;
6590       generate_test_command_call ~test test_name last
6591   | TestOutputList (seq, expected) ->
6592       pr "  /* TestOutputList for %s (%d) */\n" name i;
6593       let seq, last = get_seq_last seq in
6594       let test () =
6595         iteri (
6596           fun i str ->
6597             pr "    if (!r[%d]) {\n" i;
6598             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6599             pr "      print_strings (r);\n";
6600             pr "      return -1;\n";
6601             pr "    }\n";
6602             pr "    {\n";
6603             pr "      const char *expected = \"%s\";\n" (c_quote str);
6604             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6605             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6606             pr "        return -1;\n";
6607             pr "      }\n";
6608             pr "    }\n"
6609         ) expected;
6610         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6611         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6612           test_name;
6613         pr "      print_strings (r);\n";
6614         pr "      return -1;\n";
6615         pr "    }\n"
6616       in
6617       List.iter (generate_test_command_call test_name) seq;
6618       generate_test_command_call ~test test_name last
6619   | TestOutputListOfDevices (seq, expected) ->
6620       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6621       let seq, last = get_seq_last seq in
6622       let test () =
6623         iteri (
6624           fun i str ->
6625             pr "    if (!r[%d]) {\n" i;
6626             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6627             pr "      print_strings (r);\n";
6628             pr "      return -1;\n";
6629             pr "    }\n";
6630             pr "    {\n";
6631             pr "      const char *expected = \"%s\";\n" (c_quote str);
6632             pr "      r[%d][5] = 's';\n" i;
6633             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6634             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6635             pr "        return -1;\n";
6636             pr "      }\n";
6637             pr "    }\n"
6638         ) expected;
6639         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6640         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6641           test_name;
6642         pr "      print_strings (r);\n";
6643         pr "      return -1;\n";
6644         pr "    }\n"
6645       in
6646       List.iter (generate_test_command_call test_name) seq;
6647       generate_test_command_call ~test test_name last
6648   | TestOutputInt (seq, expected) ->
6649       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6650       let seq, last = get_seq_last seq in
6651       let test () =
6652         pr "    if (r != %d) {\n" expected;
6653         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6654           test_name expected;
6655         pr "               (int) r);\n";
6656         pr "      return -1;\n";
6657         pr "    }\n"
6658       in
6659       List.iter (generate_test_command_call test_name) seq;
6660       generate_test_command_call ~test test_name last
6661   | TestOutputIntOp (seq, op, expected) ->
6662       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6663       let seq, last = get_seq_last seq in
6664       let test () =
6665         pr "    if (! (r %s %d)) {\n" op expected;
6666         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6667           test_name op expected;
6668         pr "               (int) r);\n";
6669         pr "      return -1;\n";
6670         pr "    }\n"
6671       in
6672       List.iter (generate_test_command_call test_name) seq;
6673       generate_test_command_call ~test test_name last
6674   | TestOutputTrue seq ->
6675       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6676       let seq, last = get_seq_last seq in
6677       let test () =
6678         pr "    if (!r) {\n";
6679         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6680           test_name;
6681         pr "      return -1;\n";
6682         pr "    }\n"
6683       in
6684       List.iter (generate_test_command_call test_name) seq;
6685       generate_test_command_call ~test test_name last
6686   | TestOutputFalse seq ->
6687       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6688       let seq, last = get_seq_last seq in
6689       let test () =
6690         pr "    if (r) {\n";
6691         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6692           test_name;
6693         pr "      return -1;\n";
6694         pr "    }\n"
6695       in
6696       List.iter (generate_test_command_call test_name) seq;
6697       generate_test_command_call ~test test_name last
6698   | TestOutputLength (seq, expected) ->
6699       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6700       let seq, last = get_seq_last seq in
6701       let test () =
6702         pr "    int j;\n";
6703         pr "    for (j = 0; j < %d; ++j)\n" expected;
6704         pr "      if (r[j] == NULL) {\n";
6705         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6706           test_name;
6707         pr "        print_strings (r);\n";
6708         pr "        return -1;\n";
6709         pr "      }\n";
6710         pr "    if (r[j] != NULL) {\n";
6711         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6712           test_name;
6713         pr "      print_strings (r);\n";
6714         pr "      return -1;\n";
6715         pr "    }\n"
6716       in
6717       List.iter (generate_test_command_call test_name) seq;
6718       generate_test_command_call ~test test_name last
6719   | TestOutputBuffer (seq, expected) ->
6720       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6721       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6722       let seq, last = get_seq_last seq in
6723       let len = String.length expected in
6724       let test () =
6725         pr "    if (size != %d) {\n" len;
6726         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6727         pr "      return -1;\n";
6728         pr "    }\n";
6729         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6730         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6731         pr "      return -1;\n";
6732         pr "    }\n"
6733       in
6734       List.iter (generate_test_command_call test_name) seq;
6735       generate_test_command_call ~test test_name last
6736   | TestOutputStruct (seq, checks) ->
6737       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6738       let seq, last = get_seq_last seq in
6739       let test () =
6740         List.iter (
6741           function
6742           | CompareWithInt (field, expected) ->
6743               pr "    if (r->%s != %d) {\n" field expected;
6744               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6745                 test_name field expected;
6746               pr "               (int) r->%s);\n" field;
6747               pr "      return -1;\n";
6748               pr "    }\n"
6749           | CompareWithIntOp (field, op, expected) ->
6750               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6751               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6752                 test_name field op expected;
6753               pr "               (int) r->%s);\n" field;
6754               pr "      return -1;\n";
6755               pr "    }\n"
6756           | CompareWithString (field, expected) ->
6757               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6758               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6759                 test_name field expected;
6760               pr "               r->%s);\n" field;
6761               pr "      return -1;\n";
6762               pr "    }\n"
6763           | CompareFieldsIntEq (field1, field2) ->
6764               pr "    if (r->%s != r->%s) {\n" field1 field2;
6765               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6766                 test_name field1 field2;
6767               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6768               pr "      return -1;\n";
6769               pr "    }\n"
6770           | CompareFieldsStrEq (field1, field2) ->
6771               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6772               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6773                 test_name field1 field2;
6774               pr "               r->%s, r->%s);\n" field1 field2;
6775               pr "      return -1;\n";
6776               pr "    }\n"
6777         ) checks
6778       in
6779       List.iter (generate_test_command_call test_name) seq;
6780       generate_test_command_call ~test test_name last
6781   | TestLastFail seq ->
6782       pr "  /* TestLastFail for %s (%d) */\n" name i;
6783       let seq, last = get_seq_last seq in
6784       List.iter (generate_test_command_call test_name) seq;
6785       generate_test_command_call test_name ~expect_error:true last
6786
6787 (* Generate the code to run a command, leaving the result in 'r'.
6788  * If you expect to get an error then you should set expect_error:true.
6789  *)
6790 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6791   match cmd with
6792   | [] -> assert false
6793   | name :: args ->
6794       (* Look up the command to find out what args/ret it has. *)
6795       let style =
6796         try
6797           let _, style, _, _, _, _, _ =
6798             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6799           style
6800         with Not_found ->
6801           failwithf "%s: in test, command %s was not found" test_name name in
6802
6803       if List.length (snd style) <> List.length args then
6804         failwithf "%s: in test, wrong number of args given to %s"
6805           test_name name;
6806
6807       pr "  {\n";
6808
6809       List.iter (
6810         function
6811         | OptString n, "NULL" -> ()
6812         | Pathname n, arg
6813         | Device n, arg
6814         | Dev_or_Path n, arg
6815         | String n, arg
6816         | OptString n, arg ->
6817             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6818         | Int _, _
6819         | Int64 _, _
6820         | Bool _, _
6821         | FileIn _, _ | FileOut _, _ -> ()
6822         | StringList n, "" | DeviceList n, "" ->
6823             pr "    const char *const %s[1] = { NULL };\n" n
6824         | StringList n, arg | DeviceList n, arg ->
6825             let strs = string_split " " arg in
6826             iteri (
6827               fun i str ->
6828                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6829             ) strs;
6830             pr "    const char *const %s[] = {\n" n;
6831             iteri (
6832               fun i _ -> pr "      %s_%d,\n" n i
6833             ) strs;
6834             pr "      NULL\n";
6835             pr "    };\n";
6836       ) (List.combine (snd style) args);
6837
6838       let error_code =
6839         match fst style with
6840         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6841         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6842         | RConstString _ | RConstOptString _ ->
6843             pr "    const char *r;\n"; "NULL"
6844         | RString _ -> pr "    char *r;\n"; "NULL"
6845         | RStringList _ | RHashtable _ ->
6846             pr "    char **r;\n";
6847             pr "    int i;\n";
6848             "NULL"
6849         | RStruct (_, typ) ->
6850             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6851         | RStructList (_, typ) ->
6852             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6853         | RBufferOut _ ->
6854             pr "    char *r;\n";
6855             pr "    size_t size;\n";
6856             "NULL" in
6857
6858       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6859       pr "    r = guestfs_%s (g" name;
6860
6861       (* Generate the parameters. *)
6862       List.iter (
6863         function
6864         | OptString _, "NULL" -> pr ", NULL"
6865         | Pathname n, _
6866         | Device n, _ | Dev_or_Path n, _
6867         | String n, _
6868         | OptString n, _ ->
6869             pr ", %s" n
6870         | FileIn _, arg | FileOut _, arg ->
6871             pr ", \"%s\"" (c_quote arg)
6872         | StringList n, _ | DeviceList n, _ ->
6873             pr ", (char **) %s" n
6874         | Int _, arg ->
6875             let i =
6876               try int_of_string arg
6877               with Failure "int_of_string" ->
6878                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6879             pr ", %d" i
6880         | Int64 _, arg ->
6881             let i =
6882               try Int64.of_string arg
6883               with Failure "int_of_string" ->
6884                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6885             pr ", %Ld" i
6886         | Bool _, arg ->
6887             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6888       ) (List.combine (snd style) args);
6889
6890       (match fst style with
6891        | RBufferOut _ -> pr ", &size"
6892        | _ -> ()
6893       );
6894
6895       pr ");\n";
6896
6897       if not expect_error then
6898         pr "    if (r == %s)\n" error_code
6899       else
6900         pr "    if (r != %s)\n" error_code;
6901       pr "      return -1;\n";
6902
6903       (* Insert the test code. *)
6904       (match test with
6905        | None -> ()
6906        | Some f -> f ()
6907       );
6908
6909       (match fst style with
6910        | RErr | RInt _ | RInt64 _ | RBool _
6911        | RConstString _ | RConstOptString _ -> ()
6912        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6913        | RStringList _ | RHashtable _ ->
6914            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6915            pr "      free (r[i]);\n";
6916            pr "    free (r);\n"
6917        | RStruct (_, typ) ->
6918            pr "    guestfs_free_%s (r);\n" typ
6919        | RStructList (_, typ) ->
6920            pr "    guestfs_free_%s_list (r);\n" typ
6921       );
6922
6923       pr "  }\n"
6924
6925 and c_quote str =
6926   let str = replace_str str "\r" "\\r" in
6927   let str = replace_str str "\n" "\\n" in
6928   let str = replace_str str "\t" "\\t" in
6929   let str = replace_str str "\000" "\\0" in
6930   str
6931
6932 (* Generate a lot of different functions for guestfish. *)
6933 and generate_fish_cmds () =
6934   generate_header CStyle GPLv2plus;
6935
6936   let all_functions =
6937     List.filter (
6938       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6939     ) all_functions in
6940   let all_functions_sorted =
6941     List.filter (
6942       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6943     ) all_functions_sorted in
6944
6945   pr "#include <config.h>\n";
6946   pr "\n";
6947   pr "#include <stdio.h>\n";
6948   pr "#include <stdlib.h>\n";
6949   pr "#include <string.h>\n";
6950   pr "#include <inttypes.h>\n";
6951   pr "\n";
6952   pr "#include <guestfs.h>\n";
6953   pr "#include \"c-ctype.h\"\n";
6954   pr "#include \"full-write.h\"\n";
6955   pr "#include \"xstrtol.h\"\n";
6956   pr "#include \"fish.h\"\n";
6957   pr "\n";
6958
6959   (* list_commands function, which implements guestfish -h *)
6960   pr "void list_commands (void)\n";
6961   pr "{\n";
6962   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6963   pr "  list_builtin_commands ();\n";
6964   List.iter (
6965     fun (name, _, _, flags, _, shortdesc, _) ->
6966       let name = replace_char name '_' '-' in
6967       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6968         name shortdesc
6969   ) all_functions_sorted;
6970   pr "  printf (\"    %%s\\n\",";
6971   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6972   pr "}\n";
6973   pr "\n";
6974
6975   (* display_command function, which implements guestfish -h cmd *)
6976   pr "void display_command (const char *cmd)\n";
6977   pr "{\n";
6978   List.iter (
6979     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6980       let name2 = replace_char name '_' '-' in
6981       let alias =
6982         try find_map (function FishAlias n -> Some n | _ -> None) flags
6983         with Not_found -> name in
6984       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6985       let synopsis =
6986         match snd style with
6987         | [] -> name2
6988         | args ->
6989             sprintf "%s %s"
6990               name2 (String.concat " " (List.map name_of_argt args)) in
6991
6992       let warnings =
6993         if List.mem ProtocolLimitWarning flags then
6994           ("\n\n" ^ protocol_limit_warning)
6995         else "" in
6996
6997       (* For DangerWillRobinson commands, we should probably have
6998        * guestfish prompt before allowing you to use them (especially
6999        * in interactive mode). XXX
7000        *)
7001       let warnings =
7002         warnings ^
7003           if List.mem DangerWillRobinson flags then
7004             ("\n\n" ^ danger_will_robinson)
7005           else "" in
7006
7007       let warnings =
7008         warnings ^
7009           match deprecation_notice flags with
7010           | None -> ""
7011           | Some txt -> "\n\n" ^ txt in
7012
7013       let describe_alias =
7014         if name <> alias then
7015           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7016         else "" in
7017
7018       pr "  if (";
7019       pr "STRCASEEQ (cmd, \"%s\")" name;
7020       if name <> name2 then
7021         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7022       if name <> alias then
7023         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7024       pr ")\n";
7025       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7026         name2 shortdesc
7027         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7028          "=head1 DESCRIPTION\n\n" ^
7029          longdesc ^ warnings ^ describe_alias);
7030       pr "  else\n"
7031   ) all_functions;
7032   pr "    display_builtin_command (cmd);\n";
7033   pr "}\n";
7034   pr "\n";
7035
7036   let emit_print_list_function typ =
7037     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7038       typ typ typ;
7039     pr "{\n";
7040     pr "  unsigned int i;\n";
7041     pr "\n";
7042     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7043     pr "    printf (\"[%%d] = {\\n\", i);\n";
7044     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7045     pr "    printf (\"}\\n\");\n";
7046     pr "  }\n";
7047     pr "}\n";
7048     pr "\n";
7049   in
7050
7051   (* print_* functions *)
7052   List.iter (
7053     fun (typ, cols) ->
7054       let needs_i =
7055         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7056
7057       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7058       pr "{\n";
7059       if needs_i then (
7060         pr "  unsigned int i;\n";
7061         pr "\n"
7062       );
7063       List.iter (
7064         function
7065         | name, FString ->
7066             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7067         | name, FUUID ->
7068             pr "  printf (\"%%s%s: \", indent);\n" name;
7069             pr "  for (i = 0; i < 32; ++i)\n";
7070             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7071             pr "  printf (\"\\n\");\n"
7072         | name, FBuffer ->
7073             pr "  printf (\"%%s%s: \", indent);\n" name;
7074             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7075             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7076             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7077             pr "    else\n";
7078             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7079             pr "  printf (\"\\n\");\n"
7080         | name, (FUInt64|FBytes) ->
7081             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7082               name typ name
7083         | name, FInt64 ->
7084             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7085               name typ name
7086         | name, FUInt32 ->
7087             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7088               name typ name
7089         | name, FInt32 ->
7090             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7091               name typ name
7092         | name, FChar ->
7093             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7094               name typ name
7095         | name, FOptPercent ->
7096             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7097               typ name name typ name;
7098             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7099       ) cols;
7100       pr "}\n";
7101       pr "\n";
7102   ) structs;
7103
7104   (* Emit a print_TYPE_list function definition only if that function is used. *)
7105   List.iter (
7106     function
7107     | typ, (RStructListOnly | RStructAndList) ->
7108         (* generate the function for typ *)
7109         emit_print_list_function typ
7110     | typ, _ -> () (* empty *)
7111   ) (rstructs_used_by all_functions);
7112
7113   (* Emit a print_TYPE function definition only if that function is used. *)
7114   List.iter (
7115     function
7116     | typ, (RStructOnly | RStructAndList) ->
7117         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7118         pr "{\n";
7119         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7120         pr "}\n";
7121         pr "\n";
7122     | typ, _ -> () (* empty *)
7123   ) (rstructs_used_by all_functions);
7124
7125   (* run_<action> actions *)
7126   List.iter (
7127     fun (name, style, _, flags, _, _, _) ->
7128       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7129       pr "{\n";
7130       (match fst style with
7131        | RErr
7132        | RInt _
7133        | RBool _ -> pr "  int r;\n"
7134        | RInt64 _ -> pr "  int64_t r;\n"
7135        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7136        | RString _ -> pr "  char *r;\n"
7137        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7138        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7139        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7140        | RBufferOut _ ->
7141            pr "  char *r;\n";
7142            pr "  size_t size;\n";
7143       );
7144       List.iter (
7145         function
7146         | Device n
7147         | String n
7148         | OptString n
7149         | FileIn n
7150         | FileOut n -> pr "  const char *%s;\n" n
7151         | Pathname n
7152         | Dev_or_Path n -> pr "  char *%s;\n" n
7153         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7154         | Bool n -> pr "  int %s;\n" n
7155         | Int n -> pr "  int %s;\n" n
7156         | Int64 n -> pr "  int64_t %s;\n" n
7157       ) (snd style);
7158
7159       (* Check and convert parameters. *)
7160       let argc_expected = List.length (snd style) in
7161       pr "  if (argc != %d) {\n" argc_expected;
7162       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7163         argc_expected;
7164       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7165       pr "    return -1;\n";
7166       pr "  }\n";
7167
7168       let parse_integer fn fntyp rtyp range name i =
7169         pr "  {\n";
7170         pr "    strtol_error xerr;\n";
7171         pr "    %s r;\n" fntyp;
7172         pr "\n";
7173         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7174         pr "    if (xerr != LONGINT_OK) {\n";
7175         pr "      fprintf (stderr,\n";
7176         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7177         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7178         pr "      return -1;\n";
7179         pr "    }\n";
7180         (match range with
7181          | None -> ()
7182          | Some (min, max, comment) ->
7183              pr "    /* %s */\n" comment;
7184              pr "    if (r < %s || r > %s) {\n" min max;
7185              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7186                name;
7187              pr "      return -1;\n";
7188              pr "    }\n";
7189              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7190         );
7191         pr "    %s = r;\n" name;
7192         pr "  }\n";
7193       in
7194
7195       iteri (
7196         fun i ->
7197           function
7198           | Device name
7199           | String name ->
7200               pr "  %s = argv[%d];\n" name i
7201           | Pathname name
7202           | Dev_or_Path name ->
7203               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7204               pr "  if (%s == NULL) return -1;\n" name
7205           | OptString name ->
7206               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7207                 name i i
7208           | FileIn name ->
7209               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7210                 name i i
7211           | FileOut name ->
7212               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7213                 name i i
7214           | StringList name | DeviceList name ->
7215               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7216               pr "  if (%s == NULL) return -1;\n" name;
7217           | Bool name ->
7218               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7219           | Int name ->
7220               let range =
7221                 let min = "(-(2LL<<30))"
7222                 and max = "((2LL<<30)-1)"
7223                 and comment =
7224                   "The Int type in the generator is a signed 31 bit int." in
7225                 Some (min, max, comment) in
7226               parse_integer "xstrtol" "long" "int" range name i
7227           | Int64 name ->
7228               parse_integer "xstrtoll" "long long" "int64_t" None name i
7229       ) (snd style);
7230
7231       (* Call C API function. *)
7232       let fn =
7233         try find_map (function FishAction n -> Some n | _ -> None) flags
7234         with Not_found -> sprintf "guestfs_%s" name in
7235       pr "  r = %s " fn;
7236       generate_c_call_args ~handle:"g" style;
7237       pr ";\n";
7238
7239       List.iter (
7240         function
7241         | Device name | String name
7242         | OptString name | FileIn name | FileOut name | Bool name
7243         | Int name | Int64 name -> ()
7244         | Pathname name | Dev_or_Path name ->
7245             pr "  free (%s);\n" name
7246         | StringList name | DeviceList name ->
7247             pr "  free_strings (%s);\n" name
7248       ) (snd style);
7249
7250       (* Check return value for errors and display command results. *)
7251       (match fst style with
7252        | RErr -> pr "  return r;\n"
7253        | RInt _ ->
7254            pr "  if (r == -1) return -1;\n";
7255            pr "  printf (\"%%d\\n\", r);\n";
7256            pr "  return 0;\n"
7257        | RInt64 _ ->
7258            pr "  if (r == -1) return -1;\n";
7259            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7260            pr "  return 0;\n"
7261        | RBool _ ->
7262            pr "  if (r == -1) return -1;\n";
7263            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7264            pr "  return 0;\n"
7265        | RConstString _ ->
7266            pr "  if (r == NULL) return -1;\n";
7267            pr "  printf (\"%%s\\n\", r);\n";
7268            pr "  return 0;\n"
7269        | RConstOptString _ ->
7270            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7271            pr "  return 0;\n"
7272        | RString _ ->
7273            pr "  if (r == NULL) return -1;\n";
7274            pr "  printf (\"%%s\\n\", r);\n";
7275            pr "  free (r);\n";
7276            pr "  return 0;\n"
7277        | RStringList _ ->
7278            pr "  if (r == NULL) return -1;\n";
7279            pr "  print_strings (r);\n";
7280            pr "  free_strings (r);\n";
7281            pr "  return 0;\n"
7282        | RStruct (_, typ) ->
7283            pr "  if (r == NULL) return -1;\n";
7284            pr "  print_%s (r);\n" typ;
7285            pr "  guestfs_free_%s (r);\n" typ;
7286            pr "  return 0;\n"
7287        | RStructList (_, typ) ->
7288            pr "  if (r == NULL) return -1;\n";
7289            pr "  print_%s_list (r);\n" typ;
7290            pr "  guestfs_free_%s_list (r);\n" typ;
7291            pr "  return 0;\n"
7292        | RHashtable _ ->
7293            pr "  if (r == NULL) return -1;\n";
7294            pr "  print_table (r);\n";
7295            pr "  free_strings (r);\n";
7296            pr "  return 0;\n"
7297        | RBufferOut _ ->
7298            pr "  if (r == NULL) return -1;\n";
7299            pr "  if (full_write (1, r, size) != size) {\n";
7300            pr "    perror (\"write\");\n";
7301            pr "    free (r);\n";
7302            pr "    return -1;\n";
7303            pr "  }\n";
7304            pr "  free (r);\n";
7305            pr "  return 0;\n"
7306       );
7307       pr "}\n";
7308       pr "\n"
7309   ) all_functions;
7310
7311   (* run_action function *)
7312   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7313   pr "{\n";
7314   List.iter (
7315     fun (name, _, _, flags, _, _, _) ->
7316       let name2 = replace_char name '_' '-' in
7317       let alias =
7318         try find_map (function FishAlias n -> Some n | _ -> None) flags
7319         with Not_found -> name in
7320       pr "  if (";
7321       pr "STRCASEEQ (cmd, \"%s\")" name;
7322       if name <> name2 then
7323         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7324       if name <> alias then
7325         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7326       pr ")\n";
7327       pr "    return run_%s (cmd, argc, argv);\n" name;
7328       pr "  else\n";
7329   ) all_functions;
7330   pr "    {\n";
7331   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7332   pr "      return -1;\n";
7333   pr "    }\n";
7334   pr "  return 0;\n";
7335   pr "}\n";
7336   pr "\n"
7337
7338 (* Readline completion for guestfish. *)
7339 and generate_fish_completion () =
7340   generate_header CStyle GPLv2plus;
7341
7342   let all_functions =
7343     List.filter (
7344       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7345     ) all_functions in
7346
7347   pr "\
7348 #include <config.h>
7349
7350 #include <stdio.h>
7351 #include <stdlib.h>
7352 #include <string.h>
7353
7354 #ifdef HAVE_LIBREADLINE
7355 #include <readline/readline.h>
7356 #endif
7357
7358 #include \"fish.h\"
7359
7360 #ifdef HAVE_LIBREADLINE
7361
7362 static const char *const commands[] = {
7363   BUILTIN_COMMANDS_FOR_COMPLETION,
7364 ";
7365
7366   (* Get the commands, including the aliases.  They don't need to be
7367    * sorted - the generator() function just does a dumb linear search.
7368    *)
7369   let commands =
7370     List.map (
7371       fun (name, _, _, flags, _, _, _) ->
7372         let name2 = replace_char name '_' '-' in
7373         let alias =
7374           try find_map (function FishAlias n -> Some n | _ -> None) flags
7375           with Not_found -> name in
7376
7377         if name <> alias then [name2; alias] else [name2]
7378     ) all_functions in
7379   let commands = List.flatten commands in
7380
7381   List.iter (pr "  \"%s\",\n") commands;
7382
7383   pr "  NULL
7384 };
7385
7386 static char *
7387 generator (const char *text, int state)
7388 {
7389   static int index, len;
7390   const char *name;
7391
7392   if (!state) {
7393     index = 0;
7394     len = strlen (text);
7395   }
7396
7397   rl_attempted_completion_over = 1;
7398
7399   while ((name = commands[index]) != NULL) {
7400     index++;
7401     if (STRCASEEQLEN (name, text, len))
7402       return strdup (name);
7403   }
7404
7405   return NULL;
7406 }
7407
7408 #endif /* HAVE_LIBREADLINE */
7409
7410 char **do_completion (const char *text, int start, int end)
7411 {
7412   char **matches = NULL;
7413
7414 #ifdef HAVE_LIBREADLINE
7415   rl_completion_append_character = ' ';
7416
7417   if (start == 0)
7418     matches = rl_completion_matches (text, generator);
7419   else if (complete_dest_paths)
7420     matches = rl_completion_matches (text, complete_dest_paths_generator);
7421 #endif
7422
7423   return matches;
7424 }
7425 ";
7426
7427 (* Generate the POD documentation for guestfish. *)
7428 and generate_fish_actions_pod () =
7429   let all_functions_sorted =
7430     List.filter (
7431       fun (_, _, _, flags, _, _, _) ->
7432         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7433     ) all_functions_sorted in
7434
7435   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7436
7437   List.iter (
7438     fun (name, style, _, flags, _, _, longdesc) ->
7439       let longdesc =
7440         Str.global_substitute rex (
7441           fun s ->
7442             let sub =
7443               try Str.matched_group 1 s
7444               with Not_found ->
7445                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7446             "C<" ^ replace_char sub '_' '-' ^ ">"
7447         ) longdesc in
7448       let name = replace_char name '_' '-' in
7449       let alias =
7450         try find_map (function FishAlias n -> Some n | _ -> None) flags
7451         with Not_found -> name in
7452
7453       pr "=head2 %s" name;
7454       if name <> alias then
7455         pr " | %s" alias;
7456       pr "\n";
7457       pr "\n";
7458       pr " %s" name;
7459       List.iter (
7460         function
7461         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7462         | OptString n -> pr " %s" n
7463         | StringList n | DeviceList n -> pr " '%s ...'" n
7464         | Bool _ -> pr " true|false"
7465         | Int n -> pr " %s" n
7466         | Int64 n -> pr " %s" n
7467         | FileIn n | FileOut n -> pr " (%s|-)" n
7468       ) (snd style);
7469       pr "\n";
7470       pr "\n";
7471       pr "%s\n\n" longdesc;
7472
7473       if List.exists (function FileIn _ | FileOut _ -> true
7474                       | _ -> false) (snd style) then
7475         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7476
7477       if List.mem ProtocolLimitWarning flags then
7478         pr "%s\n\n" protocol_limit_warning;
7479
7480       if List.mem DangerWillRobinson flags then
7481         pr "%s\n\n" danger_will_robinson;
7482
7483       match deprecation_notice flags with
7484       | None -> ()
7485       | Some txt -> pr "%s\n\n" txt
7486   ) all_functions_sorted
7487
7488 (* Generate a C function prototype. *)
7489 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7490     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7491     ?(prefix = "")
7492     ?handle name style =
7493   if extern then pr "extern ";
7494   if static then pr "static ";
7495   (match fst style with
7496    | RErr -> pr "int "
7497    | RInt _ -> pr "int "
7498    | RInt64 _ -> pr "int64_t "
7499    | RBool _ -> pr "int "
7500    | RConstString _ | RConstOptString _ -> pr "const char *"
7501    | RString _ | RBufferOut _ -> pr "char *"
7502    | RStringList _ | RHashtable _ -> pr "char **"
7503    | RStruct (_, typ) ->
7504        if not in_daemon then pr "struct guestfs_%s *" typ
7505        else pr "guestfs_int_%s *" typ
7506    | RStructList (_, typ) ->
7507        if not in_daemon then pr "struct guestfs_%s_list *" typ
7508        else pr "guestfs_int_%s_list *" typ
7509   );
7510   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7511   pr "%s%s (" prefix name;
7512   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7513     pr "void"
7514   else (
7515     let comma = ref false in
7516     (match handle with
7517      | None -> ()
7518      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7519     );
7520     let next () =
7521       if !comma then (
7522         if single_line then pr ", " else pr ",\n\t\t"
7523       );
7524       comma := true
7525     in
7526     List.iter (
7527       function
7528       | Pathname n
7529       | Device n | Dev_or_Path n
7530       | String n
7531       | OptString n ->
7532           next ();
7533           pr "const char *%s" n
7534       | StringList n | DeviceList n ->
7535           next ();
7536           pr "char *const *%s" n
7537       | Bool n -> next (); pr "int %s" n
7538       | Int n -> next (); pr "int %s" n
7539       | Int64 n -> next (); pr "int64_t %s" n
7540       | FileIn n
7541       | FileOut n ->
7542           if not in_daemon then (next (); pr "const char *%s" n)
7543     ) (snd style);
7544     if is_RBufferOut then (next (); pr "size_t *size_r");
7545   );
7546   pr ")";
7547   if semicolon then pr ";";
7548   if newline then pr "\n"
7549
7550 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7551 and generate_c_call_args ?handle ?(decl = false) style =
7552   pr "(";
7553   let comma = ref false in
7554   let next () =
7555     if !comma then pr ", ";
7556     comma := true
7557   in
7558   (match handle with
7559    | None -> ()
7560    | Some handle -> pr "%s" handle; comma := true
7561   );
7562   List.iter (
7563     fun arg ->
7564       next ();
7565       pr "%s" (name_of_argt arg)
7566   ) (snd style);
7567   (* For RBufferOut calls, add implicit &size parameter. *)
7568   if not decl then (
7569     match fst style with
7570     | RBufferOut _ ->
7571         next ();
7572         pr "&size"
7573     | _ -> ()
7574   );
7575   pr ")"
7576
7577 (* Generate the OCaml bindings interface. *)
7578 and generate_ocaml_mli () =
7579   generate_header OCamlStyle LGPLv2plus;
7580
7581   pr "\
7582 (** For API documentation you should refer to the C API
7583     in the guestfs(3) manual page.  The OCaml API uses almost
7584     exactly the same calls. *)
7585
7586 type t
7587 (** A [guestfs_h] handle. *)
7588
7589 exception Error of string
7590 (** This exception is raised when there is an error. *)
7591
7592 exception Handle_closed of string
7593 (** This exception is raised if you use a {!Guestfs.t} handle
7594     after calling {!close} on it.  The string is the name of
7595     the function. *)
7596
7597 val create : unit -> t
7598 (** Create a {!Guestfs.t} handle. *)
7599
7600 val close : t -> unit
7601 (** Close the {!Guestfs.t} handle and free up all resources used
7602     by it immediately.
7603
7604     Handles are closed by the garbage collector when they become
7605     unreferenced, but callers can call this in order to provide
7606     predictable cleanup. *)
7607
7608 ";
7609   generate_ocaml_structure_decls ();
7610
7611   (* The actions. *)
7612   List.iter (
7613     fun (name, style, _, _, _, shortdesc, _) ->
7614       generate_ocaml_prototype name style;
7615       pr "(** %s *)\n" shortdesc;
7616       pr "\n"
7617   ) all_functions_sorted
7618
7619 (* Generate the OCaml bindings implementation. *)
7620 and generate_ocaml_ml () =
7621   generate_header OCamlStyle LGPLv2plus;
7622
7623   pr "\
7624 type t
7625
7626 exception Error of string
7627 exception Handle_closed of string
7628
7629 external create : unit -> t = \"ocaml_guestfs_create\"
7630 external close : t -> unit = \"ocaml_guestfs_close\"
7631
7632 (* Give the exceptions names, so they can be raised from the C code. *)
7633 let () =
7634   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7635   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7636
7637 ";
7638
7639   generate_ocaml_structure_decls ();
7640
7641   (* The actions. *)
7642   List.iter (
7643     fun (name, style, _, _, _, shortdesc, _) ->
7644       generate_ocaml_prototype ~is_external:true name style;
7645   ) all_functions_sorted
7646
7647 (* Generate the OCaml bindings C implementation. *)
7648 and generate_ocaml_c () =
7649   generate_header CStyle LGPLv2plus;
7650
7651   pr "\
7652 #include <stdio.h>
7653 #include <stdlib.h>
7654 #include <string.h>
7655
7656 #include <caml/config.h>
7657 #include <caml/alloc.h>
7658 #include <caml/callback.h>
7659 #include <caml/fail.h>
7660 #include <caml/memory.h>
7661 #include <caml/mlvalues.h>
7662 #include <caml/signals.h>
7663
7664 #include <guestfs.h>
7665
7666 #include \"guestfs_c.h\"
7667
7668 /* Copy a hashtable of string pairs into an assoc-list.  We return
7669  * the list in reverse order, but hashtables aren't supposed to be
7670  * ordered anyway.
7671  */
7672 static CAMLprim value
7673 copy_table (char * const * argv)
7674 {
7675   CAMLparam0 ();
7676   CAMLlocal5 (rv, pairv, kv, vv, cons);
7677   int i;
7678
7679   rv = Val_int (0);
7680   for (i = 0; argv[i] != NULL; i += 2) {
7681     kv = caml_copy_string (argv[i]);
7682     vv = caml_copy_string (argv[i+1]);
7683     pairv = caml_alloc (2, 0);
7684     Store_field (pairv, 0, kv);
7685     Store_field (pairv, 1, vv);
7686     cons = caml_alloc (2, 0);
7687     Store_field (cons, 1, rv);
7688     rv = cons;
7689     Store_field (cons, 0, pairv);
7690   }
7691
7692   CAMLreturn (rv);
7693 }
7694
7695 ";
7696
7697   (* Struct copy functions. *)
7698
7699   let emit_ocaml_copy_list_function typ =
7700     pr "static CAMLprim value\n";
7701     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7702     pr "{\n";
7703     pr "  CAMLparam0 ();\n";
7704     pr "  CAMLlocal2 (rv, v);\n";
7705     pr "  unsigned int i;\n";
7706     pr "\n";
7707     pr "  if (%ss->len == 0)\n" typ;
7708     pr "    CAMLreturn (Atom (0));\n";
7709     pr "  else {\n";
7710     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7711     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7712     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7713     pr "      caml_modify (&Field (rv, i), v);\n";
7714     pr "    }\n";
7715     pr "    CAMLreturn (rv);\n";
7716     pr "  }\n";
7717     pr "}\n";
7718     pr "\n";
7719   in
7720
7721   List.iter (
7722     fun (typ, cols) ->
7723       let has_optpercent_col =
7724         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7725
7726       pr "static CAMLprim value\n";
7727       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7728       pr "{\n";
7729       pr "  CAMLparam0 ();\n";
7730       if has_optpercent_col then
7731         pr "  CAMLlocal3 (rv, v, v2);\n"
7732       else
7733         pr "  CAMLlocal2 (rv, v);\n";
7734       pr "\n";
7735       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7736       iteri (
7737         fun i col ->
7738           (match col with
7739            | name, FString ->
7740                pr "  v = caml_copy_string (%s->%s);\n" typ name
7741            | name, FBuffer ->
7742                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7743                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7744                  typ name typ name
7745            | name, FUUID ->
7746                pr "  v = caml_alloc_string (32);\n";
7747                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7748            | name, (FBytes|FInt64|FUInt64) ->
7749                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7750            | name, (FInt32|FUInt32) ->
7751                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7752            | name, FOptPercent ->
7753                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7754                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7755                pr "    v = caml_alloc (1, 0);\n";
7756                pr "    Store_field (v, 0, v2);\n";
7757                pr "  } else /* None */\n";
7758                pr "    v = Val_int (0);\n";
7759            | name, FChar ->
7760                pr "  v = Val_int (%s->%s);\n" typ name
7761           );
7762           pr "  Store_field (rv, %d, v);\n" i
7763       ) cols;
7764       pr "  CAMLreturn (rv);\n";
7765       pr "}\n";
7766       pr "\n";
7767   ) structs;
7768
7769   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7770   List.iter (
7771     function
7772     | typ, (RStructListOnly | RStructAndList) ->
7773         (* generate the function for typ *)
7774         emit_ocaml_copy_list_function typ
7775     | typ, _ -> () (* empty *)
7776   ) (rstructs_used_by all_functions);
7777
7778   (* The wrappers. *)
7779   List.iter (
7780     fun (name, style, _, _, _, _, _) ->
7781       pr "/* Automatically generated wrapper for function\n";
7782       pr " * ";
7783       generate_ocaml_prototype name style;
7784       pr " */\n";
7785       pr "\n";
7786
7787       let params =
7788         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7789
7790       let needs_extra_vs =
7791         match fst style with RConstOptString _ -> true | _ -> false in
7792
7793       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7794       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7795       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7796       pr "\n";
7797
7798       pr "CAMLprim value\n";
7799       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7800       List.iter (pr ", value %s") (List.tl params);
7801       pr ")\n";
7802       pr "{\n";
7803
7804       (match params with
7805        | [p1; p2; p3; p4; p5] ->
7806            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7807        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7808            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7809            pr "  CAMLxparam%d (%s);\n"
7810              (List.length rest) (String.concat ", " rest)
7811        | ps ->
7812            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7813       );
7814       if not needs_extra_vs then
7815         pr "  CAMLlocal1 (rv);\n"
7816       else
7817         pr "  CAMLlocal3 (rv, v, v2);\n";
7818       pr "\n";
7819
7820       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7821       pr "  if (g == NULL)\n";
7822       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7823       pr "\n";
7824
7825       List.iter (
7826         function
7827         | Pathname n
7828         | Device n | Dev_or_Path n
7829         | String n
7830         | FileIn n
7831         | FileOut n ->
7832             pr "  const char *%s = String_val (%sv);\n" n n
7833         | OptString n ->
7834             pr "  const char *%s =\n" n;
7835             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7836               n n
7837         | StringList n | DeviceList n ->
7838             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7839         | Bool n ->
7840             pr "  int %s = Bool_val (%sv);\n" n n
7841         | Int n ->
7842             pr "  int %s = Int_val (%sv);\n" n n
7843         | Int64 n ->
7844             pr "  int64_t %s = Int64_val (%sv);\n" n n
7845       ) (snd style);
7846       let error_code =
7847         match fst style with
7848         | RErr -> pr "  int r;\n"; "-1"
7849         | RInt _ -> pr "  int r;\n"; "-1"
7850         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7851         | RBool _ -> pr "  int r;\n"; "-1"
7852         | RConstString _ | RConstOptString _ ->
7853             pr "  const char *r;\n"; "NULL"
7854         | RString _ -> pr "  char *r;\n"; "NULL"
7855         | RStringList _ ->
7856             pr "  int i;\n";
7857             pr "  char **r;\n";
7858             "NULL"
7859         | RStruct (_, typ) ->
7860             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7861         | RStructList (_, typ) ->
7862             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7863         | RHashtable _ ->
7864             pr "  int i;\n";
7865             pr "  char **r;\n";
7866             "NULL"
7867         | RBufferOut _ ->
7868             pr "  char *r;\n";
7869             pr "  size_t size;\n";
7870             "NULL" in
7871       pr "\n";
7872
7873       pr "  caml_enter_blocking_section ();\n";
7874       pr "  r = guestfs_%s " name;
7875       generate_c_call_args ~handle:"g" style;
7876       pr ";\n";
7877       pr "  caml_leave_blocking_section ();\n";
7878
7879       List.iter (
7880         function
7881         | StringList n | DeviceList n ->
7882             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7883         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7884         | Bool _ | Int _ | Int64 _
7885         | FileIn _ | FileOut _ -> ()
7886       ) (snd style);
7887
7888       pr "  if (r == %s)\n" error_code;
7889       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7890       pr "\n";
7891
7892       (match fst style with
7893        | RErr -> pr "  rv = Val_unit;\n"
7894        | RInt _ -> pr "  rv = Val_int (r);\n"
7895        | RInt64 _ ->
7896            pr "  rv = caml_copy_int64 (r);\n"
7897        | RBool _ -> pr "  rv = Val_bool (r);\n"
7898        | RConstString _ ->
7899            pr "  rv = caml_copy_string (r);\n"
7900        | RConstOptString _ ->
7901            pr "  if (r) { /* Some string */\n";
7902            pr "    v = caml_alloc (1, 0);\n";
7903            pr "    v2 = caml_copy_string (r);\n";
7904            pr "    Store_field (v, 0, v2);\n";
7905            pr "  } else /* None */\n";
7906            pr "    v = Val_int (0);\n";
7907        | RString _ ->
7908            pr "  rv = caml_copy_string (r);\n";
7909            pr "  free (r);\n"
7910        | RStringList _ ->
7911            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7912            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7913            pr "  free (r);\n"
7914        | RStruct (_, typ) ->
7915            pr "  rv = copy_%s (r);\n" typ;
7916            pr "  guestfs_free_%s (r);\n" typ;
7917        | RStructList (_, typ) ->
7918            pr "  rv = copy_%s_list (r);\n" typ;
7919            pr "  guestfs_free_%s_list (r);\n" typ;
7920        | RHashtable _ ->
7921            pr "  rv = copy_table (r);\n";
7922            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7923            pr "  free (r);\n";
7924        | RBufferOut _ ->
7925            pr "  rv = caml_alloc_string (size);\n";
7926            pr "  memcpy (String_val (rv), r, size);\n";
7927       );
7928
7929       pr "  CAMLreturn (rv);\n";
7930       pr "}\n";
7931       pr "\n";
7932
7933       if List.length params > 5 then (
7934         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7935         pr "CAMLprim value ";
7936         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7937         pr "CAMLprim value\n";
7938         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7939         pr "{\n";
7940         pr "  return ocaml_guestfs_%s (argv[0]" name;
7941         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7942         pr ");\n";
7943         pr "}\n";
7944         pr "\n"
7945       )
7946   ) all_functions_sorted
7947
7948 and generate_ocaml_structure_decls () =
7949   List.iter (
7950     fun (typ, cols) ->
7951       pr "type %s = {\n" typ;
7952       List.iter (
7953         function
7954         | name, FString -> pr "  %s : string;\n" name
7955         | name, FBuffer -> pr "  %s : string;\n" name
7956         | name, FUUID -> pr "  %s : string;\n" name
7957         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7958         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7959         | name, FChar -> pr "  %s : char;\n" name
7960         | name, FOptPercent -> pr "  %s : float option;\n" name
7961       ) cols;
7962       pr "}\n";
7963       pr "\n"
7964   ) structs
7965
7966 and generate_ocaml_prototype ?(is_external = false) name style =
7967   if is_external then pr "external " else pr "val ";
7968   pr "%s : t -> " name;
7969   List.iter (
7970     function
7971     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7972     | OptString _ -> pr "string option -> "
7973     | StringList _ | DeviceList _ -> pr "string array -> "
7974     | Bool _ -> pr "bool -> "
7975     | Int _ -> pr "int -> "
7976     | Int64 _ -> pr "int64 -> "
7977   ) (snd style);
7978   (match fst style with
7979    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7980    | RInt _ -> pr "int"
7981    | RInt64 _ -> pr "int64"
7982    | RBool _ -> pr "bool"
7983    | RConstString _ -> pr "string"
7984    | RConstOptString _ -> pr "string option"
7985    | RString _ | RBufferOut _ -> pr "string"
7986    | RStringList _ -> pr "string array"
7987    | RStruct (_, typ) -> pr "%s" typ
7988    | RStructList (_, typ) -> pr "%s array" typ
7989    | RHashtable _ -> pr "(string * string) list"
7990   );
7991   if is_external then (
7992     pr " = ";
7993     if List.length (snd style) + 1 > 5 then
7994       pr "\"ocaml_guestfs_%s_byte\" " name;
7995     pr "\"ocaml_guestfs_%s\"" name
7996   );
7997   pr "\n"
7998
7999 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8000 and generate_perl_xs () =
8001   generate_header CStyle LGPLv2plus;
8002
8003   pr "\
8004 #include \"EXTERN.h\"
8005 #include \"perl.h\"
8006 #include \"XSUB.h\"
8007
8008 #include <guestfs.h>
8009
8010 #ifndef PRId64
8011 #define PRId64 \"lld\"
8012 #endif
8013
8014 static SV *
8015 my_newSVll(long long val) {
8016 #ifdef USE_64_BIT_ALL
8017   return newSViv(val);
8018 #else
8019   char buf[100];
8020   int len;
8021   len = snprintf(buf, 100, \"%%\" PRId64, val);
8022   return newSVpv(buf, len);
8023 #endif
8024 }
8025
8026 #ifndef PRIu64
8027 #define PRIu64 \"llu\"
8028 #endif
8029
8030 static SV *
8031 my_newSVull(unsigned long long val) {
8032 #ifdef USE_64_BIT_ALL
8033   return newSVuv(val);
8034 #else
8035   char buf[100];
8036   int len;
8037   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8038   return newSVpv(buf, len);
8039 #endif
8040 }
8041
8042 /* http://www.perlmonks.org/?node_id=680842 */
8043 static char **
8044 XS_unpack_charPtrPtr (SV *arg) {
8045   char **ret;
8046   AV *av;
8047   I32 i;
8048
8049   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8050     croak (\"array reference expected\");
8051
8052   av = (AV *)SvRV (arg);
8053   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8054   if (!ret)
8055     croak (\"malloc failed\");
8056
8057   for (i = 0; i <= av_len (av); i++) {
8058     SV **elem = av_fetch (av, i, 0);
8059
8060     if (!elem || !*elem)
8061       croak (\"missing element in list\");
8062
8063     ret[i] = SvPV_nolen (*elem);
8064   }
8065
8066   ret[i] = NULL;
8067
8068   return ret;
8069 }
8070
8071 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8072
8073 PROTOTYPES: ENABLE
8074
8075 guestfs_h *
8076 _create ()
8077    CODE:
8078       RETVAL = guestfs_create ();
8079       if (!RETVAL)
8080         croak (\"could not create guestfs handle\");
8081       guestfs_set_error_handler (RETVAL, NULL, NULL);
8082  OUTPUT:
8083       RETVAL
8084
8085 void
8086 DESTROY (g)
8087       guestfs_h *g;
8088  PPCODE:
8089       guestfs_close (g);
8090
8091 ";
8092
8093   List.iter (
8094     fun (name, style, _, _, _, _, _) ->
8095       (match fst style with
8096        | RErr -> pr "void\n"
8097        | RInt _ -> pr "SV *\n"
8098        | RInt64 _ -> pr "SV *\n"
8099        | RBool _ -> pr "SV *\n"
8100        | RConstString _ -> pr "SV *\n"
8101        | RConstOptString _ -> pr "SV *\n"
8102        | RString _ -> pr "SV *\n"
8103        | RBufferOut _ -> pr "SV *\n"
8104        | RStringList _
8105        | RStruct _ | RStructList _
8106        | RHashtable _ ->
8107            pr "void\n" (* all lists returned implictly on the stack *)
8108       );
8109       (* Call and arguments. *)
8110       pr "%s " name;
8111       generate_c_call_args ~handle:"g" ~decl:true style;
8112       pr "\n";
8113       pr "      guestfs_h *g;\n";
8114       iteri (
8115         fun i ->
8116           function
8117           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8118               pr "      char *%s;\n" n
8119           | OptString n ->
8120               (* http://www.perlmonks.org/?node_id=554277
8121                * Note that the implicit handle argument means we have
8122                * to add 1 to the ST(x) operator.
8123                *)
8124               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8125           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8126           | Bool n -> pr "      int %s;\n" n
8127           | Int n -> pr "      int %s;\n" n
8128           | Int64 n -> pr "      int64_t %s;\n" n
8129       ) (snd style);
8130
8131       let do_cleanups () =
8132         List.iter (
8133           function
8134           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8135           | Bool _ | Int _ | Int64 _
8136           | FileIn _ | FileOut _ -> ()
8137           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8138         ) (snd style)
8139       in
8140
8141       (* Code. *)
8142       (match fst style with
8143        | RErr ->
8144            pr "PREINIT:\n";
8145            pr "      int r;\n";
8146            pr " PPCODE:\n";
8147            pr "      r = guestfs_%s " name;
8148            generate_c_call_args ~handle:"g" style;
8149            pr ";\n";
8150            do_cleanups ();
8151            pr "      if (r == -1)\n";
8152            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8153        | RInt n
8154        | RBool n ->
8155            pr "PREINIT:\n";
8156            pr "      int %s;\n" n;
8157            pr "   CODE:\n";
8158            pr "      %s = guestfs_%s " n name;
8159            generate_c_call_args ~handle:"g" style;
8160            pr ";\n";
8161            do_cleanups ();
8162            pr "      if (%s == -1)\n" n;
8163            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8164            pr "      RETVAL = newSViv (%s);\n" n;
8165            pr " OUTPUT:\n";
8166            pr "      RETVAL\n"
8167        | RInt64 n ->
8168            pr "PREINIT:\n";
8169            pr "      int64_t %s;\n" n;
8170            pr "   CODE:\n";
8171            pr "      %s = guestfs_%s " n name;
8172            generate_c_call_args ~handle:"g" style;
8173            pr ";\n";
8174            do_cleanups ();
8175            pr "      if (%s == -1)\n" n;
8176            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8177            pr "      RETVAL = my_newSVll (%s);\n" n;
8178            pr " OUTPUT:\n";
8179            pr "      RETVAL\n"
8180        | RConstString n ->
8181            pr "PREINIT:\n";
8182            pr "      const char *%s;\n" n;
8183            pr "   CODE:\n";
8184            pr "      %s = guestfs_%s " n name;
8185            generate_c_call_args ~handle:"g" style;
8186            pr ";\n";
8187            do_cleanups ();
8188            pr "      if (%s == NULL)\n" n;
8189            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8190            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8191            pr " OUTPUT:\n";
8192            pr "      RETVAL\n"
8193        | RConstOptString n ->
8194            pr "PREINIT:\n";
8195            pr "      const char *%s;\n" n;
8196            pr "   CODE:\n";
8197            pr "      %s = guestfs_%s " n name;
8198            generate_c_call_args ~handle:"g" style;
8199            pr ";\n";
8200            do_cleanups ();
8201            pr "      if (%s == NULL)\n" n;
8202            pr "        RETVAL = &PL_sv_undef;\n";
8203            pr "      else\n";
8204            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8205            pr " OUTPUT:\n";
8206            pr "      RETVAL\n"
8207        | RString n ->
8208            pr "PREINIT:\n";
8209            pr "      char *%s;\n" n;
8210            pr "   CODE:\n";
8211            pr "      %s = guestfs_%s " n name;
8212            generate_c_call_args ~handle:"g" style;
8213            pr ";\n";
8214            do_cleanups ();
8215            pr "      if (%s == NULL)\n" n;
8216            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8217            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8218            pr "      free (%s);\n" n;
8219            pr " OUTPUT:\n";
8220            pr "      RETVAL\n"
8221        | RStringList n | RHashtable n ->
8222            pr "PREINIT:\n";
8223            pr "      char **%s;\n" n;
8224            pr "      int i, n;\n";
8225            pr " PPCODE:\n";
8226            pr "      %s = guestfs_%s " n name;
8227            generate_c_call_args ~handle:"g" style;
8228            pr ";\n";
8229            do_cleanups ();
8230            pr "      if (%s == NULL)\n" n;
8231            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8232            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8233            pr "      EXTEND (SP, n);\n";
8234            pr "      for (i = 0; i < n; ++i) {\n";
8235            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8236            pr "        free (%s[i]);\n" n;
8237            pr "      }\n";
8238            pr "      free (%s);\n" n;
8239        | RStruct (n, typ) ->
8240            let cols = cols_of_struct typ in
8241            generate_perl_struct_code typ cols name style n do_cleanups
8242        | RStructList (n, typ) ->
8243            let cols = cols_of_struct typ in
8244            generate_perl_struct_list_code typ cols name style n do_cleanups
8245        | RBufferOut n ->
8246            pr "PREINIT:\n";
8247            pr "      char *%s;\n" n;
8248            pr "      size_t size;\n";
8249            pr "   CODE:\n";
8250            pr "      %s = guestfs_%s " n name;
8251            generate_c_call_args ~handle:"g" style;
8252            pr ";\n";
8253            do_cleanups ();
8254            pr "      if (%s == NULL)\n" n;
8255            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8256            pr "      RETVAL = newSVpv (%s, size);\n" n;
8257            pr "      free (%s);\n" n;
8258            pr " OUTPUT:\n";
8259            pr "      RETVAL\n"
8260       );
8261
8262       pr "\n"
8263   ) all_functions
8264
8265 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8266   pr "PREINIT:\n";
8267   pr "      struct guestfs_%s_list *%s;\n" typ n;
8268   pr "      int i;\n";
8269   pr "      HV *hv;\n";
8270   pr " PPCODE:\n";
8271   pr "      %s = guestfs_%s " n name;
8272   generate_c_call_args ~handle:"g" style;
8273   pr ";\n";
8274   do_cleanups ();
8275   pr "      if (%s == NULL)\n" n;
8276   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8277   pr "      EXTEND (SP, %s->len);\n" n;
8278   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8279   pr "        hv = newHV ();\n";
8280   List.iter (
8281     function
8282     | name, FString ->
8283         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8284           name (String.length name) n name
8285     | name, FUUID ->
8286         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8287           name (String.length name) n name
8288     | name, FBuffer ->
8289         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8290           name (String.length name) n name n name
8291     | name, (FBytes|FUInt64) ->
8292         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8293           name (String.length name) n name
8294     | name, FInt64 ->
8295         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8296           name (String.length name) n name
8297     | name, (FInt32|FUInt32) ->
8298         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8299           name (String.length name) n name
8300     | name, FChar ->
8301         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8302           name (String.length name) n name
8303     | name, FOptPercent ->
8304         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8305           name (String.length name) n name
8306   ) cols;
8307   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8308   pr "      }\n";
8309   pr "      guestfs_free_%s_list (%s);\n" typ n
8310
8311 and generate_perl_struct_code typ cols name style n do_cleanups =
8312   pr "PREINIT:\n";
8313   pr "      struct guestfs_%s *%s;\n" typ n;
8314   pr " PPCODE:\n";
8315   pr "      %s = guestfs_%s " n name;
8316   generate_c_call_args ~handle:"g" style;
8317   pr ";\n";
8318   do_cleanups ();
8319   pr "      if (%s == NULL)\n" n;
8320   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8321   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8322   List.iter (
8323     fun ((name, _) as col) ->
8324       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8325
8326       match col with
8327       | name, FString ->
8328           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8329             n name
8330       | name, FBuffer ->
8331           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8332             n name n name
8333       | name, FUUID ->
8334           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8335             n name
8336       | name, (FBytes|FUInt64) ->
8337           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8338             n name
8339       | name, FInt64 ->
8340           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8341             n name
8342       | name, (FInt32|FUInt32) ->
8343           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8344             n name
8345       | name, FChar ->
8346           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8347             n name
8348       | name, FOptPercent ->
8349           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8350             n name
8351   ) cols;
8352   pr "      free (%s);\n" n
8353
8354 (* Generate Sys/Guestfs.pm. *)
8355 and generate_perl_pm () =
8356   generate_header HashStyle LGPLv2plus;
8357
8358   pr "\
8359 =pod
8360
8361 =head1 NAME
8362
8363 Sys::Guestfs - Perl bindings for libguestfs
8364
8365 =head1 SYNOPSIS
8366
8367  use Sys::Guestfs;
8368
8369  my $h = Sys::Guestfs->new ();
8370  $h->add_drive ('guest.img');
8371  $h->launch ();
8372  $h->mount ('/dev/sda1', '/');
8373  $h->touch ('/hello');
8374  $h->sync ();
8375
8376 =head1 DESCRIPTION
8377
8378 The C<Sys::Guestfs> module provides a Perl XS binding to the
8379 libguestfs API for examining and modifying virtual machine
8380 disk images.
8381
8382 Amongst the things this is good for: making batch configuration
8383 changes to guests, getting disk used/free statistics (see also:
8384 virt-df), migrating between virtualization systems (see also:
8385 virt-p2v), performing partial backups, performing partial guest
8386 clones, cloning guests and changing registry/UUID/hostname info, and
8387 much else besides.
8388
8389 Libguestfs uses Linux kernel and qemu code, and can access any type of
8390 guest filesystem that Linux and qemu can, including but not limited
8391 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8392 schemes, qcow, qcow2, vmdk.
8393
8394 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8395 LVs, what filesystem is in each LV, etc.).  It can also run commands
8396 in the context of the guest.  Also you can access filesystems over FTP.
8397
8398 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8399 functions for using libguestfs from Perl, including integration
8400 with libvirt.
8401
8402 =head1 ERRORS
8403
8404 All errors turn into calls to C<croak> (see L<Carp(3)>).
8405
8406 =head1 METHODS
8407
8408 =over 4
8409
8410 =cut
8411
8412 package Sys::Guestfs;
8413
8414 use strict;
8415 use warnings;
8416
8417 require XSLoader;
8418 XSLoader::load ('Sys::Guestfs');
8419
8420 =item $h = Sys::Guestfs->new ();
8421
8422 Create a new guestfs handle.
8423
8424 =cut
8425
8426 sub new {
8427   my $proto = shift;
8428   my $class = ref ($proto) || $proto;
8429
8430   my $self = Sys::Guestfs::_create ();
8431   bless $self, $class;
8432   return $self;
8433 }
8434
8435 ";
8436
8437   (* Actions.  We only need to print documentation for these as
8438    * they are pulled in from the XS code automatically.
8439    *)
8440   List.iter (
8441     fun (name, style, _, flags, _, _, longdesc) ->
8442       if not (List.mem NotInDocs flags) then (
8443         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8444         pr "=item ";
8445         generate_perl_prototype name style;
8446         pr "\n\n";
8447         pr "%s\n\n" longdesc;
8448         if List.mem ProtocolLimitWarning flags then
8449           pr "%s\n\n" protocol_limit_warning;
8450         if List.mem DangerWillRobinson flags then
8451           pr "%s\n\n" danger_will_robinson;
8452         match deprecation_notice flags with
8453         | None -> ()
8454         | Some txt -> pr "%s\n\n" txt
8455       )
8456   ) all_functions_sorted;
8457
8458   (* End of file. *)
8459   pr "\
8460 =cut
8461
8462 1;
8463
8464 =back
8465
8466 =head1 COPYRIGHT
8467
8468 Copyright (C) %s Red Hat Inc.
8469
8470 =head1 LICENSE
8471
8472 Please see the file COPYING.LIB for the full license.
8473
8474 =head1 SEE ALSO
8475
8476 L<guestfs(3)>,
8477 L<guestfish(1)>,
8478 L<http://libguestfs.org>,
8479 L<Sys::Guestfs::Lib(3)>.
8480
8481 =cut
8482 " copyright_years
8483
8484 and generate_perl_prototype name style =
8485   (match fst style with
8486    | RErr -> ()
8487    | RBool n
8488    | RInt n
8489    | RInt64 n
8490    | RConstString n
8491    | RConstOptString n
8492    | RString n
8493    | RBufferOut n -> pr "$%s = " n
8494    | RStruct (n,_)
8495    | RHashtable n -> pr "%%%s = " n
8496    | RStringList n
8497    | RStructList (n,_) -> pr "@%s = " n
8498   );
8499   pr "$h->%s (" name;
8500   let comma = ref false in
8501   List.iter (
8502     fun arg ->
8503       if !comma then pr ", ";
8504       comma := true;
8505       match arg with
8506       | Pathname n | Device n | Dev_or_Path n | String n
8507       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8508           pr "$%s" n
8509       | StringList n | DeviceList n ->
8510           pr "\\@%s" n
8511   ) (snd style);
8512   pr ");"
8513
8514 (* Generate Python C module. *)
8515 and generate_python_c () =
8516   generate_header CStyle LGPLv2plus;
8517
8518   pr "\
8519 #include <Python.h>
8520
8521 #include <stdio.h>
8522 #include <stdlib.h>
8523 #include <assert.h>
8524
8525 #include \"guestfs.h\"
8526
8527 typedef struct {
8528   PyObject_HEAD
8529   guestfs_h *g;
8530 } Pyguestfs_Object;
8531
8532 static guestfs_h *
8533 get_handle (PyObject *obj)
8534 {
8535   assert (obj);
8536   assert (obj != Py_None);
8537   return ((Pyguestfs_Object *) obj)->g;
8538 }
8539
8540 static PyObject *
8541 put_handle (guestfs_h *g)
8542 {
8543   assert (g);
8544   return
8545     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8546 }
8547
8548 /* This list should be freed (but not the strings) after use. */
8549 static char **
8550 get_string_list (PyObject *obj)
8551 {
8552   int i, len;
8553   char **r;
8554
8555   assert (obj);
8556
8557   if (!PyList_Check (obj)) {
8558     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8559     return NULL;
8560   }
8561
8562   len = PyList_Size (obj);
8563   r = malloc (sizeof (char *) * (len+1));
8564   if (r == NULL) {
8565     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8566     return NULL;
8567   }
8568
8569   for (i = 0; i < len; ++i)
8570     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8571   r[len] = NULL;
8572
8573   return r;
8574 }
8575
8576 static PyObject *
8577 put_string_list (char * const * const argv)
8578 {
8579   PyObject *list;
8580   int argc, i;
8581
8582   for (argc = 0; argv[argc] != NULL; ++argc)
8583     ;
8584
8585   list = PyList_New (argc);
8586   for (i = 0; i < argc; ++i)
8587     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8588
8589   return list;
8590 }
8591
8592 static PyObject *
8593 put_table (char * const * const argv)
8594 {
8595   PyObject *list, *item;
8596   int argc, i;
8597
8598   for (argc = 0; argv[argc] != NULL; ++argc)
8599     ;
8600
8601   list = PyList_New (argc >> 1);
8602   for (i = 0; i < argc; i += 2) {
8603     item = PyTuple_New (2);
8604     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8605     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8606     PyList_SetItem (list, i >> 1, item);
8607   }
8608
8609   return list;
8610 }
8611
8612 static void
8613 free_strings (char **argv)
8614 {
8615   int argc;
8616
8617   for (argc = 0; argv[argc] != NULL; ++argc)
8618     free (argv[argc]);
8619   free (argv);
8620 }
8621
8622 static PyObject *
8623 py_guestfs_create (PyObject *self, PyObject *args)
8624 {
8625   guestfs_h *g;
8626
8627   g = guestfs_create ();
8628   if (g == NULL) {
8629     PyErr_SetString (PyExc_RuntimeError,
8630                      \"guestfs.create: failed to allocate handle\");
8631     return NULL;
8632   }
8633   guestfs_set_error_handler (g, NULL, NULL);
8634   return put_handle (g);
8635 }
8636
8637 static PyObject *
8638 py_guestfs_close (PyObject *self, PyObject *args)
8639 {
8640   PyObject *py_g;
8641   guestfs_h *g;
8642
8643   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8644     return NULL;
8645   g = get_handle (py_g);
8646
8647   guestfs_close (g);
8648
8649   Py_INCREF (Py_None);
8650   return Py_None;
8651 }
8652
8653 ";
8654
8655   let emit_put_list_function typ =
8656     pr "static PyObject *\n";
8657     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8658     pr "{\n";
8659     pr "  PyObject *list;\n";
8660     pr "  int i;\n";
8661     pr "\n";
8662     pr "  list = PyList_New (%ss->len);\n" typ;
8663     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8664     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8665     pr "  return list;\n";
8666     pr "};\n";
8667     pr "\n"
8668   in
8669
8670   (* Structures, turned into Python dictionaries. *)
8671   List.iter (
8672     fun (typ, cols) ->
8673       pr "static PyObject *\n";
8674       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8675       pr "{\n";
8676       pr "  PyObject *dict;\n";
8677       pr "\n";
8678       pr "  dict = PyDict_New ();\n";
8679       List.iter (
8680         function
8681         | name, FString ->
8682             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8683             pr "                        PyString_FromString (%s->%s));\n"
8684               typ name
8685         | name, FBuffer ->
8686             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8687             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8688               typ name typ name
8689         | name, FUUID ->
8690             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8691             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8692               typ name
8693         | name, (FBytes|FUInt64) ->
8694             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8695             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8696               typ name
8697         | name, FInt64 ->
8698             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8699             pr "                        PyLong_FromLongLong (%s->%s));\n"
8700               typ name
8701         | name, FUInt32 ->
8702             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8703             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8704               typ name
8705         | name, FInt32 ->
8706             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8707             pr "                        PyLong_FromLong (%s->%s));\n"
8708               typ name
8709         | name, FOptPercent ->
8710             pr "  if (%s->%s >= 0)\n" typ name;
8711             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8712             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8713               typ name;
8714             pr "  else {\n";
8715             pr "    Py_INCREF (Py_None);\n";
8716             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8717             pr "  }\n"
8718         | name, FChar ->
8719             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8720             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8721       ) cols;
8722       pr "  return dict;\n";
8723       pr "};\n";
8724       pr "\n";
8725
8726   ) structs;
8727
8728   (* Emit a put_TYPE_list function definition only if that function is used. *)
8729   List.iter (
8730     function
8731     | typ, (RStructListOnly | RStructAndList) ->
8732         (* generate the function for typ *)
8733         emit_put_list_function typ
8734     | typ, _ -> () (* empty *)
8735   ) (rstructs_used_by all_functions);
8736
8737   (* Python wrapper functions. *)
8738   List.iter (
8739     fun (name, style, _, _, _, _, _) ->
8740       pr "static PyObject *\n";
8741       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8742       pr "{\n";
8743
8744       pr "  PyObject *py_g;\n";
8745       pr "  guestfs_h *g;\n";
8746       pr "  PyObject *py_r;\n";
8747
8748       let error_code =
8749         match fst style with
8750         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8751         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8752         | RConstString _ | RConstOptString _ ->
8753             pr "  const char *r;\n"; "NULL"
8754         | RString _ -> pr "  char *r;\n"; "NULL"
8755         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8756         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8757         | RStructList (_, typ) ->
8758             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8759         | RBufferOut _ ->
8760             pr "  char *r;\n";
8761             pr "  size_t size;\n";
8762             "NULL" in
8763
8764       List.iter (
8765         function
8766         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8767             pr "  const char *%s;\n" n
8768         | OptString n -> pr "  const char *%s;\n" n
8769         | StringList n | DeviceList n ->
8770             pr "  PyObject *py_%s;\n" n;
8771             pr "  char **%s;\n" n
8772         | Bool n -> pr "  int %s;\n" n
8773         | Int n -> pr "  int %s;\n" n
8774         | Int64 n -> pr "  long long %s;\n" n
8775       ) (snd style);
8776
8777       pr "\n";
8778
8779       (* Convert the parameters. *)
8780       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8781       List.iter (
8782         function
8783         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8784         | OptString _ -> pr "z"
8785         | StringList _ | DeviceList _ -> pr "O"
8786         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8787         | Int _ -> pr "i"
8788         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8789                              * emulate C's int/long/long long in Python?
8790                              *)
8791       ) (snd style);
8792       pr ":guestfs_%s\",\n" name;
8793       pr "                         &py_g";
8794       List.iter (
8795         function
8796         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8797         | OptString n -> pr ", &%s" n
8798         | StringList n | DeviceList n -> pr ", &py_%s" n
8799         | Bool n -> pr ", &%s" n
8800         | Int n -> pr ", &%s" n
8801         | Int64 n -> pr ", &%s" n
8802       ) (snd style);
8803
8804       pr "))\n";
8805       pr "    return NULL;\n";
8806
8807       pr "  g = get_handle (py_g);\n";
8808       List.iter (
8809         function
8810         | Pathname _ | Device _ | Dev_or_Path _ | String _
8811         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8812         | StringList n | DeviceList n ->
8813             pr "  %s = get_string_list (py_%s);\n" n n;
8814             pr "  if (!%s) return NULL;\n" n
8815       ) (snd style);
8816
8817       pr "\n";
8818
8819       pr "  r = guestfs_%s " name;
8820       generate_c_call_args ~handle:"g" style;
8821       pr ";\n";
8822
8823       List.iter (
8824         function
8825         | Pathname _ | Device _ | Dev_or_Path _ | String _
8826         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8827         | StringList n | DeviceList n ->
8828             pr "  free (%s);\n" n
8829       ) (snd style);
8830
8831       pr "  if (r == %s) {\n" error_code;
8832       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8833       pr "    return NULL;\n";
8834       pr "  }\n";
8835       pr "\n";
8836
8837       (match fst style with
8838        | RErr ->
8839            pr "  Py_INCREF (Py_None);\n";
8840            pr "  py_r = Py_None;\n"
8841        | RInt _
8842        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8843        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8844        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8845        | RConstOptString _ ->
8846            pr "  if (r)\n";
8847            pr "    py_r = PyString_FromString (r);\n";
8848            pr "  else {\n";
8849            pr "    Py_INCREF (Py_None);\n";
8850            pr "    py_r = Py_None;\n";
8851            pr "  }\n"
8852        | RString _ ->
8853            pr "  py_r = PyString_FromString (r);\n";
8854            pr "  free (r);\n"
8855        | RStringList _ ->
8856            pr "  py_r = put_string_list (r);\n";
8857            pr "  free_strings (r);\n"
8858        | RStruct (_, typ) ->
8859            pr "  py_r = put_%s (r);\n" typ;
8860            pr "  guestfs_free_%s (r);\n" typ
8861        | RStructList (_, typ) ->
8862            pr "  py_r = put_%s_list (r);\n" typ;
8863            pr "  guestfs_free_%s_list (r);\n" typ
8864        | RHashtable n ->
8865            pr "  py_r = put_table (r);\n";
8866            pr "  free_strings (r);\n"
8867        | RBufferOut _ ->
8868            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8869            pr "  free (r);\n"
8870       );
8871
8872       pr "  return py_r;\n";
8873       pr "}\n";
8874       pr "\n"
8875   ) all_functions;
8876
8877   (* Table of functions. *)
8878   pr "static PyMethodDef methods[] = {\n";
8879   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8880   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8881   List.iter (
8882     fun (name, _, _, _, _, _, _) ->
8883       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8884         name name
8885   ) all_functions;
8886   pr "  { NULL, NULL, 0, NULL }\n";
8887   pr "};\n";
8888   pr "\n";
8889
8890   (* Init function. *)
8891   pr "\
8892 void
8893 initlibguestfsmod (void)
8894 {
8895   static int initialized = 0;
8896
8897   if (initialized) return;
8898   Py_InitModule ((char *) \"libguestfsmod\", methods);
8899   initialized = 1;
8900 }
8901 "
8902
8903 (* Generate Python module. *)
8904 and generate_python_py () =
8905   generate_header HashStyle LGPLv2plus;
8906
8907   pr "\
8908 u\"\"\"Python bindings for libguestfs
8909
8910 import guestfs
8911 g = guestfs.GuestFS ()
8912 g.add_drive (\"guest.img\")
8913 g.launch ()
8914 parts = g.list_partitions ()
8915
8916 The guestfs module provides a Python binding to the libguestfs API
8917 for examining and modifying virtual machine disk images.
8918
8919 Amongst the things this is good for: making batch configuration
8920 changes to guests, getting disk used/free statistics (see also:
8921 virt-df), migrating between virtualization systems (see also:
8922 virt-p2v), performing partial backups, performing partial guest
8923 clones, cloning guests and changing registry/UUID/hostname info, and
8924 much else besides.
8925
8926 Libguestfs uses Linux kernel and qemu code, and can access any type of
8927 guest filesystem that Linux and qemu can, including but not limited
8928 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8929 schemes, qcow, qcow2, vmdk.
8930
8931 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8932 LVs, what filesystem is in each LV, etc.).  It can also run commands
8933 in the context of the guest.  Also you can access filesystems over FTP.
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