Remove references to FTP, replace with FUSE.
[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, see
4708 L<guestfs(3)/UPLOADING>."
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.
5217    *)
5218   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5219   pr "\n";
5220
5221   (* Message header, etc. *)
5222   pr "\
5223 /* The communication protocol is now documented in the guestfs(3)
5224  * manpage.
5225  */
5226
5227 const GUESTFS_PROGRAM = 0x2000F5F5;
5228 const GUESTFS_PROTOCOL_VERSION = 1;
5229
5230 /* These constants must be larger than any possible message length. */
5231 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5232 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5233
5234 enum guestfs_message_direction {
5235   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5236   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5237 };
5238
5239 enum guestfs_message_status {
5240   GUESTFS_STATUS_OK = 0,
5241   GUESTFS_STATUS_ERROR = 1
5242 };
5243
5244 const GUESTFS_ERROR_LEN = 256;
5245
5246 struct guestfs_message_error {
5247   string error_message<GUESTFS_ERROR_LEN>;
5248 };
5249
5250 struct guestfs_message_header {
5251   unsigned prog;                     /* GUESTFS_PROGRAM */
5252   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5253   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5254   guestfs_message_direction direction;
5255   unsigned serial;                   /* message serial number */
5256   guestfs_message_status status;
5257 };
5258
5259 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5260
5261 struct guestfs_chunk {
5262   int cancel;                        /* if non-zero, transfer is cancelled */
5263   /* data size is 0 bytes if the transfer has finished successfully */
5264   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5265 };
5266 "
5267
5268 (* Generate the guestfs-structs.h file. *)
5269 and generate_structs_h () =
5270   generate_header CStyle LGPLv2plus;
5271
5272   (* This is a public exported header file containing various
5273    * structures.  The structures are carefully written to have
5274    * exactly the same in-memory format as the XDR structures that
5275    * we use on the wire to the daemon.  The reason for creating
5276    * copies of these structures here is just so we don't have to
5277    * export the whole of guestfs_protocol.h (which includes much
5278    * unrelated and XDR-dependent stuff that we don't want to be
5279    * public, or required by clients).
5280    *
5281    * To reiterate, we will pass these structures to and from the
5282    * client with a simple assignment or memcpy, so the format
5283    * must be identical to what rpcgen / the RFC defines.
5284    *)
5285
5286   (* Public structures. *)
5287   List.iter (
5288     fun (typ, cols) ->
5289       pr "struct guestfs_%s {\n" typ;
5290       List.iter (
5291         function
5292         | name, FChar -> pr "  char %s;\n" name
5293         | name, FString -> pr "  char *%s;\n" name
5294         | name, FBuffer ->
5295             pr "  uint32_t %s_len;\n" name;
5296             pr "  char *%s;\n" name
5297         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5298         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5299         | name, FInt32 -> pr "  int32_t %s;\n" name
5300         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5301         | name, FInt64 -> pr "  int64_t %s;\n" name
5302         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5303       ) cols;
5304       pr "};\n";
5305       pr "\n";
5306       pr "struct guestfs_%s_list {\n" typ;
5307       pr "  uint32_t len;\n";
5308       pr "  struct guestfs_%s *val;\n" typ;
5309       pr "};\n";
5310       pr "\n";
5311       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5312       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5313       pr "\n"
5314   ) structs
5315
5316 (* Generate the guestfs-actions.h file. *)
5317 and generate_actions_h () =
5318   generate_header CStyle LGPLv2plus;
5319   List.iter (
5320     fun (shortname, style, _, _, _, _, _) ->
5321       let name = "guestfs_" ^ shortname in
5322       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5323         name style
5324   ) all_functions
5325
5326 (* Generate the guestfs-internal-actions.h file. *)
5327 and generate_internal_actions_h () =
5328   generate_header CStyle LGPLv2plus;
5329   List.iter (
5330     fun (shortname, style, _, _, _, _, _) ->
5331       let name = "guestfs__" ^ shortname in
5332       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5333         name style
5334   ) non_daemon_functions
5335
5336 (* Generate the client-side dispatch stubs. *)
5337 and generate_client_actions () =
5338   generate_header CStyle LGPLv2plus;
5339
5340   pr "\
5341 #include <stdio.h>
5342 #include <stdlib.h>
5343 #include <stdint.h>
5344 #include <inttypes.h>
5345
5346 #include \"guestfs.h\"
5347 #include \"guestfs-internal.h\"
5348 #include \"guestfs-internal-actions.h\"
5349 #include \"guestfs_protocol.h\"
5350
5351 #define error guestfs_error
5352 //#define perrorf guestfs_perrorf
5353 #define safe_malloc guestfs_safe_malloc
5354 #define safe_realloc guestfs_safe_realloc
5355 //#define safe_strdup guestfs_safe_strdup
5356 #define safe_memdup guestfs_safe_memdup
5357
5358 /* Check the return message from a call for validity. */
5359 static int
5360 check_reply_header (guestfs_h *g,
5361                     const struct guestfs_message_header *hdr,
5362                     unsigned int proc_nr, unsigned int serial)
5363 {
5364   if (hdr->prog != GUESTFS_PROGRAM) {
5365     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5366     return -1;
5367   }
5368   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5369     error (g, \"wrong protocol version (%%d/%%d)\",
5370            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5371     return -1;
5372   }
5373   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5374     error (g, \"unexpected message direction (%%d/%%d)\",
5375            hdr->direction, GUESTFS_DIRECTION_REPLY);
5376     return -1;
5377   }
5378   if (hdr->proc != proc_nr) {
5379     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5380     return -1;
5381   }
5382   if (hdr->serial != serial) {
5383     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5384     return -1;
5385   }
5386
5387   return 0;
5388 }
5389
5390 /* Check we are in the right state to run a high-level action. */
5391 static int
5392 check_state (guestfs_h *g, const char *caller)
5393 {
5394   if (!guestfs__is_ready (g)) {
5395     if (guestfs__is_config (g) || guestfs__is_launching (g))
5396       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5397         caller);
5398     else
5399       error (g, \"%%s called from the wrong state, %%d != READY\",
5400         caller, guestfs__get_state (g));
5401     return -1;
5402   }
5403   return 0;
5404 }
5405
5406 ";
5407
5408   (* Generate code to generate guestfish call traces. *)
5409   let trace_call shortname style =
5410     pr "  if (guestfs__get_trace (g)) {\n";
5411
5412     let needs_i =
5413       List.exists (function
5414                    | StringList _ | DeviceList _ -> true
5415                    | _ -> false) (snd style) in
5416     if needs_i then (
5417       pr "    int i;\n";
5418       pr "\n"
5419     );
5420
5421     pr "    printf (\"%s\");\n" shortname;
5422     List.iter (
5423       function
5424       | String n                        (* strings *)
5425       | Device n
5426       | Pathname n
5427       | Dev_or_Path n
5428       | FileIn n
5429       | FileOut n ->
5430           (* guestfish doesn't support string escaping, so neither do we *)
5431           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5432       | OptString n ->                  (* string option *)
5433           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5434           pr "    else printf (\" null\");\n"
5435       | StringList n
5436       | DeviceList n ->                 (* string list *)
5437           pr "    putchar (' ');\n";
5438           pr "    putchar ('\"');\n";
5439           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5440           pr "      if (i > 0) putchar (' ');\n";
5441           pr "      fputs (%s[i], stdout);\n" n;
5442           pr "    }\n";
5443           pr "    putchar ('\"');\n";
5444       | Bool n ->                       (* boolean *)
5445           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5446       | Int n ->                        (* int *)
5447           pr "    printf (\" %%d\", %s);\n" n
5448       | Int64 n ->
5449           pr "    printf (\" %%\" PRIi64, %s);\n" n
5450     ) (snd style);
5451     pr "    putchar ('\\n');\n";
5452     pr "  }\n";
5453     pr "\n";
5454   in
5455
5456   (* For non-daemon functions, generate a wrapper around each function. *)
5457   List.iter (
5458     fun (shortname, style, _, _, _, _, _) ->
5459       let name = "guestfs_" ^ shortname in
5460
5461       generate_prototype ~extern:false ~semicolon:false ~newline:true
5462         ~handle:"g" name style;
5463       pr "{\n";
5464       trace_call shortname style;
5465       pr "  return guestfs__%s " shortname;
5466       generate_c_call_args ~handle:"g" style;
5467       pr ";\n";
5468       pr "}\n";
5469       pr "\n"
5470   ) non_daemon_functions;
5471
5472   (* Client-side stubs for each function. *)
5473   List.iter (
5474     fun (shortname, style, _, _, _, _, _) ->
5475       let name = "guestfs_" ^ shortname in
5476
5477       (* Generate the action stub. *)
5478       generate_prototype ~extern:false ~semicolon:false ~newline:true
5479         ~handle:"g" name style;
5480
5481       let error_code =
5482         match fst style with
5483         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5484         | RConstString _ | RConstOptString _ ->
5485             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5486         | RString _ | RStringList _
5487         | RStruct _ | RStructList _
5488         | RHashtable _ | RBufferOut _ ->
5489             "NULL" in
5490
5491       pr "{\n";
5492
5493       (match snd style with
5494        | [] -> ()
5495        | _ -> pr "  struct %s_args args;\n" name
5496       );
5497
5498       pr "  guestfs_message_header hdr;\n";
5499       pr "  guestfs_message_error err;\n";
5500       let has_ret =
5501         match fst style with
5502         | RErr -> false
5503         | RConstString _ | RConstOptString _ ->
5504             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5505         | RInt _ | RInt64 _
5506         | RBool _ | RString _ | RStringList _
5507         | RStruct _ | RStructList _
5508         | RHashtable _ | RBufferOut _ ->
5509             pr "  struct %s_ret ret;\n" name;
5510             true in
5511
5512       pr "  int serial;\n";
5513       pr "  int r;\n";
5514       pr "\n";
5515       trace_call shortname style;
5516       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5517       pr "  guestfs___set_busy (g);\n";
5518       pr "\n";
5519
5520       (* Send the main header and arguments. *)
5521       (match snd style with
5522        | [] ->
5523            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5524              (String.uppercase shortname)
5525        | args ->
5526            List.iter (
5527              function
5528              | Pathname n | Device n | Dev_or_Path n | String n ->
5529                  pr "  args.%s = (char *) %s;\n" n n
5530              | OptString n ->
5531                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5532              | StringList n | DeviceList n ->
5533                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5534                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5535              | Bool n ->
5536                  pr "  args.%s = %s;\n" n n
5537              | Int n ->
5538                  pr "  args.%s = %s;\n" n n
5539              | Int64 n ->
5540                  pr "  args.%s = %s;\n" n n
5541              | FileIn _ | FileOut _ -> ()
5542            ) args;
5543            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5544              (String.uppercase shortname);
5545            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5546              name;
5547       );
5548       pr "  if (serial == -1) {\n";
5549       pr "    guestfs___end_busy (g);\n";
5550       pr "    return %s;\n" error_code;
5551       pr "  }\n";
5552       pr "\n";
5553
5554       (* Send any additional files (FileIn) requested. *)
5555       let need_read_reply_label = ref false in
5556       List.iter (
5557         function
5558         | FileIn n ->
5559             pr "  r = guestfs___send_file (g, %s);\n" n;
5560             pr "  if (r == -1) {\n";
5561             pr "    guestfs___end_busy (g);\n";
5562             pr "    return %s;\n" error_code;
5563             pr "  }\n";
5564             pr "  if (r == -2) /* daemon cancelled */\n";
5565             pr "    goto read_reply;\n";
5566             need_read_reply_label := true;
5567             pr "\n";
5568         | _ -> ()
5569       ) (snd style);
5570
5571       (* Wait for the reply from the remote end. *)
5572       if !need_read_reply_label then pr " read_reply:\n";
5573       pr "  memset (&hdr, 0, sizeof hdr);\n";
5574       pr "  memset (&err, 0, sizeof err);\n";
5575       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5576       pr "\n";
5577       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5578       if not has_ret then
5579         pr "NULL, NULL"
5580       else
5581         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5582       pr ");\n";
5583
5584       pr "  if (r == -1) {\n";
5585       pr "    guestfs___end_busy (g);\n";
5586       pr "    return %s;\n" error_code;
5587       pr "  }\n";
5588       pr "\n";
5589
5590       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5591         (String.uppercase shortname);
5592       pr "    guestfs___end_busy (g);\n";
5593       pr "    return %s;\n" error_code;
5594       pr "  }\n";
5595       pr "\n";
5596
5597       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5598       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5599       pr "    free (err.error_message);\n";
5600       pr "    guestfs___end_busy (g);\n";
5601       pr "    return %s;\n" error_code;
5602       pr "  }\n";
5603       pr "\n";
5604
5605       (* Expecting to receive further files (FileOut)? *)
5606       List.iter (
5607         function
5608         | FileOut n ->
5609             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5610             pr "    guestfs___end_busy (g);\n";
5611             pr "    return %s;\n" error_code;
5612             pr "  }\n";
5613             pr "\n";
5614         | _ -> ()
5615       ) (snd style);
5616
5617       pr "  guestfs___end_busy (g);\n";
5618
5619       (match fst style with
5620        | RErr -> pr "  return 0;\n"
5621        | RInt n | RInt64 n | RBool n ->
5622            pr "  return ret.%s;\n" n
5623        | RConstString _ | RConstOptString _ ->
5624            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5625        | RString n ->
5626            pr "  return ret.%s; /* caller will free */\n" n
5627        | RStringList n | RHashtable n ->
5628            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5629            pr "  ret.%s.%s_val =\n" n n;
5630            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5631            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5632              n n;
5633            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5634            pr "  return ret.%s.%s_val;\n" n n
5635        | RStruct (n, _) ->
5636            pr "  /* caller will free this */\n";
5637            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5638        | RStructList (n, _) ->
5639            pr "  /* caller will free this */\n";
5640            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5641        | RBufferOut n ->
5642            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5643            pr "   * _val might be NULL here.  To make the API saner for\n";
5644            pr "   * callers, we turn this case into a unique pointer (using\n";
5645            pr "   * malloc(1)).\n";
5646            pr "   */\n";
5647            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5648            pr "    *size_r = ret.%s.%s_len;\n" n n;
5649            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5650            pr "  } else {\n";
5651            pr "    free (ret.%s.%s_val);\n" n n;
5652            pr "    char *p = safe_malloc (g, 1);\n";
5653            pr "    *size_r = ret.%s.%s_len;\n" n n;
5654            pr "    return p;\n";
5655            pr "  }\n";
5656       );
5657
5658       pr "}\n\n"
5659   ) daemon_functions;
5660
5661   (* Functions to free structures. *)
5662   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5663   pr " * structure format is identical to the XDR format.  See note in\n";
5664   pr " * generator.ml.\n";
5665   pr " */\n";
5666   pr "\n";
5667
5668   List.iter (
5669     fun (typ, _) ->
5670       pr "void\n";
5671       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5672       pr "{\n";
5673       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5674       pr "  free (x);\n";
5675       pr "}\n";
5676       pr "\n";
5677
5678       pr "void\n";
5679       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5680       pr "{\n";
5681       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5682       pr "  free (x);\n";
5683       pr "}\n";
5684       pr "\n";
5685
5686   ) structs;
5687
5688 (* Generate daemon/actions.h. *)
5689 and generate_daemon_actions_h () =
5690   generate_header CStyle GPLv2plus;
5691
5692   pr "#include \"../src/guestfs_protocol.h\"\n";
5693   pr "\n";
5694
5695   List.iter (
5696     fun (name, style, _, _, _, _, _) ->
5697       generate_prototype
5698         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5699         name style;
5700   ) daemon_functions
5701
5702 (* Generate the linker script which controls the visibility of
5703  * symbols in the public ABI and ensures no other symbols get
5704  * exported accidentally.
5705  *)
5706 and generate_linker_script () =
5707   generate_header HashStyle GPLv2plus;
5708
5709   let globals = [
5710     "guestfs_create";
5711     "guestfs_close";
5712     "guestfs_get_error_handler";
5713     "guestfs_get_out_of_memory_handler";
5714     "guestfs_last_error";
5715     "guestfs_set_error_handler";
5716     "guestfs_set_launch_done_callback";
5717     "guestfs_set_log_message_callback";
5718     "guestfs_set_out_of_memory_handler";
5719     "guestfs_set_subprocess_quit_callback";
5720
5721     (* Unofficial parts of the API: the bindings code use these
5722      * functions, so it is useful to export them.
5723      *)
5724     "guestfs_safe_calloc";
5725     "guestfs_safe_malloc";
5726   ] in
5727   let functions =
5728     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5729       all_functions in
5730   let structs =
5731     List.concat (
5732       List.map (fun (typ, _) ->
5733                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5734         structs
5735     ) in
5736   let globals = List.sort compare (globals @ functions @ structs) in
5737
5738   pr "{\n";
5739   pr "    global:\n";
5740   List.iter (pr "        %s;\n") globals;
5741   pr "\n";
5742
5743   pr "    local:\n";
5744   pr "        *;\n";
5745   pr "};\n"
5746
5747 (* Generate the server-side stubs. *)
5748 and generate_daemon_actions () =
5749   generate_header CStyle GPLv2plus;
5750
5751   pr "#include <config.h>\n";
5752   pr "\n";
5753   pr "#include <stdio.h>\n";
5754   pr "#include <stdlib.h>\n";
5755   pr "#include <string.h>\n";
5756   pr "#include <inttypes.h>\n";
5757   pr "#include <rpc/types.h>\n";
5758   pr "#include <rpc/xdr.h>\n";
5759   pr "\n";
5760   pr "#include \"daemon.h\"\n";
5761   pr "#include \"c-ctype.h\"\n";
5762   pr "#include \"../src/guestfs_protocol.h\"\n";
5763   pr "#include \"actions.h\"\n";
5764   pr "\n";
5765
5766   List.iter (
5767     fun (name, style, _, _, _, _, _) ->
5768       (* Generate server-side stubs. *)
5769       pr "static void %s_stub (XDR *xdr_in)\n" name;
5770       pr "{\n";
5771       let error_code =
5772         match fst style with
5773         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5774         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5775         | RBool _ -> pr "  int r;\n"; "-1"
5776         | RConstString _ | RConstOptString _ ->
5777             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5778         | RString _ -> pr "  char *r;\n"; "NULL"
5779         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5780         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5781         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5782         | RBufferOut _ ->
5783             pr "  size_t size = 1;\n";
5784             pr "  char *r;\n";
5785             "NULL" in
5786
5787       (match snd style with
5788        | [] -> ()
5789        | args ->
5790            pr "  struct guestfs_%s_args args;\n" name;
5791            List.iter (
5792              function
5793              | Device n | Dev_or_Path n
5794              | Pathname n
5795              | String n -> ()
5796              | OptString n -> pr "  char *%s;\n" n
5797              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5798              | Bool n -> pr "  int %s;\n" n
5799              | Int n -> pr "  int %s;\n" n
5800              | Int64 n -> pr "  int64_t %s;\n" n
5801              | FileIn _ | FileOut _ -> ()
5802            ) args
5803       );
5804       pr "\n";
5805
5806       (match snd style with
5807        | [] -> ()
5808        | args ->
5809            pr "  memset (&args, 0, sizeof args);\n";
5810            pr "\n";
5811            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5812            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5813            pr "    return;\n";
5814            pr "  }\n";
5815            let pr_args n =
5816              pr "  char *%s = args.%s;\n" n n
5817            in
5818            let pr_list_handling_code n =
5819              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5820              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5821              pr "  if (%s == NULL) {\n" n;
5822              pr "    reply_with_perror (\"realloc\");\n";
5823              pr "    goto done;\n";
5824              pr "  }\n";
5825              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5826              pr "  args.%s.%s_val = %s;\n" n n n;
5827            in
5828            List.iter (
5829              function
5830              | Pathname n ->
5831                  pr_args n;
5832                  pr "  ABS_PATH (%s, goto done);\n" n;
5833              | Device n ->
5834                  pr_args n;
5835                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5836              | Dev_or_Path n ->
5837                  pr_args n;
5838                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5839              | String n -> pr_args n
5840              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5841              | StringList n ->
5842                  pr_list_handling_code n;
5843              | DeviceList n ->
5844                  pr_list_handling_code n;
5845                  pr "  /* Ensure that each is a device,\n";
5846                  pr "   * and perform device name translation. */\n";
5847                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5848                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5849                  pr "  }\n";
5850              | Bool n -> pr "  %s = args.%s;\n" n n
5851              | Int n -> pr "  %s = args.%s;\n" n n
5852              | Int64 n -> pr "  %s = args.%s;\n" n n
5853              | FileIn _ | FileOut _ -> ()
5854            ) args;
5855            pr "\n"
5856       );
5857
5858
5859       (* this is used at least for do_equal *)
5860       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5861         (* Emit NEED_ROOT just once, even when there are two or
5862            more Pathname args *)
5863         pr "  NEED_ROOT (goto done);\n";
5864       );
5865
5866       (* Don't want to call the impl with any FileIn or FileOut
5867        * parameters, since these go "outside" the RPC protocol.
5868        *)
5869       let args' =
5870         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5871           (snd style) in
5872       pr "  r = do_%s " name;
5873       generate_c_call_args (fst style, args');
5874       pr ";\n";
5875
5876       (match fst style with
5877        | RErr | RInt _ | RInt64 _ | RBool _
5878        | RConstString _ | RConstOptString _
5879        | RString _ | RStringList _ | RHashtable _
5880        | RStruct (_, _) | RStructList (_, _) ->
5881            pr "  if (r == %s)\n" error_code;
5882            pr "    /* do_%s has already called reply_with_error */\n" name;
5883            pr "    goto done;\n";
5884            pr "\n"
5885        | RBufferOut _ ->
5886            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5887            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5888            pr "   */\n";
5889            pr "  if (size == 1 && r == %s)\n" error_code;
5890            pr "    /* do_%s has already called reply_with_error */\n" name;
5891            pr "    goto done;\n";
5892            pr "\n"
5893       );
5894
5895       (* If there are any FileOut parameters, then the impl must
5896        * send its own reply.
5897        *)
5898       let no_reply =
5899         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5900       if no_reply then
5901         pr "  /* do_%s has already sent a reply */\n" name
5902       else (
5903         match fst style with
5904         | RErr -> pr "  reply (NULL, NULL);\n"
5905         | RInt n | RInt64 n | RBool n ->
5906             pr "  struct guestfs_%s_ret ret;\n" name;
5907             pr "  ret.%s = r;\n" n;
5908             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5909               name
5910         | RConstString _ | RConstOptString _ ->
5911             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5912         | RString n ->
5913             pr "  struct guestfs_%s_ret ret;\n" name;
5914             pr "  ret.%s = r;\n" n;
5915             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5916               name;
5917             pr "  free (r);\n"
5918         | RStringList n | RHashtable n ->
5919             pr "  struct guestfs_%s_ret ret;\n" name;
5920             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5921             pr "  ret.%s.%s_val = r;\n" n n;
5922             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5923               name;
5924             pr "  free_strings (r);\n"
5925         | RStruct (n, _) ->
5926             pr "  struct guestfs_%s_ret ret;\n" name;
5927             pr "  ret.%s = *r;\n" n;
5928             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5929               name;
5930             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5931               name
5932         | RStructList (n, _) ->
5933             pr "  struct guestfs_%s_ret ret;\n" name;
5934             pr "  ret.%s = *r;\n" n;
5935             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5936               name;
5937             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5938               name
5939         | RBufferOut n ->
5940             pr "  struct guestfs_%s_ret ret;\n" name;
5941             pr "  ret.%s.%s_val = r;\n" n n;
5942             pr "  ret.%s.%s_len = size;\n" n n;
5943             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5944               name;
5945             pr "  free (r);\n"
5946       );
5947
5948       (* Free the args. *)
5949       (match snd style with
5950        | [] ->
5951            pr "done: ;\n";
5952        | _ ->
5953            pr "done:\n";
5954            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5955              name
5956       );
5957
5958       pr "}\n\n";
5959   ) daemon_functions;
5960
5961   (* Dispatch function. *)
5962   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5963   pr "{\n";
5964   pr "  switch (proc_nr) {\n";
5965
5966   List.iter (
5967     fun (name, style, _, _, _, _, _) ->
5968       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5969       pr "      %s_stub (xdr_in);\n" name;
5970       pr "      break;\n"
5971   ) daemon_functions;
5972
5973   pr "    default:\n";
5974   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";
5975   pr "  }\n";
5976   pr "}\n";
5977   pr "\n";
5978
5979   (* LVM columns and tokenization functions. *)
5980   (* XXX This generates crap code.  We should rethink how we
5981    * do this parsing.
5982    *)
5983   List.iter (
5984     function
5985     | typ, cols ->
5986         pr "static const char *lvm_%s_cols = \"%s\";\n"
5987           typ (String.concat "," (List.map fst cols));
5988         pr "\n";
5989
5990         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5991         pr "{\n";
5992         pr "  char *tok, *p, *next;\n";
5993         pr "  int i, j;\n";
5994         pr "\n";
5995         (*
5996           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5997           pr "\n";
5998         *)
5999         pr "  if (!str) {\n";
6000         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6001         pr "    return -1;\n";
6002         pr "  }\n";
6003         pr "  if (!*str || c_isspace (*str)) {\n";
6004         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6005         pr "    return -1;\n";
6006         pr "  }\n";
6007         pr "  tok = str;\n";
6008         List.iter (
6009           fun (name, coltype) ->
6010             pr "  if (!tok) {\n";
6011             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6012             pr "    return -1;\n";
6013             pr "  }\n";
6014             pr "  p = strchrnul (tok, ',');\n";
6015             pr "  if (*p) next = p+1; else next = NULL;\n";
6016             pr "  *p = '\\0';\n";
6017             (match coltype with
6018              | FString ->
6019                  pr "  r->%s = strdup (tok);\n" name;
6020                  pr "  if (r->%s == NULL) {\n" name;
6021                  pr "    perror (\"strdup\");\n";
6022                  pr "    return -1;\n";
6023                  pr "  }\n"
6024              | FUUID ->
6025                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6026                  pr "    if (tok[j] == '\\0') {\n";
6027                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6028                  pr "      return -1;\n";
6029                  pr "    } else if (tok[j] != '-')\n";
6030                  pr "      r->%s[i++] = tok[j];\n" name;
6031                  pr "  }\n";
6032              | FBytes ->
6033                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6034                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6035                  pr "    return -1;\n";
6036                  pr "  }\n";
6037              | FInt64 ->
6038                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6039                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6040                  pr "    return -1;\n";
6041                  pr "  }\n";
6042              | FOptPercent ->
6043                  pr "  if (tok[0] == '\\0')\n";
6044                  pr "    r->%s = -1;\n" name;
6045                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6046                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6047                  pr "    return -1;\n";
6048                  pr "  }\n";
6049              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6050                  assert false (* can never be an LVM column *)
6051             );
6052             pr "  tok = next;\n";
6053         ) cols;
6054
6055         pr "  if (tok != NULL) {\n";
6056         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6057         pr "    return -1;\n";
6058         pr "  }\n";
6059         pr "  return 0;\n";
6060         pr "}\n";
6061         pr "\n";
6062
6063         pr "guestfs_int_lvm_%s_list *\n" typ;
6064         pr "parse_command_line_%ss (void)\n" typ;
6065         pr "{\n";
6066         pr "  char *out, *err;\n";
6067         pr "  char *p, *pend;\n";
6068         pr "  int r, i;\n";
6069         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6070         pr "  void *newp;\n";
6071         pr "\n";
6072         pr "  ret = malloc (sizeof *ret);\n";
6073         pr "  if (!ret) {\n";
6074         pr "    reply_with_perror (\"malloc\");\n";
6075         pr "    return NULL;\n";
6076         pr "  }\n";
6077         pr "\n";
6078         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6079         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6080         pr "\n";
6081         pr "  r = command (&out, &err,\n";
6082         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
6083         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6084         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6085         pr "  if (r == -1) {\n";
6086         pr "    reply_with_error (\"%%s\", err);\n";
6087         pr "    free (out);\n";
6088         pr "    free (err);\n";
6089         pr "    free (ret);\n";
6090         pr "    return NULL;\n";
6091         pr "  }\n";
6092         pr "\n";
6093         pr "  free (err);\n";
6094         pr "\n";
6095         pr "  /* Tokenize each line of the output. */\n";
6096         pr "  p = out;\n";
6097         pr "  i = 0;\n";
6098         pr "  while (p) {\n";
6099         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6100         pr "    if (pend) {\n";
6101         pr "      *pend = '\\0';\n";
6102         pr "      pend++;\n";
6103         pr "    }\n";
6104         pr "\n";
6105         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6106         pr "      p++;\n";
6107         pr "\n";
6108         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6109         pr "      p = pend;\n";
6110         pr "      continue;\n";
6111         pr "    }\n";
6112         pr "\n";
6113         pr "    /* Allocate some space to store this next entry. */\n";
6114         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6115         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6116         pr "    if (newp == NULL) {\n";
6117         pr "      reply_with_perror (\"realloc\");\n";
6118         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6119         pr "      free (ret);\n";
6120         pr "      free (out);\n";
6121         pr "      return NULL;\n";
6122         pr "    }\n";
6123         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6124         pr "\n";
6125         pr "    /* Tokenize the next entry. */\n";
6126         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6127         pr "    if (r == -1) {\n";
6128         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6129         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6130         pr "      free (ret);\n";
6131         pr "      free (out);\n";
6132         pr "      return NULL;\n";
6133         pr "    }\n";
6134         pr "\n";
6135         pr "    ++i;\n";
6136         pr "    p = pend;\n";
6137         pr "  }\n";
6138         pr "\n";
6139         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6140         pr "\n";
6141         pr "  free (out);\n";
6142         pr "  return ret;\n";
6143         pr "}\n"
6144
6145   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6146
6147 (* Generate a list of function names, for debugging in the daemon.. *)
6148 and generate_daemon_names () =
6149   generate_header CStyle GPLv2plus;
6150
6151   pr "#include <config.h>\n";
6152   pr "\n";
6153   pr "#include \"daemon.h\"\n";
6154   pr "\n";
6155
6156   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6157   pr "const char *function_names[] = {\n";
6158   List.iter (
6159     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6160   ) daemon_functions;
6161   pr "};\n";
6162
6163 (* Generate the optional groups for the daemon to implement
6164  * guestfs_available.
6165  *)
6166 and generate_daemon_optgroups_c () =
6167   generate_header CStyle GPLv2plus;
6168
6169   pr "#include <config.h>\n";
6170   pr "\n";
6171   pr "#include \"daemon.h\"\n";
6172   pr "#include \"optgroups.h\"\n";
6173   pr "\n";
6174
6175   pr "struct optgroup optgroups[] = {\n";
6176   List.iter (
6177     fun (group, _) ->
6178       pr "  { \"%s\", optgroup_%s_available },\n" group group
6179   ) optgroups;
6180   pr "  { NULL, NULL }\n";
6181   pr "};\n"
6182
6183 and generate_daemon_optgroups_h () =
6184   generate_header CStyle GPLv2plus;
6185
6186   List.iter (
6187     fun (group, _) ->
6188       pr "extern int optgroup_%s_available (void);\n" group
6189   ) optgroups
6190
6191 (* Generate the tests. *)
6192 and generate_tests () =
6193   generate_header CStyle GPLv2plus;
6194
6195   pr "\
6196 #include <stdio.h>
6197 #include <stdlib.h>
6198 #include <string.h>
6199 #include <unistd.h>
6200 #include <sys/types.h>
6201 #include <fcntl.h>
6202
6203 #include \"guestfs.h\"
6204 #include \"guestfs-internal.h\"
6205
6206 static guestfs_h *g;
6207 static int suppress_error = 0;
6208
6209 static void print_error (guestfs_h *g, void *data, const char *msg)
6210 {
6211   if (!suppress_error)
6212     fprintf (stderr, \"%%s\\n\", msg);
6213 }
6214
6215 /* FIXME: nearly identical code appears in fish.c */
6216 static void print_strings (char *const *argv)
6217 {
6218   int argc;
6219
6220   for (argc = 0; argv[argc] != NULL; ++argc)
6221     printf (\"\\t%%s\\n\", argv[argc]);
6222 }
6223
6224 /*
6225 static void print_table (char const *const *argv)
6226 {
6227   int i;
6228
6229   for (i = 0; argv[i] != NULL; i += 2)
6230     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6231 }
6232 */
6233
6234 ";
6235
6236   (* Generate a list of commands which are not tested anywhere. *)
6237   pr "static void no_test_warnings (void)\n";
6238   pr "{\n";
6239
6240   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6241   List.iter (
6242     fun (_, _, _, _, tests, _, _) ->
6243       let tests = filter_map (
6244         function
6245         | (_, (Always|If _|Unless _), test) -> Some test
6246         | (_, Disabled, _) -> None
6247       ) tests in
6248       let seq = List.concat (List.map seq_of_test tests) in
6249       let cmds_tested = List.map List.hd seq in
6250       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6251   ) all_functions;
6252
6253   List.iter (
6254     fun (name, _, _, _, _, _, _) ->
6255       if not (Hashtbl.mem hash name) then
6256         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6257   ) all_functions;
6258
6259   pr "}\n";
6260   pr "\n";
6261
6262   (* Generate the actual tests.  Note that we generate the tests
6263    * in reverse order, deliberately, so that (in general) the
6264    * newest tests run first.  This makes it quicker and easier to
6265    * debug them.
6266    *)
6267   let test_names =
6268     List.map (
6269       fun (name, _, _, flags, tests, _, _) ->
6270         mapi (generate_one_test name flags) tests
6271     ) (List.rev all_functions) in
6272   let test_names = List.concat test_names in
6273   let nr_tests = List.length test_names in
6274
6275   pr "\
6276 int main (int argc, char *argv[])
6277 {
6278   char c = 0;
6279   unsigned long int n_failed = 0;
6280   const char *filename;
6281   int fd;
6282   int nr_tests, test_num = 0;
6283
6284   setbuf (stdout, NULL);
6285
6286   no_test_warnings ();
6287
6288   g = guestfs_create ();
6289   if (g == NULL) {
6290     printf (\"guestfs_create FAILED\\n\");
6291     exit (EXIT_FAILURE);
6292   }
6293
6294   guestfs_set_error_handler (g, print_error, NULL);
6295
6296   guestfs_set_path (g, \"../appliance\");
6297
6298   filename = \"test1.img\";
6299   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6300   if (fd == -1) {
6301     perror (filename);
6302     exit (EXIT_FAILURE);
6303   }
6304   if (lseek (fd, %d, SEEK_SET) == -1) {
6305     perror (\"lseek\");
6306     close (fd);
6307     unlink (filename);
6308     exit (EXIT_FAILURE);
6309   }
6310   if (write (fd, &c, 1) == -1) {
6311     perror (\"write\");
6312     close (fd);
6313     unlink (filename);
6314     exit (EXIT_FAILURE);
6315   }
6316   if (close (fd) == -1) {
6317     perror (filename);
6318     unlink (filename);
6319     exit (EXIT_FAILURE);
6320   }
6321   if (guestfs_add_drive (g, filename) == -1) {
6322     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6323     exit (EXIT_FAILURE);
6324   }
6325
6326   filename = \"test2.img\";
6327   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6328   if (fd == -1) {
6329     perror (filename);
6330     exit (EXIT_FAILURE);
6331   }
6332   if (lseek (fd, %d, SEEK_SET) == -1) {
6333     perror (\"lseek\");
6334     close (fd);
6335     unlink (filename);
6336     exit (EXIT_FAILURE);
6337   }
6338   if (write (fd, &c, 1) == -1) {
6339     perror (\"write\");
6340     close (fd);
6341     unlink (filename);
6342     exit (EXIT_FAILURE);
6343   }
6344   if (close (fd) == -1) {
6345     perror (filename);
6346     unlink (filename);
6347     exit (EXIT_FAILURE);
6348   }
6349   if (guestfs_add_drive (g, filename) == -1) {
6350     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6351     exit (EXIT_FAILURE);
6352   }
6353
6354   filename = \"test3.img\";
6355   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6356   if (fd == -1) {
6357     perror (filename);
6358     exit (EXIT_FAILURE);
6359   }
6360   if (lseek (fd, %d, SEEK_SET) == -1) {
6361     perror (\"lseek\");
6362     close (fd);
6363     unlink (filename);
6364     exit (EXIT_FAILURE);
6365   }
6366   if (write (fd, &c, 1) == -1) {
6367     perror (\"write\");
6368     close (fd);
6369     unlink (filename);
6370     exit (EXIT_FAILURE);
6371   }
6372   if (close (fd) == -1) {
6373     perror (filename);
6374     unlink (filename);
6375     exit (EXIT_FAILURE);
6376   }
6377   if (guestfs_add_drive (g, filename) == -1) {
6378     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6379     exit (EXIT_FAILURE);
6380   }
6381
6382   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6383     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6384     exit (EXIT_FAILURE);
6385   }
6386
6387   if (guestfs_launch (g) == -1) {
6388     printf (\"guestfs_launch FAILED\\n\");
6389     exit (EXIT_FAILURE);
6390   }
6391
6392   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6393   alarm (600);
6394
6395   /* Cancel previous alarm. */
6396   alarm (0);
6397
6398   nr_tests = %d;
6399
6400 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6401
6402   iteri (
6403     fun i test_name ->
6404       pr "  test_num++;\n";
6405       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6406       pr "  if (%s () == -1) {\n" test_name;
6407       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6408       pr "    n_failed++;\n";
6409       pr "  }\n";
6410   ) test_names;
6411   pr "\n";
6412
6413   pr "  guestfs_close (g);\n";
6414   pr "  unlink (\"test1.img\");\n";
6415   pr "  unlink (\"test2.img\");\n";
6416   pr "  unlink (\"test3.img\");\n";
6417   pr "\n";
6418
6419   pr "  if (n_failed > 0) {\n";
6420   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6421   pr "    exit (EXIT_FAILURE);\n";
6422   pr "  }\n";
6423   pr "\n";
6424
6425   pr "  exit (EXIT_SUCCESS);\n";
6426   pr "}\n"
6427
6428 and generate_one_test name flags i (init, prereq, test) =
6429   let test_name = sprintf "test_%s_%d" name i in
6430
6431   pr "\
6432 static int %s_skip (void)
6433 {
6434   const char *str;
6435
6436   str = getenv (\"TEST_ONLY\");
6437   if (str)
6438     return strstr (str, \"%s\") == NULL;
6439   str = getenv (\"SKIP_%s\");
6440   if (str && STREQ (str, \"1\")) return 1;
6441   str = getenv (\"SKIP_TEST_%s\");
6442   if (str && STREQ (str, \"1\")) return 1;
6443   return 0;
6444 }
6445
6446 " test_name name (String.uppercase test_name) (String.uppercase name);
6447
6448   (match prereq with
6449    | Disabled | Always -> ()
6450    | If code | Unless code ->
6451        pr "static int %s_prereq (void)\n" test_name;
6452        pr "{\n";
6453        pr "  %s\n" code;
6454        pr "}\n";
6455        pr "\n";
6456   );
6457
6458   pr "\
6459 static int %s (void)
6460 {
6461   if (%s_skip ()) {
6462     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6463     return 0;
6464   }
6465
6466 " test_name test_name test_name;
6467
6468   (* Optional functions should only be tested if the relevant
6469    * support is available in the daemon.
6470    *)
6471   List.iter (
6472     function
6473     | Optional group ->
6474         pr "  {\n";
6475         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6476         pr "    int r;\n";
6477         pr "    suppress_error = 1;\n";
6478         pr "    r = guestfs_available (g, (char **) groups);\n";
6479         pr "    suppress_error = 0;\n";
6480         pr "    if (r == -1) {\n";
6481         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6482         pr "      return 0;\n";
6483         pr "    }\n";
6484         pr "  }\n";
6485     | _ -> ()
6486   ) flags;
6487
6488   (match prereq with
6489    | Disabled ->
6490        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6491    | If _ ->
6492        pr "  if (! %s_prereq ()) {\n" test_name;
6493        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6494        pr "    return 0;\n";
6495        pr "  }\n";
6496        pr "\n";
6497        generate_one_test_body name i test_name init test;
6498    | Unless _ ->
6499        pr "  if (%s_prereq ()) {\n" test_name;
6500        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6501        pr "    return 0;\n";
6502        pr "  }\n";
6503        pr "\n";
6504        generate_one_test_body name i test_name init test;
6505    | Always ->
6506        generate_one_test_body name i test_name init test
6507   );
6508
6509   pr "  return 0;\n";
6510   pr "}\n";
6511   pr "\n";
6512   test_name
6513
6514 and generate_one_test_body name i test_name init test =
6515   (match init with
6516    | InitNone (* XXX at some point, InitNone and InitEmpty became
6517                * folded together as the same thing.  Really we should
6518                * make InitNone do nothing at all, but the tests may
6519                * need to be checked to make sure this is OK.
6520                *)
6521    | InitEmpty ->
6522        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6523        List.iter (generate_test_command_call test_name)
6524          [["blockdev_setrw"; "/dev/sda"];
6525           ["umount_all"];
6526           ["lvm_remove_all"]]
6527    | InitPartition ->
6528        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6529        List.iter (generate_test_command_call test_name)
6530          [["blockdev_setrw"; "/dev/sda"];
6531           ["umount_all"];
6532           ["lvm_remove_all"];
6533           ["part_disk"; "/dev/sda"; "mbr"]]
6534    | InitBasicFS ->
6535        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6536        List.iter (generate_test_command_call test_name)
6537          [["blockdev_setrw"; "/dev/sda"];
6538           ["umount_all"];
6539           ["lvm_remove_all"];
6540           ["part_disk"; "/dev/sda"; "mbr"];
6541           ["mkfs"; "ext2"; "/dev/sda1"];
6542           ["mount_options"; ""; "/dev/sda1"; "/"]]
6543    | InitBasicFSonLVM ->
6544        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6545          test_name;
6546        List.iter (generate_test_command_call test_name)
6547          [["blockdev_setrw"; "/dev/sda"];
6548           ["umount_all"];
6549           ["lvm_remove_all"];
6550           ["part_disk"; "/dev/sda"; "mbr"];
6551           ["pvcreate"; "/dev/sda1"];
6552           ["vgcreate"; "VG"; "/dev/sda1"];
6553           ["lvcreate"; "LV"; "VG"; "8"];
6554           ["mkfs"; "ext2"; "/dev/VG/LV"];
6555           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6556    | InitISOFS ->
6557        pr "  /* InitISOFS for %s */\n" test_name;
6558        List.iter (generate_test_command_call test_name)
6559          [["blockdev_setrw"; "/dev/sda"];
6560           ["umount_all"];
6561           ["lvm_remove_all"];
6562           ["mount_ro"; "/dev/sdd"; "/"]]
6563   );
6564
6565   let get_seq_last = function
6566     | [] ->
6567         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6568           test_name
6569     | seq ->
6570         let seq = List.rev seq in
6571         List.rev (List.tl seq), List.hd seq
6572   in
6573
6574   match test with
6575   | TestRun seq ->
6576       pr "  /* TestRun for %s (%d) */\n" name i;
6577       List.iter (generate_test_command_call test_name) seq
6578   | TestOutput (seq, expected) ->
6579       pr "  /* TestOutput for %s (%d) */\n" name i;
6580       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6581       let seq, last = get_seq_last seq in
6582       let test () =
6583         pr "    if (STRNEQ (r, expected)) {\n";
6584         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6585         pr "      return -1;\n";
6586         pr "    }\n"
6587       in
6588       List.iter (generate_test_command_call test_name) seq;
6589       generate_test_command_call ~test test_name last
6590   | TestOutputList (seq, expected) ->
6591       pr "  /* TestOutputList for %s (%d) */\n" name i;
6592       let seq, last = get_seq_last seq in
6593       let test () =
6594         iteri (
6595           fun i str ->
6596             pr "    if (!r[%d]) {\n" i;
6597             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6598             pr "      print_strings (r);\n";
6599             pr "      return -1;\n";
6600             pr "    }\n";
6601             pr "    {\n";
6602             pr "      const char *expected = \"%s\";\n" (c_quote str);
6603             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6604             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6605             pr "        return -1;\n";
6606             pr "      }\n";
6607             pr "    }\n"
6608         ) expected;
6609         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6610         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6611           test_name;
6612         pr "      print_strings (r);\n";
6613         pr "      return -1;\n";
6614         pr "    }\n"
6615       in
6616       List.iter (generate_test_command_call test_name) seq;
6617       generate_test_command_call ~test test_name last
6618   | TestOutputListOfDevices (seq, expected) ->
6619       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6620       let seq, last = get_seq_last seq in
6621       let test () =
6622         iteri (
6623           fun i str ->
6624             pr "    if (!r[%d]) {\n" i;
6625             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6626             pr "      print_strings (r);\n";
6627             pr "      return -1;\n";
6628             pr "    }\n";
6629             pr "    {\n";
6630             pr "      const char *expected = \"%s\";\n" (c_quote str);
6631             pr "      r[%d][5] = 's';\n" i;
6632             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6633             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6634             pr "        return -1;\n";
6635             pr "      }\n";
6636             pr "    }\n"
6637         ) expected;
6638         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6639         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6640           test_name;
6641         pr "      print_strings (r);\n";
6642         pr "      return -1;\n";
6643         pr "    }\n"
6644       in
6645       List.iter (generate_test_command_call test_name) seq;
6646       generate_test_command_call ~test test_name last
6647   | TestOutputInt (seq, expected) ->
6648       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6649       let seq, last = get_seq_last seq in
6650       let test () =
6651         pr "    if (r != %d) {\n" expected;
6652         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6653           test_name expected;
6654         pr "               (int) r);\n";
6655         pr "      return -1;\n";
6656         pr "    }\n"
6657       in
6658       List.iter (generate_test_command_call test_name) seq;
6659       generate_test_command_call ~test test_name last
6660   | TestOutputIntOp (seq, op, expected) ->
6661       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6662       let seq, last = get_seq_last seq in
6663       let test () =
6664         pr "    if (! (r %s %d)) {\n" op expected;
6665         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6666           test_name op expected;
6667         pr "               (int) r);\n";
6668         pr "      return -1;\n";
6669         pr "    }\n"
6670       in
6671       List.iter (generate_test_command_call test_name) seq;
6672       generate_test_command_call ~test test_name last
6673   | TestOutputTrue seq ->
6674       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6675       let seq, last = get_seq_last seq in
6676       let test () =
6677         pr "    if (!r) {\n";
6678         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6679           test_name;
6680         pr "      return -1;\n";
6681         pr "    }\n"
6682       in
6683       List.iter (generate_test_command_call test_name) seq;
6684       generate_test_command_call ~test test_name last
6685   | TestOutputFalse seq ->
6686       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6687       let seq, last = get_seq_last seq in
6688       let test () =
6689         pr "    if (r) {\n";
6690         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6691           test_name;
6692         pr "      return -1;\n";
6693         pr "    }\n"
6694       in
6695       List.iter (generate_test_command_call test_name) seq;
6696       generate_test_command_call ~test test_name last
6697   | TestOutputLength (seq, expected) ->
6698       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6699       let seq, last = get_seq_last seq in
6700       let test () =
6701         pr "    int j;\n";
6702         pr "    for (j = 0; j < %d; ++j)\n" expected;
6703         pr "      if (r[j] == NULL) {\n";
6704         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6705           test_name;
6706         pr "        print_strings (r);\n";
6707         pr "        return -1;\n";
6708         pr "      }\n";
6709         pr "    if (r[j] != NULL) {\n";
6710         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6711           test_name;
6712         pr "      print_strings (r);\n";
6713         pr "      return -1;\n";
6714         pr "    }\n"
6715       in
6716       List.iter (generate_test_command_call test_name) seq;
6717       generate_test_command_call ~test test_name last
6718   | TestOutputBuffer (seq, expected) ->
6719       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6720       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6721       let seq, last = get_seq_last seq in
6722       let len = String.length expected in
6723       let test () =
6724         pr "    if (size != %d) {\n" len;
6725         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6726         pr "      return -1;\n";
6727         pr "    }\n";
6728         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6729         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6730         pr "      return -1;\n";
6731         pr "    }\n"
6732       in
6733       List.iter (generate_test_command_call test_name) seq;
6734       generate_test_command_call ~test test_name last
6735   | TestOutputStruct (seq, checks) ->
6736       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6737       let seq, last = get_seq_last seq in
6738       let test () =
6739         List.iter (
6740           function
6741           | CompareWithInt (field, expected) ->
6742               pr "    if (r->%s != %d) {\n" field expected;
6743               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6744                 test_name field expected;
6745               pr "               (int) r->%s);\n" field;
6746               pr "      return -1;\n";
6747               pr "    }\n"
6748           | CompareWithIntOp (field, op, expected) ->
6749               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6750               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6751                 test_name field op expected;
6752               pr "               (int) r->%s);\n" field;
6753               pr "      return -1;\n";
6754               pr "    }\n"
6755           | CompareWithString (field, expected) ->
6756               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6757               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6758                 test_name field expected;
6759               pr "               r->%s);\n" field;
6760               pr "      return -1;\n";
6761               pr "    }\n"
6762           | CompareFieldsIntEq (field1, field2) ->
6763               pr "    if (r->%s != r->%s) {\n" field1 field2;
6764               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6765                 test_name field1 field2;
6766               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6767               pr "      return -1;\n";
6768               pr "    }\n"
6769           | CompareFieldsStrEq (field1, field2) ->
6770               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6771               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6772                 test_name field1 field2;
6773               pr "               r->%s, r->%s);\n" field1 field2;
6774               pr "      return -1;\n";
6775               pr "    }\n"
6776         ) checks
6777       in
6778       List.iter (generate_test_command_call test_name) seq;
6779       generate_test_command_call ~test test_name last
6780   | TestLastFail seq ->
6781       pr "  /* TestLastFail for %s (%d) */\n" name i;
6782       let seq, last = get_seq_last seq in
6783       List.iter (generate_test_command_call test_name) seq;
6784       generate_test_command_call test_name ~expect_error:true last
6785
6786 (* Generate the code to run a command, leaving the result in 'r'.
6787  * If you expect to get an error then you should set expect_error:true.
6788  *)
6789 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6790   match cmd with
6791   | [] -> assert false
6792   | name :: args ->
6793       (* Look up the command to find out what args/ret it has. *)
6794       let style =
6795         try
6796           let _, style, _, _, _, _, _ =
6797             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6798           style
6799         with Not_found ->
6800           failwithf "%s: in test, command %s was not found" test_name name in
6801
6802       if List.length (snd style) <> List.length args then
6803         failwithf "%s: in test, wrong number of args given to %s"
6804           test_name name;
6805
6806       pr "  {\n";
6807
6808       List.iter (
6809         function
6810         | OptString n, "NULL" -> ()
6811         | Pathname n, arg
6812         | Device n, arg
6813         | Dev_or_Path n, arg
6814         | String n, arg
6815         | OptString n, arg ->
6816             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6817         | Int _, _
6818         | Int64 _, _
6819         | Bool _, _
6820         | FileIn _, _ | FileOut _, _ -> ()
6821         | StringList n, "" | DeviceList n, "" ->
6822             pr "    const char *const %s[1] = { NULL };\n" n
6823         | StringList n, arg | DeviceList n, arg ->
6824             let strs = string_split " " arg in
6825             iteri (
6826               fun i str ->
6827                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6828             ) strs;
6829             pr "    const char *const %s[] = {\n" n;
6830             iteri (
6831               fun i _ -> pr "      %s_%d,\n" n i
6832             ) strs;
6833             pr "      NULL\n";
6834             pr "    };\n";
6835       ) (List.combine (snd style) args);
6836
6837       let error_code =
6838         match fst style with
6839         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6840         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6841         | RConstString _ | RConstOptString _ ->
6842             pr "    const char *r;\n"; "NULL"
6843         | RString _ -> pr "    char *r;\n"; "NULL"
6844         | RStringList _ | RHashtable _ ->
6845             pr "    char **r;\n";
6846             pr "    int i;\n";
6847             "NULL"
6848         | RStruct (_, typ) ->
6849             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6850         | RStructList (_, typ) ->
6851             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6852         | RBufferOut _ ->
6853             pr "    char *r;\n";
6854             pr "    size_t size;\n";
6855             "NULL" in
6856
6857       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6858       pr "    r = guestfs_%s (g" name;
6859
6860       (* Generate the parameters. *)
6861       List.iter (
6862         function
6863         | OptString _, "NULL" -> pr ", NULL"
6864         | Pathname n, _
6865         | Device n, _ | Dev_or_Path n, _
6866         | String n, _
6867         | OptString n, _ ->
6868             pr ", %s" n
6869         | FileIn _, arg | FileOut _, arg ->
6870             pr ", \"%s\"" (c_quote arg)
6871         | StringList n, _ | DeviceList n, _ ->
6872             pr ", (char **) %s" n
6873         | Int _, arg ->
6874             let i =
6875               try int_of_string arg
6876               with Failure "int_of_string" ->
6877                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6878             pr ", %d" i
6879         | Int64 _, arg ->
6880             let i =
6881               try Int64.of_string arg
6882               with Failure "int_of_string" ->
6883                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6884             pr ", %Ld" i
6885         | Bool _, arg ->
6886             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6887       ) (List.combine (snd style) args);
6888
6889       (match fst style with
6890        | RBufferOut _ -> pr ", &size"
6891        | _ -> ()
6892       );
6893
6894       pr ");\n";
6895
6896       if not expect_error then
6897         pr "    if (r == %s)\n" error_code
6898       else
6899         pr "    if (r != %s)\n" error_code;
6900       pr "      return -1;\n";
6901
6902       (* Insert the test code. *)
6903       (match test with
6904        | None -> ()
6905        | Some f -> f ()
6906       );
6907
6908       (match fst style with
6909        | RErr | RInt _ | RInt64 _ | RBool _
6910        | RConstString _ | RConstOptString _ -> ()
6911        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6912        | RStringList _ | RHashtable _ ->
6913            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6914            pr "      free (r[i]);\n";
6915            pr "    free (r);\n"
6916        | RStruct (_, typ) ->
6917            pr "    guestfs_free_%s (r);\n" typ
6918        | RStructList (_, typ) ->
6919            pr "    guestfs_free_%s_list (r);\n" typ
6920       );
6921
6922       pr "  }\n"
6923
6924 and c_quote str =
6925   let str = replace_str str "\r" "\\r" in
6926   let str = replace_str str "\n" "\\n" in
6927   let str = replace_str str "\t" "\\t" in
6928   let str = replace_str str "\000" "\\0" in
6929   str
6930
6931 (* Generate a lot of different functions for guestfish. *)
6932 and generate_fish_cmds () =
6933   generate_header CStyle GPLv2plus;
6934
6935   let all_functions =
6936     List.filter (
6937       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6938     ) all_functions in
6939   let all_functions_sorted =
6940     List.filter (
6941       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6942     ) all_functions_sorted in
6943
6944   pr "#include <config.h>\n";
6945   pr "\n";
6946   pr "#include <stdio.h>\n";
6947   pr "#include <stdlib.h>\n";
6948   pr "#include <string.h>\n";
6949   pr "#include <inttypes.h>\n";
6950   pr "\n";
6951   pr "#include <guestfs.h>\n";
6952   pr "#include \"c-ctype.h\"\n";
6953   pr "#include \"full-write.h\"\n";
6954   pr "#include \"xstrtol.h\"\n";
6955   pr "#include \"fish.h\"\n";
6956   pr "\n";
6957
6958   (* list_commands function, which implements guestfish -h *)
6959   pr "void list_commands (void)\n";
6960   pr "{\n";
6961   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6962   pr "  list_builtin_commands ();\n";
6963   List.iter (
6964     fun (name, _, _, flags, _, shortdesc, _) ->
6965       let name = replace_char name '_' '-' in
6966       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6967         name shortdesc
6968   ) all_functions_sorted;
6969   pr "  printf (\"    %%s\\n\",";
6970   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6971   pr "}\n";
6972   pr "\n";
6973
6974   (* display_command function, which implements guestfish -h cmd *)
6975   pr "void display_command (const char *cmd)\n";
6976   pr "{\n";
6977   List.iter (
6978     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6979       let name2 = replace_char name '_' '-' in
6980       let alias =
6981         try find_map (function FishAlias n -> Some n | _ -> None) flags
6982         with Not_found -> name in
6983       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6984       let synopsis =
6985         match snd style with
6986         | [] -> name2
6987         | args ->
6988             sprintf "%s %s"
6989               name2 (String.concat " " (List.map name_of_argt args)) in
6990
6991       let warnings =
6992         if List.mem ProtocolLimitWarning flags then
6993           ("\n\n" ^ protocol_limit_warning)
6994         else "" in
6995
6996       (* For DangerWillRobinson commands, we should probably have
6997        * guestfish prompt before allowing you to use them (especially
6998        * in interactive mode). XXX
6999        *)
7000       let warnings =
7001         warnings ^
7002           if List.mem DangerWillRobinson flags then
7003             ("\n\n" ^ danger_will_robinson)
7004           else "" in
7005
7006       let warnings =
7007         warnings ^
7008           match deprecation_notice flags with
7009           | None -> ""
7010           | Some txt -> "\n\n" ^ txt in
7011
7012       let describe_alias =
7013         if name <> alias then
7014           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7015         else "" in
7016
7017       pr "  if (";
7018       pr "STRCASEEQ (cmd, \"%s\")" name;
7019       if name <> name2 then
7020         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7021       if name <> alias then
7022         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7023       pr ")\n";
7024       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7025         name2 shortdesc
7026         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7027          "=head1 DESCRIPTION\n\n" ^
7028          longdesc ^ warnings ^ describe_alias);
7029       pr "  else\n"
7030   ) all_functions;
7031   pr "    display_builtin_command (cmd);\n";
7032   pr "}\n";
7033   pr "\n";
7034
7035   let emit_print_list_function typ =
7036     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7037       typ typ typ;
7038     pr "{\n";
7039     pr "  unsigned int i;\n";
7040     pr "\n";
7041     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7042     pr "    printf (\"[%%d] = {\\n\", i);\n";
7043     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7044     pr "    printf (\"}\\n\");\n";
7045     pr "  }\n";
7046     pr "}\n";
7047     pr "\n";
7048   in
7049
7050   (* print_* functions *)
7051   List.iter (
7052     fun (typ, cols) ->
7053       let needs_i =
7054         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7055
7056       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7057       pr "{\n";
7058       if needs_i then (
7059         pr "  unsigned int i;\n";
7060         pr "\n"
7061       );
7062       List.iter (
7063         function
7064         | name, FString ->
7065             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7066         | name, FUUID ->
7067             pr "  printf (\"%%s%s: \", indent);\n" name;
7068             pr "  for (i = 0; i < 32; ++i)\n";
7069             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7070             pr "  printf (\"\\n\");\n"
7071         | name, FBuffer ->
7072             pr "  printf (\"%%s%s: \", indent);\n" name;
7073             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7074             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7075             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7076             pr "    else\n";
7077             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7078             pr "  printf (\"\\n\");\n"
7079         | name, (FUInt64|FBytes) ->
7080             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7081               name typ name
7082         | name, FInt64 ->
7083             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7084               name typ name
7085         | name, FUInt32 ->
7086             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7087               name typ name
7088         | name, FInt32 ->
7089             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7090               name typ name
7091         | name, FChar ->
7092             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7093               name typ name
7094         | name, FOptPercent ->
7095             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7096               typ name name typ name;
7097             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7098       ) cols;
7099       pr "}\n";
7100       pr "\n";
7101   ) structs;
7102
7103   (* Emit a print_TYPE_list function definition only if that function is used. *)
7104   List.iter (
7105     function
7106     | typ, (RStructListOnly | RStructAndList) ->
7107         (* generate the function for typ *)
7108         emit_print_list_function typ
7109     | typ, _ -> () (* empty *)
7110   ) (rstructs_used_by all_functions);
7111
7112   (* Emit a print_TYPE function definition only if that function is used. *)
7113   List.iter (
7114     function
7115     | typ, (RStructOnly | RStructAndList) ->
7116         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7117         pr "{\n";
7118         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7119         pr "}\n";
7120         pr "\n";
7121     | typ, _ -> () (* empty *)
7122   ) (rstructs_used_by all_functions);
7123
7124   (* run_<action> actions *)
7125   List.iter (
7126     fun (name, style, _, flags, _, _, _) ->
7127       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7128       pr "{\n";
7129       (match fst style with
7130        | RErr
7131        | RInt _
7132        | RBool _ -> pr "  int r;\n"
7133        | RInt64 _ -> pr "  int64_t r;\n"
7134        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7135        | RString _ -> pr "  char *r;\n"
7136        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7137        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7138        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7139        | RBufferOut _ ->
7140            pr "  char *r;\n";
7141            pr "  size_t size;\n";
7142       );
7143       List.iter (
7144         function
7145         | Device n
7146         | String n
7147         | OptString n
7148         | FileIn n
7149         | FileOut n -> pr "  const char *%s;\n" n
7150         | Pathname n
7151         | Dev_or_Path n -> pr "  char *%s;\n" n
7152         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7153         | Bool n -> pr "  int %s;\n" n
7154         | Int n -> pr "  int %s;\n" n
7155         | Int64 n -> pr "  int64_t %s;\n" n
7156       ) (snd style);
7157
7158       (* Check and convert parameters. *)
7159       let argc_expected = List.length (snd style) in
7160       pr "  if (argc != %d) {\n" argc_expected;
7161       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7162         argc_expected;
7163       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7164       pr "    return -1;\n";
7165       pr "  }\n";
7166
7167       let parse_integer fn fntyp rtyp range name i =
7168         pr "  {\n";
7169         pr "    strtol_error xerr;\n";
7170         pr "    %s r;\n" fntyp;
7171         pr "\n";
7172         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7173         pr "    if (xerr != LONGINT_OK) {\n";
7174         pr "      fprintf (stderr,\n";
7175         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7176         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7177         pr "      return -1;\n";
7178         pr "    }\n";
7179         (match range with
7180          | None -> ()
7181          | Some (min, max, comment) ->
7182              pr "    /* %s */\n" comment;
7183              pr "    if (r < %s || r > %s) {\n" min max;
7184              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7185                name;
7186              pr "      return -1;\n";
7187              pr "    }\n";
7188              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7189         );
7190         pr "    %s = r;\n" name;
7191         pr "  }\n";
7192       in
7193
7194       iteri (
7195         fun i ->
7196           function
7197           | Device name
7198           | String name ->
7199               pr "  %s = argv[%d];\n" name i
7200           | Pathname name
7201           | Dev_or_Path name ->
7202               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7203               pr "  if (%s == NULL) return -1;\n" name
7204           | OptString name ->
7205               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7206                 name i i
7207           | FileIn name ->
7208               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7209                 name i i
7210           | FileOut name ->
7211               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7212                 name i i
7213           | StringList name | DeviceList name ->
7214               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7215               pr "  if (%s == NULL) return -1;\n" name;
7216           | Bool name ->
7217               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7218           | Int name ->
7219               let range =
7220                 let min = "(-(2LL<<30))"
7221                 and max = "((2LL<<30)-1)"
7222                 and comment =
7223                   "The Int type in the generator is a signed 31 bit int." in
7224                 Some (min, max, comment) in
7225               parse_integer "xstrtol" "long" "int" range name i
7226           | Int64 name ->
7227               parse_integer "xstrtoll" "long long" "int64_t" None name i
7228       ) (snd style);
7229
7230       (* Call C API function. *)
7231       let fn =
7232         try find_map (function FishAction n -> Some n | _ -> None) flags
7233         with Not_found -> sprintf "guestfs_%s" name in
7234       pr "  r = %s " fn;
7235       generate_c_call_args ~handle:"g" style;
7236       pr ";\n";
7237
7238       List.iter (
7239         function
7240         | Device name | String name
7241         | OptString name | FileIn name | FileOut name | Bool name
7242         | Int name | Int64 name -> ()
7243         | Pathname name | Dev_or_Path name ->
7244             pr "  free (%s);\n" name
7245         | StringList name | DeviceList name ->
7246             pr "  free_strings (%s);\n" name
7247       ) (snd style);
7248
7249       (* Check return value for errors and display command results. *)
7250       (match fst style with
7251        | RErr -> pr "  return r;\n"
7252        | RInt _ ->
7253            pr "  if (r == -1) return -1;\n";
7254            pr "  printf (\"%%d\\n\", r);\n";
7255            pr "  return 0;\n"
7256        | RInt64 _ ->
7257            pr "  if (r == -1) return -1;\n";
7258            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7259            pr "  return 0;\n"
7260        | RBool _ ->
7261            pr "  if (r == -1) return -1;\n";
7262            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7263            pr "  return 0;\n"
7264        | RConstString _ ->
7265            pr "  if (r == NULL) return -1;\n";
7266            pr "  printf (\"%%s\\n\", r);\n";
7267            pr "  return 0;\n"
7268        | RConstOptString _ ->
7269            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7270            pr "  return 0;\n"
7271        | RString _ ->
7272            pr "  if (r == NULL) return -1;\n";
7273            pr "  printf (\"%%s\\n\", r);\n";
7274            pr "  free (r);\n";
7275            pr "  return 0;\n"
7276        | RStringList _ ->
7277            pr "  if (r == NULL) return -1;\n";
7278            pr "  print_strings (r);\n";
7279            pr "  free_strings (r);\n";
7280            pr "  return 0;\n"
7281        | RStruct (_, typ) ->
7282            pr "  if (r == NULL) return -1;\n";
7283            pr "  print_%s (r);\n" typ;
7284            pr "  guestfs_free_%s (r);\n" typ;
7285            pr "  return 0;\n"
7286        | RStructList (_, typ) ->
7287            pr "  if (r == NULL) return -1;\n";
7288            pr "  print_%s_list (r);\n" typ;
7289            pr "  guestfs_free_%s_list (r);\n" typ;
7290            pr "  return 0;\n"
7291        | RHashtable _ ->
7292            pr "  if (r == NULL) return -1;\n";
7293            pr "  print_table (r);\n";
7294            pr "  free_strings (r);\n";
7295            pr "  return 0;\n"
7296        | RBufferOut _ ->
7297            pr "  if (r == NULL) return -1;\n";
7298            pr "  if (full_write (1, r, size) != size) {\n";
7299            pr "    perror (\"write\");\n";
7300            pr "    free (r);\n";
7301            pr "    return -1;\n";
7302            pr "  }\n";
7303            pr "  free (r);\n";
7304            pr "  return 0;\n"
7305       );
7306       pr "}\n";
7307       pr "\n"
7308   ) all_functions;
7309
7310   (* run_action function *)
7311   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7312   pr "{\n";
7313   List.iter (
7314     fun (name, _, _, flags, _, _, _) ->
7315       let name2 = replace_char name '_' '-' in
7316       let alias =
7317         try find_map (function FishAlias n -> Some n | _ -> None) flags
7318         with Not_found -> name in
7319       pr "  if (";
7320       pr "STRCASEEQ (cmd, \"%s\")" name;
7321       if name <> name2 then
7322         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7323       if name <> alias then
7324         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7325       pr ")\n";
7326       pr "    return run_%s (cmd, argc, argv);\n" name;
7327       pr "  else\n";
7328   ) all_functions;
7329   pr "    {\n";
7330   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7331   pr "      return -1;\n";
7332   pr "    }\n";
7333   pr "  return 0;\n";
7334   pr "}\n";
7335   pr "\n"
7336
7337 (* Readline completion for guestfish. *)
7338 and generate_fish_completion () =
7339   generate_header CStyle GPLv2plus;
7340
7341   let all_functions =
7342     List.filter (
7343       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7344     ) all_functions in
7345
7346   pr "\
7347 #include <config.h>
7348
7349 #include <stdio.h>
7350 #include <stdlib.h>
7351 #include <string.h>
7352
7353 #ifdef HAVE_LIBREADLINE
7354 #include <readline/readline.h>
7355 #endif
7356
7357 #include \"fish.h\"
7358
7359 #ifdef HAVE_LIBREADLINE
7360
7361 static const char *const commands[] = {
7362   BUILTIN_COMMANDS_FOR_COMPLETION,
7363 ";
7364
7365   (* Get the commands, including the aliases.  They don't need to be
7366    * sorted - the generator() function just does a dumb linear search.
7367    *)
7368   let commands =
7369     List.map (
7370       fun (name, _, _, flags, _, _, _) ->
7371         let name2 = replace_char name '_' '-' in
7372         let alias =
7373           try find_map (function FishAlias n -> Some n | _ -> None) flags
7374           with Not_found -> name in
7375
7376         if name <> alias then [name2; alias] else [name2]
7377     ) all_functions in
7378   let commands = List.flatten commands in
7379
7380   List.iter (pr "  \"%s\",\n") commands;
7381
7382   pr "  NULL
7383 };
7384
7385 static char *
7386 generator (const char *text, int state)
7387 {
7388   static int index, len;
7389   const char *name;
7390
7391   if (!state) {
7392     index = 0;
7393     len = strlen (text);
7394   }
7395
7396   rl_attempted_completion_over = 1;
7397
7398   while ((name = commands[index]) != NULL) {
7399     index++;
7400     if (STRCASEEQLEN (name, text, len))
7401       return strdup (name);
7402   }
7403
7404   return NULL;
7405 }
7406
7407 #endif /* HAVE_LIBREADLINE */
7408
7409 char **do_completion (const char *text, int start, int end)
7410 {
7411   char **matches = NULL;
7412
7413 #ifdef HAVE_LIBREADLINE
7414   rl_completion_append_character = ' ';
7415
7416   if (start == 0)
7417     matches = rl_completion_matches (text, generator);
7418   else if (complete_dest_paths)
7419     matches = rl_completion_matches (text, complete_dest_paths_generator);
7420 #endif
7421
7422   return matches;
7423 }
7424 ";
7425
7426 (* Generate the POD documentation for guestfish. *)
7427 and generate_fish_actions_pod () =
7428   let all_functions_sorted =
7429     List.filter (
7430       fun (_, _, _, flags, _, _, _) ->
7431         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7432     ) all_functions_sorted in
7433
7434   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7435
7436   List.iter (
7437     fun (name, style, _, flags, _, _, longdesc) ->
7438       let longdesc =
7439         Str.global_substitute rex (
7440           fun s ->
7441             let sub =
7442               try Str.matched_group 1 s
7443               with Not_found ->
7444                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7445             "C<" ^ replace_char sub '_' '-' ^ ">"
7446         ) longdesc in
7447       let name = replace_char name '_' '-' in
7448       let alias =
7449         try find_map (function FishAlias n -> Some n | _ -> None) flags
7450         with Not_found -> name in
7451
7452       pr "=head2 %s" name;
7453       if name <> alias then
7454         pr " | %s" alias;
7455       pr "\n";
7456       pr "\n";
7457       pr " %s" name;
7458       List.iter (
7459         function
7460         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7461         | OptString n -> pr " %s" n
7462         | StringList n | DeviceList n -> pr " '%s ...'" n
7463         | Bool _ -> pr " true|false"
7464         | Int n -> pr " %s" n
7465         | Int64 n -> pr " %s" n
7466         | FileIn n | FileOut n -> pr " (%s|-)" n
7467       ) (snd style);
7468       pr "\n";
7469       pr "\n";
7470       pr "%s\n\n" longdesc;
7471
7472       if List.exists (function FileIn _ | FileOut _ -> true
7473                       | _ -> false) (snd style) then
7474         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7475
7476       if List.mem ProtocolLimitWarning flags then
7477         pr "%s\n\n" protocol_limit_warning;
7478
7479       if List.mem DangerWillRobinson flags then
7480         pr "%s\n\n" danger_will_robinson;
7481
7482       match deprecation_notice flags with
7483       | None -> ()
7484       | Some txt -> pr "%s\n\n" txt
7485   ) all_functions_sorted
7486
7487 (* Generate a C function prototype. *)
7488 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7489     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7490     ?(prefix = "")
7491     ?handle name style =
7492   if extern then pr "extern ";
7493   if static then pr "static ";
7494   (match fst style with
7495    | RErr -> pr "int "
7496    | RInt _ -> pr "int "
7497    | RInt64 _ -> pr "int64_t "
7498    | RBool _ -> pr "int "
7499    | RConstString _ | RConstOptString _ -> pr "const char *"
7500    | RString _ | RBufferOut _ -> pr "char *"
7501    | RStringList _ | RHashtable _ -> pr "char **"
7502    | RStruct (_, typ) ->
7503        if not in_daemon then pr "struct guestfs_%s *" typ
7504        else pr "guestfs_int_%s *" typ
7505    | RStructList (_, typ) ->
7506        if not in_daemon then pr "struct guestfs_%s_list *" typ
7507        else pr "guestfs_int_%s_list *" typ
7508   );
7509   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7510   pr "%s%s (" prefix name;
7511   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7512     pr "void"
7513   else (
7514     let comma = ref false in
7515     (match handle with
7516      | None -> ()
7517      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7518     );
7519     let next () =
7520       if !comma then (
7521         if single_line then pr ", " else pr ",\n\t\t"
7522       );
7523       comma := true
7524     in
7525     List.iter (
7526       function
7527       | Pathname n
7528       | Device n | Dev_or_Path n
7529       | String n
7530       | OptString n ->
7531           next ();
7532           pr "const char *%s" n
7533       | StringList n | DeviceList n ->
7534           next ();
7535           pr "char *const *%s" n
7536       | Bool n -> next (); pr "int %s" n
7537       | Int n -> next (); pr "int %s" n
7538       | Int64 n -> next (); pr "int64_t %s" n
7539       | FileIn n
7540       | FileOut n ->
7541           if not in_daemon then (next (); pr "const char *%s" n)
7542     ) (snd style);
7543     if is_RBufferOut then (next (); pr "size_t *size_r");
7544   );
7545   pr ")";
7546   if semicolon then pr ";";
7547   if newline then pr "\n"
7548
7549 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7550 and generate_c_call_args ?handle ?(decl = false) style =
7551   pr "(";
7552   let comma = ref false in
7553   let next () =
7554     if !comma then pr ", ";
7555     comma := true
7556   in
7557   (match handle with
7558    | None -> ()
7559    | Some handle -> pr "%s" handle; comma := true
7560   );
7561   List.iter (
7562     fun arg ->
7563       next ();
7564       pr "%s" (name_of_argt arg)
7565   ) (snd style);
7566   (* For RBufferOut calls, add implicit &size parameter. *)
7567   if not decl then (
7568     match fst style with
7569     | RBufferOut _ ->
7570         next ();
7571         pr "&size"
7572     | _ -> ()
7573   );
7574   pr ")"
7575
7576 (* Generate the OCaml bindings interface. *)
7577 and generate_ocaml_mli () =
7578   generate_header OCamlStyle LGPLv2plus;
7579
7580   pr "\
7581 (** For API documentation you should refer to the C API
7582     in the guestfs(3) manual page.  The OCaml API uses almost
7583     exactly the same calls. *)
7584
7585 type t
7586 (** A [guestfs_h] handle. *)
7587
7588 exception Error of string
7589 (** This exception is raised when there is an error. *)
7590
7591 exception Handle_closed of string
7592 (** This exception is raised if you use a {!Guestfs.t} handle
7593     after calling {!close} on it.  The string is the name of
7594     the function. *)
7595
7596 val create : unit -> t
7597 (** Create a {!Guestfs.t} handle. *)
7598
7599 val close : t -> unit
7600 (** Close the {!Guestfs.t} handle and free up all resources used
7601     by it immediately.
7602
7603     Handles are closed by the garbage collector when they become
7604     unreferenced, but callers can call this in order to provide
7605     predictable cleanup. *)
7606
7607 ";
7608   generate_ocaml_structure_decls ();
7609
7610   (* The actions. *)
7611   List.iter (
7612     fun (name, style, _, _, _, shortdesc, _) ->
7613       generate_ocaml_prototype name style;
7614       pr "(** %s *)\n" shortdesc;
7615       pr "\n"
7616   ) all_functions_sorted
7617
7618 (* Generate the OCaml bindings implementation. *)
7619 and generate_ocaml_ml () =
7620   generate_header OCamlStyle LGPLv2plus;
7621
7622   pr "\
7623 type t
7624
7625 exception Error of string
7626 exception Handle_closed of string
7627
7628 external create : unit -> t = \"ocaml_guestfs_create\"
7629 external close : t -> unit = \"ocaml_guestfs_close\"
7630
7631 (* Give the exceptions names, so they can be raised from the C code. *)
7632 let () =
7633   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7634   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7635
7636 ";
7637
7638   generate_ocaml_structure_decls ();
7639
7640   (* The actions. *)
7641   List.iter (
7642     fun (name, style, _, _, _, shortdesc, _) ->
7643       generate_ocaml_prototype ~is_external:true name style;
7644   ) all_functions_sorted
7645
7646 (* Generate the OCaml bindings C implementation. *)
7647 and generate_ocaml_c () =
7648   generate_header CStyle LGPLv2plus;
7649
7650   pr "\
7651 #include <stdio.h>
7652 #include <stdlib.h>
7653 #include <string.h>
7654
7655 #include <caml/config.h>
7656 #include <caml/alloc.h>
7657 #include <caml/callback.h>
7658 #include <caml/fail.h>
7659 #include <caml/memory.h>
7660 #include <caml/mlvalues.h>
7661 #include <caml/signals.h>
7662
7663 #include <guestfs.h>
7664
7665 #include \"guestfs_c.h\"
7666
7667 /* Copy a hashtable of string pairs into an assoc-list.  We return
7668  * the list in reverse order, but hashtables aren't supposed to be
7669  * ordered anyway.
7670  */
7671 static CAMLprim value
7672 copy_table (char * const * argv)
7673 {
7674   CAMLparam0 ();
7675   CAMLlocal5 (rv, pairv, kv, vv, cons);
7676   int i;
7677
7678   rv = Val_int (0);
7679   for (i = 0; argv[i] != NULL; i += 2) {
7680     kv = caml_copy_string (argv[i]);
7681     vv = caml_copy_string (argv[i+1]);
7682     pairv = caml_alloc (2, 0);
7683     Store_field (pairv, 0, kv);
7684     Store_field (pairv, 1, vv);
7685     cons = caml_alloc (2, 0);
7686     Store_field (cons, 1, rv);
7687     rv = cons;
7688     Store_field (cons, 0, pairv);
7689   }
7690
7691   CAMLreturn (rv);
7692 }
7693
7694 ";
7695
7696   (* Struct copy functions. *)
7697
7698   let emit_ocaml_copy_list_function typ =
7699     pr "static CAMLprim value\n";
7700     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7701     pr "{\n";
7702     pr "  CAMLparam0 ();\n";
7703     pr "  CAMLlocal2 (rv, v);\n";
7704     pr "  unsigned int i;\n";
7705     pr "\n";
7706     pr "  if (%ss->len == 0)\n" typ;
7707     pr "    CAMLreturn (Atom (0));\n";
7708     pr "  else {\n";
7709     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7710     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7711     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7712     pr "      caml_modify (&Field (rv, i), v);\n";
7713     pr "    }\n";
7714     pr "    CAMLreturn (rv);\n";
7715     pr "  }\n";
7716     pr "}\n";
7717     pr "\n";
7718   in
7719
7720   List.iter (
7721     fun (typ, cols) ->
7722       let has_optpercent_col =
7723         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7724
7725       pr "static CAMLprim value\n";
7726       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7727       pr "{\n";
7728       pr "  CAMLparam0 ();\n";
7729       if has_optpercent_col then
7730         pr "  CAMLlocal3 (rv, v, v2);\n"
7731       else
7732         pr "  CAMLlocal2 (rv, v);\n";
7733       pr "\n";
7734       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7735       iteri (
7736         fun i col ->
7737           (match col with
7738            | name, FString ->
7739                pr "  v = caml_copy_string (%s->%s);\n" typ name
7740            | name, FBuffer ->
7741                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7742                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7743                  typ name typ name
7744            | name, FUUID ->
7745                pr "  v = caml_alloc_string (32);\n";
7746                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7747            | name, (FBytes|FInt64|FUInt64) ->
7748                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7749            | name, (FInt32|FUInt32) ->
7750                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7751            | name, FOptPercent ->
7752                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7753                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7754                pr "    v = caml_alloc (1, 0);\n";
7755                pr "    Store_field (v, 0, v2);\n";
7756                pr "  } else /* None */\n";
7757                pr "    v = Val_int (0);\n";
7758            | name, FChar ->
7759                pr "  v = Val_int (%s->%s);\n" typ name
7760           );
7761           pr "  Store_field (rv, %d, v);\n" i
7762       ) cols;
7763       pr "  CAMLreturn (rv);\n";
7764       pr "}\n";
7765       pr "\n";
7766   ) structs;
7767
7768   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7769   List.iter (
7770     function
7771     | typ, (RStructListOnly | RStructAndList) ->
7772         (* generate the function for typ *)
7773         emit_ocaml_copy_list_function typ
7774     | typ, _ -> () (* empty *)
7775   ) (rstructs_used_by all_functions);
7776
7777   (* The wrappers. *)
7778   List.iter (
7779     fun (name, style, _, _, _, _, _) ->
7780       pr "/* Automatically generated wrapper for function\n";
7781       pr " * ";
7782       generate_ocaml_prototype name style;
7783       pr " */\n";
7784       pr "\n";
7785
7786       let params =
7787         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7788
7789       let needs_extra_vs =
7790         match fst style with RConstOptString _ -> true | _ -> false in
7791
7792       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7793       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7794       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7795       pr "\n";
7796
7797       pr "CAMLprim value\n";
7798       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7799       List.iter (pr ", value %s") (List.tl params);
7800       pr ")\n";
7801       pr "{\n";
7802
7803       (match params with
7804        | [p1; p2; p3; p4; p5] ->
7805            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7806        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7807            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7808            pr "  CAMLxparam%d (%s);\n"
7809              (List.length rest) (String.concat ", " rest)
7810        | ps ->
7811            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7812       );
7813       if not needs_extra_vs then
7814         pr "  CAMLlocal1 (rv);\n"
7815       else
7816         pr "  CAMLlocal3 (rv, v, v2);\n";
7817       pr "\n";
7818
7819       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7820       pr "  if (g == NULL)\n";
7821       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7822       pr "\n";
7823
7824       List.iter (
7825         function
7826         | Pathname n
7827         | Device n | Dev_or_Path n
7828         | String n
7829         | FileIn n
7830         | FileOut n ->
7831             pr "  const char *%s = String_val (%sv);\n" n n
7832         | OptString n ->
7833             pr "  const char *%s =\n" n;
7834             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7835               n n
7836         | StringList n | DeviceList n ->
7837             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7838         | Bool n ->
7839             pr "  int %s = Bool_val (%sv);\n" n n
7840         | Int n ->
7841             pr "  int %s = Int_val (%sv);\n" n n
7842         | Int64 n ->
7843             pr "  int64_t %s = Int64_val (%sv);\n" n n
7844       ) (snd style);
7845       let error_code =
7846         match fst style with
7847         | RErr -> pr "  int r;\n"; "-1"
7848         | RInt _ -> pr "  int r;\n"; "-1"
7849         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7850         | RBool _ -> pr "  int r;\n"; "-1"
7851         | RConstString _ | RConstOptString _ ->
7852             pr "  const char *r;\n"; "NULL"
7853         | RString _ -> pr "  char *r;\n"; "NULL"
7854         | RStringList _ ->
7855             pr "  int i;\n";
7856             pr "  char **r;\n";
7857             "NULL"
7858         | RStruct (_, typ) ->
7859             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7860         | RStructList (_, typ) ->
7861             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7862         | RHashtable _ ->
7863             pr "  int i;\n";
7864             pr "  char **r;\n";
7865             "NULL"
7866         | RBufferOut _ ->
7867             pr "  char *r;\n";
7868             pr "  size_t size;\n";
7869             "NULL" in
7870       pr "\n";
7871
7872       pr "  caml_enter_blocking_section ();\n";
7873       pr "  r = guestfs_%s " name;
7874       generate_c_call_args ~handle:"g" style;
7875       pr ";\n";
7876       pr "  caml_leave_blocking_section ();\n";
7877
7878       List.iter (
7879         function
7880         | StringList n | DeviceList n ->
7881             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7882         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7883         | Bool _ | Int _ | Int64 _
7884         | FileIn _ | FileOut _ -> ()
7885       ) (snd style);
7886
7887       pr "  if (r == %s)\n" error_code;
7888       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7889       pr "\n";
7890
7891       (match fst style with
7892        | RErr -> pr "  rv = Val_unit;\n"
7893        | RInt _ -> pr "  rv = Val_int (r);\n"
7894        | RInt64 _ ->
7895            pr "  rv = caml_copy_int64 (r);\n"
7896        | RBool _ -> pr "  rv = Val_bool (r);\n"
7897        | RConstString _ ->
7898            pr "  rv = caml_copy_string (r);\n"
7899        | RConstOptString _ ->
7900            pr "  if (r) { /* Some string */\n";
7901            pr "    v = caml_alloc (1, 0);\n";
7902            pr "    v2 = caml_copy_string (r);\n";
7903            pr "    Store_field (v, 0, v2);\n";
7904            pr "  } else /* None */\n";
7905            pr "    v = Val_int (0);\n";
7906        | RString _ ->
7907            pr "  rv = caml_copy_string (r);\n";
7908            pr "  free (r);\n"
7909        | RStringList _ ->
7910            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7911            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7912            pr "  free (r);\n"
7913        | RStruct (_, typ) ->
7914            pr "  rv = copy_%s (r);\n" typ;
7915            pr "  guestfs_free_%s (r);\n" typ;
7916        | RStructList (_, typ) ->
7917            pr "  rv = copy_%s_list (r);\n" typ;
7918            pr "  guestfs_free_%s_list (r);\n" typ;
7919        | RHashtable _ ->
7920            pr "  rv = copy_table (r);\n";
7921            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7922            pr "  free (r);\n";
7923        | RBufferOut _ ->
7924            pr "  rv = caml_alloc_string (size);\n";
7925            pr "  memcpy (String_val (rv), r, size);\n";
7926       );
7927
7928       pr "  CAMLreturn (rv);\n";
7929       pr "}\n";
7930       pr "\n";
7931
7932       if List.length params > 5 then (
7933         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7934         pr "CAMLprim value ";
7935         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7936         pr "CAMLprim value\n";
7937         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7938         pr "{\n";
7939         pr "  return ocaml_guestfs_%s (argv[0]" name;
7940         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7941         pr ");\n";
7942         pr "}\n";
7943         pr "\n"
7944       )
7945   ) all_functions_sorted
7946
7947 and generate_ocaml_structure_decls () =
7948   List.iter (
7949     fun (typ, cols) ->
7950       pr "type %s = {\n" typ;
7951       List.iter (
7952         function
7953         | name, FString -> pr "  %s : string;\n" name
7954         | name, FBuffer -> pr "  %s : string;\n" name
7955         | name, FUUID -> pr "  %s : string;\n" name
7956         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7957         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7958         | name, FChar -> pr "  %s : char;\n" name
7959         | name, FOptPercent -> pr "  %s : float option;\n" name
7960       ) cols;
7961       pr "}\n";
7962       pr "\n"
7963   ) structs
7964
7965 and generate_ocaml_prototype ?(is_external = false) name style =
7966   if is_external then pr "external " else pr "val ";
7967   pr "%s : t -> " name;
7968   List.iter (
7969     function
7970     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7971     | OptString _ -> pr "string option -> "
7972     | StringList _ | DeviceList _ -> pr "string array -> "
7973     | Bool _ -> pr "bool -> "
7974     | Int _ -> pr "int -> "
7975     | Int64 _ -> pr "int64 -> "
7976   ) (snd style);
7977   (match fst style with
7978    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7979    | RInt _ -> pr "int"
7980    | RInt64 _ -> pr "int64"
7981    | RBool _ -> pr "bool"
7982    | RConstString _ -> pr "string"
7983    | RConstOptString _ -> pr "string option"
7984    | RString _ | RBufferOut _ -> pr "string"
7985    | RStringList _ -> pr "string array"
7986    | RStruct (_, typ) -> pr "%s" typ
7987    | RStructList (_, typ) -> pr "%s array" typ
7988    | RHashtable _ -> pr "(string * string) list"
7989   );
7990   if is_external then (
7991     pr " = ";
7992     if List.length (snd style) + 1 > 5 then
7993       pr "\"ocaml_guestfs_%s_byte\" " name;
7994     pr "\"ocaml_guestfs_%s\"" name
7995   );
7996   pr "\n"
7997
7998 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7999 and generate_perl_xs () =
8000   generate_header CStyle LGPLv2plus;
8001
8002   pr "\
8003 #include \"EXTERN.h\"
8004 #include \"perl.h\"
8005 #include \"XSUB.h\"
8006
8007 #include <guestfs.h>
8008
8009 #ifndef PRId64
8010 #define PRId64 \"lld\"
8011 #endif
8012
8013 static SV *
8014 my_newSVll(long long val) {
8015 #ifdef USE_64_BIT_ALL
8016   return newSViv(val);
8017 #else
8018   char buf[100];
8019   int len;
8020   len = snprintf(buf, 100, \"%%\" PRId64, val);
8021   return newSVpv(buf, len);
8022 #endif
8023 }
8024
8025 #ifndef PRIu64
8026 #define PRIu64 \"llu\"
8027 #endif
8028
8029 static SV *
8030 my_newSVull(unsigned long long val) {
8031 #ifdef USE_64_BIT_ALL
8032   return newSVuv(val);
8033 #else
8034   char buf[100];
8035   int len;
8036   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8037   return newSVpv(buf, len);
8038 #endif
8039 }
8040
8041 /* http://www.perlmonks.org/?node_id=680842 */
8042 static char **
8043 XS_unpack_charPtrPtr (SV *arg) {
8044   char **ret;
8045   AV *av;
8046   I32 i;
8047
8048   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8049     croak (\"array reference expected\");
8050
8051   av = (AV *)SvRV (arg);
8052   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8053   if (!ret)
8054     croak (\"malloc failed\");
8055
8056   for (i = 0; i <= av_len (av); i++) {
8057     SV **elem = av_fetch (av, i, 0);
8058
8059     if (!elem || !*elem)
8060       croak (\"missing element in list\");
8061
8062     ret[i] = SvPV_nolen (*elem);
8063   }
8064
8065   ret[i] = NULL;
8066
8067   return ret;
8068 }
8069
8070 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8071
8072 PROTOTYPES: ENABLE
8073
8074 guestfs_h *
8075 _create ()
8076    CODE:
8077       RETVAL = guestfs_create ();
8078       if (!RETVAL)
8079         croak (\"could not create guestfs handle\");
8080       guestfs_set_error_handler (RETVAL, NULL, NULL);
8081  OUTPUT:
8082       RETVAL
8083
8084 void
8085 DESTROY (g)
8086       guestfs_h *g;
8087  PPCODE:
8088       guestfs_close (g);
8089
8090 ";
8091
8092   List.iter (
8093     fun (name, style, _, _, _, _, _) ->
8094       (match fst style with
8095        | RErr -> pr "void\n"
8096        | RInt _ -> pr "SV *\n"
8097        | RInt64 _ -> pr "SV *\n"
8098        | RBool _ -> pr "SV *\n"
8099        | RConstString _ -> pr "SV *\n"
8100        | RConstOptString _ -> pr "SV *\n"
8101        | RString _ -> pr "SV *\n"
8102        | RBufferOut _ -> pr "SV *\n"
8103        | RStringList _
8104        | RStruct _ | RStructList _
8105        | RHashtable _ ->
8106            pr "void\n" (* all lists returned implictly on the stack *)
8107       );
8108       (* Call and arguments. *)
8109       pr "%s " name;
8110       generate_c_call_args ~handle:"g" ~decl:true style;
8111       pr "\n";
8112       pr "      guestfs_h *g;\n";
8113       iteri (
8114         fun i ->
8115           function
8116           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8117               pr "      char *%s;\n" n
8118           | OptString n ->
8119               (* http://www.perlmonks.org/?node_id=554277
8120                * Note that the implicit handle argument means we have
8121                * to add 1 to the ST(x) operator.
8122                *)
8123               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8124           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8125           | Bool n -> pr "      int %s;\n" n
8126           | Int n -> pr "      int %s;\n" n
8127           | Int64 n -> pr "      int64_t %s;\n" n
8128       ) (snd style);
8129
8130       let do_cleanups () =
8131         List.iter (
8132           function
8133           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8134           | Bool _ | Int _ | Int64 _
8135           | FileIn _ | FileOut _ -> ()
8136           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8137         ) (snd style)
8138       in
8139
8140       (* Code. *)
8141       (match fst style with
8142        | RErr ->
8143            pr "PREINIT:\n";
8144            pr "      int r;\n";
8145            pr " PPCODE:\n";
8146            pr "      r = guestfs_%s " name;
8147            generate_c_call_args ~handle:"g" style;
8148            pr ";\n";
8149            do_cleanups ();
8150            pr "      if (r == -1)\n";
8151            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8152        | RInt n
8153        | RBool n ->
8154            pr "PREINIT:\n";
8155            pr "      int %s;\n" n;
8156            pr "   CODE:\n";
8157            pr "      %s = guestfs_%s " n name;
8158            generate_c_call_args ~handle:"g" style;
8159            pr ";\n";
8160            do_cleanups ();
8161            pr "      if (%s == -1)\n" n;
8162            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8163            pr "      RETVAL = newSViv (%s);\n" n;
8164            pr " OUTPUT:\n";
8165            pr "      RETVAL\n"
8166        | RInt64 n ->
8167            pr "PREINIT:\n";
8168            pr "      int64_t %s;\n" n;
8169            pr "   CODE:\n";
8170            pr "      %s = guestfs_%s " n name;
8171            generate_c_call_args ~handle:"g" style;
8172            pr ";\n";
8173            do_cleanups ();
8174            pr "      if (%s == -1)\n" n;
8175            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8176            pr "      RETVAL = my_newSVll (%s);\n" n;
8177            pr " OUTPUT:\n";
8178            pr "      RETVAL\n"
8179        | RConstString n ->
8180            pr "PREINIT:\n";
8181            pr "      const char *%s;\n" n;
8182            pr "   CODE:\n";
8183            pr "      %s = guestfs_%s " n name;
8184            generate_c_call_args ~handle:"g" style;
8185            pr ";\n";
8186            do_cleanups ();
8187            pr "      if (%s == NULL)\n" n;
8188            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8189            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8190            pr " OUTPUT:\n";
8191            pr "      RETVAL\n"
8192        | RConstOptString n ->
8193            pr "PREINIT:\n";
8194            pr "      const char *%s;\n" n;
8195            pr "   CODE:\n";
8196            pr "      %s = guestfs_%s " n name;
8197            generate_c_call_args ~handle:"g" style;
8198            pr ";\n";
8199            do_cleanups ();
8200            pr "      if (%s == NULL)\n" n;
8201            pr "        RETVAL = &PL_sv_undef;\n";
8202            pr "      else\n";
8203            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8204            pr " OUTPUT:\n";
8205            pr "      RETVAL\n"
8206        | RString n ->
8207            pr "PREINIT:\n";
8208            pr "      char *%s;\n" n;
8209            pr "   CODE:\n";
8210            pr "      %s = guestfs_%s " n name;
8211            generate_c_call_args ~handle:"g" style;
8212            pr ";\n";
8213            do_cleanups ();
8214            pr "      if (%s == NULL)\n" n;
8215            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8216            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8217            pr "      free (%s);\n" n;
8218            pr " OUTPUT:\n";
8219            pr "      RETVAL\n"
8220        | RStringList n | RHashtable n ->
8221            pr "PREINIT:\n";
8222            pr "      char **%s;\n" n;
8223            pr "      int i, n;\n";
8224            pr " PPCODE:\n";
8225            pr "      %s = guestfs_%s " n name;
8226            generate_c_call_args ~handle:"g" style;
8227            pr ";\n";
8228            do_cleanups ();
8229            pr "      if (%s == NULL)\n" n;
8230            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8231            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8232            pr "      EXTEND (SP, n);\n";
8233            pr "      for (i = 0; i < n; ++i) {\n";
8234            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8235            pr "        free (%s[i]);\n" n;
8236            pr "      }\n";
8237            pr "      free (%s);\n" n;
8238        | RStruct (n, typ) ->
8239            let cols = cols_of_struct typ in
8240            generate_perl_struct_code typ cols name style n do_cleanups
8241        | RStructList (n, typ) ->
8242            let cols = cols_of_struct typ in
8243            generate_perl_struct_list_code typ cols name style n do_cleanups
8244        | RBufferOut n ->
8245            pr "PREINIT:\n";
8246            pr "      char *%s;\n" n;
8247            pr "      size_t size;\n";
8248            pr "   CODE:\n";
8249            pr "      %s = guestfs_%s " n name;
8250            generate_c_call_args ~handle:"g" style;
8251            pr ";\n";
8252            do_cleanups ();
8253            pr "      if (%s == NULL)\n" n;
8254            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8255            pr "      RETVAL = newSVpv (%s, size);\n" n;
8256            pr "      free (%s);\n" n;
8257            pr " OUTPUT:\n";
8258            pr "      RETVAL\n"
8259       );
8260
8261       pr "\n"
8262   ) all_functions
8263
8264 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8265   pr "PREINIT:\n";
8266   pr "      struct guestfs_%s_list *%s;\n" typ n;
8267   pr "      int i;\n";
8268   pr "      HV *hv;\n";
8269   pr " PPCODE:\n";
8270   pr "      %s = guestfs_%s " n name;
8271   generate_c_call_args ~handle:"g" style;
8272   pr ";\n";
8273   do_cleanups ();
8274   pr "      if (%s == NULL)\n" n;
8275   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8276   pr "      EXTEND (SP, %s->len);\n" n;
8277   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8278   pr "        hv = newHV ();\n";
8279   List.iter (
8280     function
8281     | name, FString ->
8282         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8283           name (String.length name) n name
8284     | name, FUUID ->
8285         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8286           name (String.length name) n name
8287     | name, FBuffer ->
8288         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8289           name (String.length name) n name n name
8290     | name, (FBytes|FUInt64) ->
8291         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8292           name (String.length name) n name
8293     | name, FInt64 ->
8294         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8295           name (String.length name) n name
8296     | name, (FInt32|FUInt32) ->
8297         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8298           name (String.length name) n name
8299     | name, FChar ->
8300         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8301           name (String.length name) n name
8302     | name, FOptPercent ->
8303         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8304           name (String.length name) n name
8305   ) cols;
8306   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8307   pr "      }\n";
8308   pr "      guestfs_free_%s_list (%s);\n" typ n
8309
8310 and generate_perl_struct_code typ cols name style n do_cleanups =
8311   pr "PREINIT:\n";
8312   pr "      struct guestfs_%s *%s;\n" typ n;
8313   pr " PPCODE:\n";
8314   pr "      %s = guestfs_%s " n name;
8315   generate_c_call_args ~handle:"g" style;
8316   pr ";\n";
8317   do_cleanups ();
8318   pr "      if (%s == NULL)\n" n;
8319   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8320   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8321   List.iter (
8322     fun ((name, _) as col) ->
8323       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8324
8325       match col with
8326       | name, FString ->
8327           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8328             n name
8329       | name, FBuffer ->
8330           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8331             n name n name
8332       | name, FUUID ->
8333           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8334             n name
8335       | name, (FBytes|FUInt64) ->
8336           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8337             n name
8338       | name, FInt64 ->
8339           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8340             n name
8341       | name, (FInt32|FUInt32) ->
8342           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8343             n name
8344       | name, FChar ->
8345           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8346             n name
8347       | name, FOptPercent ->
8348           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8349             n name
8350   ) cols;
8351   pr "      free (%s);\n" n
8352
8353 (* Generate Sys/Guestfs.pm. *)
8354 and generate_perl_pm () =
8355   generate_header HashStyle LGPLv2plus;
8356
8357   pr "\
8358 =pod
8359
8360 =head1 NAME
8361
8362 Sys::Guestfs - Perl bindings for libguestfs
8363
8364 =head1 SYNOPSIS
8365
8366  use Sys::Guestfs;
8367
8368  my $h = Sys::Guestfs->new ();
8369  $h->add_drive ('guest.img');
8370  $h->launch ();
8371  $h->mount ('/dev/sda1', '/');
8372  $h->touch ('/hello');
8373  $h->sync ();
8374
8375 =head1 DESCRIPTION
8376
8377 The C<Sys::Guestfs> module provides a Perl XS binding to the
8378 libguestfs API for examining and modifying virtual machine
8379 disk images.
8380
8381 Amongst the things this is good for: making batch configuration
8382 changes to guests, getting disk used/free statistics (see also:
8383 virt-df), migrating between virtualization systems (see also:
8384 virt-p2v), performing partial backups, performing partial guest
8385 clones, cloning guests and changing registry/UUID/hostname info, and
8386 much else besides.
8387
8388 Libguestfs uses Linux kernel and qemu code, and can access any type of
8389 guest filesystem that Linux and qemu can, including but not limited
8390 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8391 schemes, qcow, qcow2, vmdk.
8392
8393 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8394 LVs, what filesystem is in each LV, etc.).  It can also run commands
8395 in the context of the guest.  Also you can access filesystems over
8396 FUSE.
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
8934 FUSE.
8935
8936 Errors which happen while using the API are turned into Python
8937 RuntimeError exceptions.
8938
8939 To create a guestfs handle you usually have to perform the following
8940 sequence of calls:
8941
8942 # Create the handle, call add_drive at least once, and possibly
8943 # several times if the guest has multiple block devices:
8944 g = guestfs.GuestFS ()
8945 g.add_drive (\"guest.img\")
8946
8947 # Launch the qemu subprocess and wait for it to become ready:
8948 g.launch ()
8949
8950 # Now you can issue commands, for example:
8951 logvols = g.lvs ()
8952
8953 \"\"\"
8954
8955 import libguestfsmod
8956
8957 class GuestFS:
8958     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8959
8960     def __init__ (self):
8961         \"\"\"Create a new libguestfs handle.\"\"\"
8962         self._o = libguestfsmod.create ()
8963
8964     def __del__ (self):
8965         libguestfsmod.close (self._o)
8966
8967 ";
8968
8969   List.iter (
8970     fun (name, style, _, flags, _, _, longdesc) ->
8971       pr "    def %s " name;
8972       generate_py_call_args ~handle:"self" (snd style);
8973       pr ":\n";
8974
8975       if not (List.mem NotInDocs flags) then (
8976         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8977         let doc =
8978           match fst style with
8979           | RErr | RInt _ | RInt64 _ | RBool _
8980           | RConstOptString _ | RConstString _
8981           | RString _ | RBufferOut _ -> doc
8982           | RStringList _ ->
8983               doc ^ "\n\nThis function returns a list of strings."
8984           | RStruct (_, typ) ->
8985               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8986           | RStructList (_, typ) ->
8987               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8988           | RHashtable _ ->
8989               doc ^ "\n\nThis function returns a dictionary." in
8990         let doc =
8991           if List.mem ProtocolLimitWarning flags then
8992             doc ^ "\n\n" ^ protocol_limit_warning
8993           else doc in
8994         let doc =
8995           if List.mem DangerWillRobinson flags then
8996             doc ^ "\n\n" ^ danger_will_robinson
8997           else doc in
8998         let doc =
8999           match deprecation_notice flags with
9000           | None -> doc
9001           | Some txt -> doc ^ "\n\n" ^ txt in
9002         let doc = pod2text ~width:60 name doc in
9003         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9004         let doc = String.concat "\n        " doc in
9005         pr "        u\"\"\"%s\"\"\"\n" doc;
9006       );
9007       pr "        return libguestfsmod.%s " name;
9008       generate_py_call_args ~handle:"self._o" (snd style);
9009       pr "\n";
9010       pr "\n";
9011   ) all_functions
9012
9013 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9014 and generate_py_call_args ~handle args =
9015   pr "(%s" handle;
9016   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9017   pr ")"
9018
9019 (* Useful if you need the longdesc POD text as plain text.  Returns a
9020  * list of lines.
9021  *
9022  * Because this is very slow (the slowest part of autogeneration),
9023  * we memoize the results.
9024  *)
9025 and pod2text ~width name longdesc =
9026   let key = width, name, longdesc in
9027   try Hashtbl.find pod2text_memo key
9028   with Not_found ->
9029     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9030     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9031     close_out chan;
9032     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9033     let chan = open_process_in cmd in
9034     let lines = ref [] in
9035     let rec loop i =
9036       let line = input_line chan in
9037       if i = 1 then             (* discard the first line of output *)
9038         loop (i+1)
9039       else (
9040         let line = triml line in
9041         lines := line :: !lines;
9042         loop (i+1)
9043       ) in
9044     let lines = try loop 1 with End_of_file -> List.rev !lines in
9045     unlink filename;
9046     (match close_process_in chan with
9047      | WEXITED 0 -> ()
9048      | WEXITED i ->
9049          failwithf "pod2text: process exited with non-zero status (%d)" i
9050      | WSIGNALED i | WSTOPPED i ->
9051          failwithf "pod2text: process signalled or stopped by signal %d" i
9052     );
9053     Hashtbl.add pod2text_memo key lines;
9054     pod2text_memo_updated ();
9055     lines
9056
9057 (* Generate ruby bindings. *)
9058 and generate_ruby_c () =
9059   generate_header CStyle LGPLv2plus;
9060
9061   pr "\
9062 #include <stdio.h>
9063 #include <stdlib.h>
9064
9065 #include <ruby.h>
9066
9067 #include \"guestfs.h\"
9068
9069 #include \"extconf.h\"
9070
9071 /* For Ruby < 1.9 */
9072 #ifndef RARRAY_LEN
9073 #define RARRAY_LEN(r) (RARRAY((r))->len)
9074 #endif
9075
9076 static VALUE m_guestfs;                 /* guestfs module */
9077 static VALUE c_guestfs;                 /* guestfs_h handle */
9078 static VALUE e_Error;                   /* used for all errors */
9079
9080 static void ruby_guestfs_free (void *p)
9081 {
9082   if (!p) return;
9083   guestfs_close ((guestfs_h *) p);
9084 }
9085
9086 static VALUE ruby_guestfs_create (VALUE m)
9087 {
9088   guestfs_h *g;
9089
9090   g = guestfs_create ();
9091   if (!g)
9092     rb_raise (e_Error, \"failed to create guestfs handle\");
9093
9094   /* Don't print error messages to stderr by default. */
9095   guestfs_set_error_handler (g, NULL, NULL);
9096
9097   /* Wrap it, and make sure the close function is called when the
9098    * handle goes away.
9099    */
9100   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9101 }
9102
9103 static VALUE ruby_guestfs_close (VALUE gv)
9104 {
9105   guestfs_h *g;
9106   Data_Get_Struct (gv, guestfs_h, g);
9107
9108   ruby_guestfs_free (g);
9109   DATA_PTR (gv) = NULL;
9110
9111   return Qnil;
9112 }
9113
9114 ";
9115
9116   List.iter (
9117     fun (name, style, _, _, _, _, _) ->
9118       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9119       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9120       pr ")\n";
9121       pr "{\n";
9122       pr "  guestfs_h *g;\n";
9123       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9124       pr "  if (!g)\n";
9125       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9126         name;
9127       pr "\n";
9128
9129       List.iter (
9130         function
9131         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9132             pr "  Check_Type (%sv, T_STRING);\n" n;
9133             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9134             pr "  if (!%s)\n" n;
9135             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9136             pr "              \"%s\", \"%s\");\n" n name
9137         | OptString n ->
9138             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9139         | StringList n | DeviceList n ->
9140             pr "  char **%s;\n" n;
9141             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9142             pr "  {\n";
9143             pr "    int i, len;\n";
9144             pr "    len = RARRAY_LEN (%sv);\n" n;
9145             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9146               n;
9147             pr "    for (i = 0; i < len; ++i) {\n";
9148             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9149             pr "      %s[i] = StringValueCStr (v);\n" n;
9150             pr "    }\n";
9151             pr "    %s[len] = NULL;\n" n;
9152             pr "  }\n";
9153         | Bool n ->
9154             pr "  int %s = RTEST (%sv);\n" n n
9155         | Int n ->
9156             pr "  int %s = NUM2INT (%sv);\n" n n
9157         | Int64 n ->
9158             pr "  long long %s = NUM2LL (%sv);\n" n n
9159       ) (snd style);
9160       pr "\n";
9161
9162       let error_code =
9163         match fst style with
9164         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9165         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9166         | RConstString _ | RConstOptString _ ->
9167             pr "  const char *r;\n"; "NULL"
9168         | RString _ -> pr "  char *r;\n"; "NULL"
9169         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9170         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9171         | RStructList (_, typ) ->
9172             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9173         | RBufferOut _ ->
9174             pr "  char *r;\n";
9175             pr "  size_t size;\n";
9176             "NULL" in
9177       pr "\n";
9178
9179       pr "  r = guestfs_%s " name;
9180       generate_c_call_args ~handle:"g" style;
9181       pr ";\n";
9182
9183       List.iter (
9184         function
9185         | Pathname _ | Device _ | Dev_or_Path _ | String _
9186         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9187         | StringList n | DeviceList n ->
9188             pr "  free (%s);\n" n
9189       ) (snd style);
9190
9191       pr "  if (r == %s)\n" error_code;
9192       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9193       pr "\n";
9194
9195       (match fst style with
9196        | RErr ->
9197            pr "  return Qnil;\n"
9198        | RInt _ | RBool _ ->
9199            pr "  return INT2NUM (r);\n"
9200        | RInt64 _ ->
9201            pr "  return ULL2NUM (r);\n"
9202        | RConstString _ ->
9203            pr "  return rb_str_new2 (r);\n";
9204        | RConstOptString _ ->
9205            pr "  if (r)\n";
9206            pr "    return rb_str_new2 (r);\n";
9207            pr "  else\n";
9208            pr "    return Qnil;\n";
9209        | RString _ ->
9210            pr "  VALUE rv = rb_str_new2 (r);\n";
9211            pr "  free (r);\n";
9212            pr "  return rv;\n";
9213        | RStringList _ ->
9214            pr "  int i, len = 0;\n";
9215            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9216            pr "  VALUE rv = rb_ary_new2 (len);\n";
9217            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9218            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9219            pr "    free (r[i]);\n";
9220            pr "  }\n";
9221            pr "  free (r);\n";
9222            pr "  return rv;\n"
9223        | RStruct (_, typ) ->
9224            let cols = cols_of_struct typ in
9225            generate_ruby_struct_code typ cols
9226        | RStructList (_, typ) ->
9227            let cols = cols_of_struct typ in
9228            generate_ruby_struct_list_code typ cols
9229        | RHashtable _ ->
9230            pr "  VALUE rv = rb_hash_new ();\n";
9231            pr "  int i;\n";
9232            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9233            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9234            pr "    free (r[i]);\n";
9235            pr "    free (r[i+1]);\n";
9236            pr "  }\n";
9237            pr "  free (r);\n";
9238            pr "  return rv;\n"
9239        | RBufferOut _ ->
9240            pr "  VALUE rv = rb_str_new (r, size);\n";
9241            pr "  free (r);\n";
9242            pr "  return rv;\n";
9243       );
9244
9245       pr "}\n";
9246       pr "\n"
9247   ) all_functions;
9248
9249   pr "\
9250 /* Initialize the module. */
9251 void Init__guestfs ()
9252 {
9253   m_guestfs = rb_define_module (\"Guestfs\");
9254   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9255   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9256
9257   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9258   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9259
9260 ";
9261   (* Define the rest of the methods. *)
9262   List.iter (
9263     fun (name, style, _, _, _, _, _) ->
9264       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9265       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9266   ) all_functions;
9267
9268   pr "}\n"
9269
9270 (* Ruby code to return a struct. *)
9271 and generate_ruby_struct_code typ cols =
9272   pr "  VALUE rv = rb_hash_new ();\n";
9273   List.iter (
9274     function
9275     | name, FString ->
9276         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9277     | name, FBuffer ->
9278         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9279     | name, FUUID ->
9280         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9281     | name, (FBytes|FUInt64) ->
9282         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9283     | name, FInt64 ->
9284         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9285     | name, FUInt32 ->
9286         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9287     | name, FInt32 ->
9288         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9289     | name, FOptPercent ->
9290         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9291     | name, FChar -> (* XXX wrong? *)
9292         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9293   ) cols;
9294   pr "  guestfs_free_%s (r);\n" typ;
9295   pr "  return rv;\n"
9296
9297 (* Ruby code to return a struct list. *)
9298 and generate_ruby_struct_list_code typ cols =
9299   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9300   pr "  int i;\n";
9301   pr "  for (i = 0; i < r->len; ++i) {\n";
9302   pr "    VALUE hv = rb_hash_new ();\n";
9303   List.iter (
9304     function
9305     | name, FString ->
9306         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9307     | name, FBuffer ->
9308         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
9309     | name, FUUID ->
9310         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9311     | name, (FBytes|FUInt64) ->
9312         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9313     | name, FInt64 ->
9314         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9315     | name, FUInt32 ->
9316         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9317     | name, FInt32 ->
9318         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9319     | name, FOptPercent ->
9320         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9321     | name, FChar -> (* XXX wrong? *)
9322         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9323   ) cols;
9324   pr "    rb_ary_push (rv, hv);\n";
9325   pr "  }\n";
9326   pr "  guestfs_free_%s_list (r);\n" typ;
9327   pr "  return rv;\n"
9328
9329 (* Generate Java bindings GuestFS.java file. *)
9330 and generate_java_java () =
9331   generate_header CStyle LGPLv2plus;
9332
9333   pr "\
9334 package com.redhat.et.libguestfs;
9335
9336 import java.util.HashMap;
9337 import com.redhat.et.libguestfs.LibGuestFSException;
9338 import com.redhat.et.libguestfs.PV;
9339 import com.redhat.et.libguestfs.VG;
9340 import com.redhat.et.libguestfs.LV;
9341 import com.redhat.et.libguestfs.Stat;
9342 import com.redhat.et.libguestfs.StatVFS;
9343 import com.redhat.et.libguestfs.IntBool;
9344 import com.redhat.et.libguestfs.Dirent;
9345
9346 /**
9347  * The GuestFS object is a libguestfs handle.
9348  *
9349  * @author rjones
9350  */
9351 public class GuestFS {
9352   // Load the native code.
9353   static {
9354     System.loadLibrary (\"guestfs_jni\");
9355   }
9356
9357   /**
9358    * The native guestfs_h pointer.
9359    */
9360   long g;
9361
9362   /**
9363    * Create a libguestfs handle.
9364    *
9365    * @throws LibGuestFSException
9366    */
9367   public GuestFS () throws LibGuestFSException
9368   {
9369     g = _create ();
9370   }
9371   private native long _create () throws LibGuestFSException;
9372
9373   /**
9374    * Close a libguestfs handle.
9375    *
9376    * You can also leave handles to be collected by the garbage
9377    * collector, but this method ensures that the resources used
9378    * by the handle are freed up immediately.  If you call any
9379    * other methods after closing the handle, you will get an
9380    * exception.
9381    *
9382    * @throws LibGuestFSException
9383    */
9384   public void close () throws LibGuestFSException
9385   {
9386     if (g != 0)
9387       _close (g);
9388     g = 0;
9389   }
9390   private native void _close (long g) throws LibGuestFSException;
9391
9392   public void finalize () throws LibGuestFSException
9393   {
9394     close ();
9395   }
9396
9397 ";
9398
9399   List.iter (
9400     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9401       if not (List.mem NotInDocs flags); then (
9402         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9403         let doc =
9404           if List.mem ProtocolLimitWarning flags then
9405             doc ^ "\n\n" ^ protocol_limit_warning
9406           else doc in
9407         let doc =
9408           if List.mem DangerWillRobinson flags then
9409             doc ^ "\n\n" ^ danger_will_robinson
9410           else doc in
9411         let doc =
9412           match deprecation_notice flags with
9413           | None -> doc
9414           | Some txt -> doc ^ "\n\n" ^ txt in
9415         let doc = pod2text ~width:60 name doc in
9416         let doc = List.map (            (* RHBZ#501883 *)
9417           function
9418           | "" -> "<p>"
9419           | nonempty -> nonempty
9420         ) doc in
9421         let doc = String.concat "\n   * " doc in
9422
9423         pr "  /**\n";
9424         pr "   * %s\n" shortdesc;
9425         pr "   * <p>\n";
9426         pr "   * %s\n" doc;
9427         pr "   * @throws LibGuestFSException\n";
9428         pr "   */\n";
9429         pr "  ";
9430       );
9431       generate_java_prototype ~public:true ~semicolon:false name style;
9432       pr "\n";
9433       pr "  {\n";
9434       pr "    if (g == 0)\n";
9435       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9436         name;
9437       pr "    ";
9438       if fst style <> RErr then pr "return ";
9439       pr "_%s " name;
9440       generate_java_call_args ~handle:"g" (snd style);
9441       pr ";\n";
9442       pr "  }\n";
9443       pr "  ";
9444       generate_java_prototype ~privat:true ~native:true name style;
9445       pr "\n";
9446       pr "\n";
9447   ) all_functions;
9448
9449   pr "}\n"
9450
9451 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9452 and generate_java_call_args ~handle args =
9453   pr "(%s" handle;
9454   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9455   pr ")"
9456
9457 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9458     ?(semicolon=true) name style =
9459   if privat then pr "private ";
9460   if public then pr "public ";
9461   if native then pr "native ";
9462
9463   (* return type *)
9464   (match fst style with
9465    | RErr -> pr "void ";
9466    | RInt _ -> pr "int ";
9467    | RInt64 _ -> pr "long ";
9468    | RBool _ -> pr "boolean ";
9469    | RConstString _ | RConstOptString _ | RString _
9470    | RBufferOut _ -> pr "String ";
9471    | RStringList _ -> pr "String[] ";
9472    | RStruct (_, typ) ->
9473        let name = java_name_of_struct typ in
9474        pr "%s " name;
9475    | RStructList (_, typ) ->
9476        let name = java_name_of_struct typ in
9477        pr "%s[] " name;
9478    | RHashtable _ -> pr "HashMap<String,String> ";
9479   );
9480
9481   if native then pr "_%s " name else pr "%s " name;
9482   pr "(";
9483   let needs_comma = ref false in
9484   if native then (
9485     pr "long g";
9486     needs_comma := true
9487   );
9488
9489   (* args *)
9490   List.iter (
9491     fun arg ->
9492       if !needs_comma then pr ", ";
9493       needs_comma := true;
9494
9495       match arg with
9496       | Pathname n
9497       | Device n | Dev_or_Path n
9498       | String n
9499       | OptString n
9500       | FileIn n
9501       | FileOut n ->
9502           pr "String %s" n
9503       | StringList n | DeviceList n ->
9504           pr "String[] %s" n
9505       | Bool n ->
9506           pr "boolean %s" n
9507       | Int n ->
9508           pr "int %s" n
9509       | Int64 n ->
9510           pr "long %s" n
9511   ) (snd style);
9512
9513   pr ")\n";
9514   pr "    throws LibGuestFSException";
9515   if semicolon then pr ";"
9516
9517 and generate_java_struct jtyp cols () =
9518   generate_header CStyle LGPLv2plus;
9519
9520   pr "\
9521 package com.redhat.et.libguestfs;
9522
9523 /**
9524  * Libguestfs %s structure.
9525  *
9526  * @author rjones
9527  * @see GuestFS
9528  */
9529 public class %s {
9530 " jtyp jtyp;
9531
9532   List.iter (
9533     function
9534     | name, FString
9535     | name, FUUID
9536     | name, FBuffer -> pr "  public String %s;\n" name
9537     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9538     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9539     | name, FChar -> pr "  public char %s;\n" name
9540     | name, FOptPercent ->
9541         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9542         pr "  public float %s;\n" name
9543   ) cols;
9544
9545   pr "}\n"
9546
9547 and generate_java_c () =
9548   generate_header CStyle LGPLv2plus;
9549
9550   pr "\
9551 #include <stdio.h>
9552 #include <stdlib.h>
9553 #include <string.h>
9554
9555 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9556 #include \"guestfs.h\"
9557
9558 /* Note that this function returns.  The exception is not thrown
9559  * until after the wrapper function returns.
9560  */
9561 static void
9562 throw_exception (JNIEnv *env, const char *msg)
9563 {
9564   jclass cl;
9565   cl = (*env)->FindClass (env,
9566                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9567   (*env)->ThrowNew (env, cl, msg);
9568 }
9569
9570 JNIEXPORT jlong JNICALL
9571 Java_com_redhat_et_libguestfs_GuestFS__1create
9572   (JNIEnv *env, jobject obj)
9573 {
9574   guestfs_h *g;
9575
9576   g = guestfs_create ();
9577   if (g == NULL) {
9578     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9579     return 0;
9580   }
9581   guestfs_set_error_handler (g, NULL, NULL);
9582   return (jlong) (long) g;
9583 }
9584
9585 JNIEXPORT void JNICALL
9586 Java_com_redhat_et_libguestfs_GuestFS__1close
9587   (JNIEnv *env, jobject obj, jlong jg)
9588 {
9589   guestfs_h *g = (guestfs_h *) (long) jg;
9590   guestfs_close (g);
9591 }
9592
9593 ";
9594
9595   List.iter (
9596     fun (name, style, _, _, _, _, _) ->
9597       pr "JNIEXPORT ";
9598       (match fst style with
9599        | RErr -> pr "void ";
9600        | RInt _ -> pr "jint ";
9601        | RInt64 _ -> pr "jlong ";
9602        | RBool _ -> pr "jboolean ";
9603        | RConstString _ | RConstOptString _ | RString _
9604        | RBufferOut _ -> pr "jstring ";
9605        | RStruct _ | RHashtable _ ->
9606            pr "jobject ";
9607        | RStringList _ | RStructList _ ->
9608            pr "jobjectArray ";
9609       );
9610       pr "JNICALL\n";
9611       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9612       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9613       pr "\n";
9614       pr "  (JNIEnv *env, jobject obj, jlong jg";
9615       List.iter (
9616         function
9617         | Pathname n
9618         | Device n | Dev_or_Path n
9619         | String n
9620         | OptString n
9621         | FileIn n
9622         | FileOut n ->
9623             pr ", jstring j%s" n
9624         | StringList n | DeviceList n ->
9625             pr ", jobjectArray j%s" n
9626         | Bool n ->
9627             pr ", jboolean j%s" n
9628         | Int n ->
9629             pr ", jint j%s" n
9630         | Int64 n ->
9631             pr ", jlong j%s" n
9632       ) (snd style);
9633       pr ")\n";
9634       pr "{\n";
9635       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9636       let error_code, no_ret =
9637         match fst style with
9638         | RErr -> pr "  int r;\n"; "-1", ""
9639         | RBool _
9640         | RInt _ -> pr "  int r;\n"; "-1", "0"
9641         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9642         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9643         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9644         | RString _ ->
9645             pr "  jstring jr;\n";
9646             pr "  char *r;\n"; "NULL", "NULL"
9647         | RStringList _ ->
9648             pr "  jobjectArray jr;\n";
9649             pr "  int r_len;\n";
9650             pr "  jclass cl;\n";
9651             pr "  jstring jstr;\n";
9652             pr "  char **r;\n"; "NULL", "NULL"
9653         | RStruct (_, typ) ->
9654             pr "  jobject jr;\n";
9655             pr "  jclass cl;\n";
9656             pr "  jfieldID fl;\n";
9657             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9658         | RStructList (_, typ) ->
9659             pr "  jobjectArray jr;\n";
9660             pr "  jclass cl;\n";
9661             pr "  jfieldID fl;\n";
9662             pr "  jobject jfl;\n";
9663             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9664         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9665         | RBufferOut _ ->
9666             pr "  jstring jr;\n";
9667             pr "  char *r;\n";
9668             pr "  size_t size;\n";
9669             "NULL", "NULL" in
9670       List.iter (
9671         function
9672         | Pathname n
9673         | Device n | Dev_or_Path n
9674         | String n
9675         | OptString n
9676         | FileIn n
9677         | FileOut n ->
9678             pr "  const char *%s;\n" n
9679         | StringList n | DeviceList n ->
9680             pr "  int %s_len;\n" n;
9681             pr "  const char **%s;\n" n
9682         | Bool n
9683         | Int n ->
9684             pr "  int %s;\n" n
9685         | Int64 n ->
9686             pr "  int64_t %s;\n" n
9687       ) (snd style);
9688
9689       let needs_i =
9690         (match fst style with
9691          | RStringList _ | RStructList _ -> true
9692          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9693          | RConstOptString _
9694          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9695           List.exists (function
9696                        | StringList _ -> true
9697                        | DeviceList _ -> true
9698                        | _ -> false) (snd style) in
9699       if needs_i then
9700         pr "  int i;\n";
9701
9702       pr "\n";
9703
9704       (* Get the parameters. *)
9705       List.iter (
9706         function
9707         | Pathname n
9708         | Device n | Dev_or_Path n
9709         | String n
9710         | FileIn n
9711         | FileOut n ->
9712             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9713         | OptString n ->
9714             (* This is completely undocumented, but Java null becomes
9715              * a NULL parameter.
9716              *)
9717             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9718         | StringList n | DeviceList n ->
9719             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9720             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9721             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9722             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9723               n;
9724             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9725             pr "  }\n";
9726             pr "  %s[%s_len] = NULL;\n" n n;
9727         | Bool n
9728         | Int n
9729         | Int64 n ->
9730             pr "  %s = j%s;\n" n n
9731       ) (snd style);
9732
9733       (* Make the call. *)
9734       pr "  r = guestfs_%s " name;
9735       generate_c_call_args ~handle:"g" style;
9736       pr ";\n";
9737
9738       (* Release the parameters. *)
9739       List.iter (
9740         function
9741         | Pathname n
9742         | Device n | Dev_or_Path n
9743         | String n
9744         | FileIn n
9745         | FileOut n ->
9746             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9747         | OptString n ->
9748             pr "  if (j%s)\n" n;
9749             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9750         | StringList n | DeviceList n ->
9751             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9752             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9753               n;
9754             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9755             pr "  }\n";
9756             pr "  free (%s);\n" n
9757         | Bool n
9758         | Int n
9759         | Int64 n -> ()
9760       ) (snd style);
9761
9762       (* Check for errors. *)
9763       pr "  if (r == %s) {\n" error_code;
9764       pr "    throw_exception (env, guestfs_last_error (g));\n";
9765       pr "    return %s;\n" no_ret;
9766       pr "  }\n";
9767
9768       (* Return value. *)
9769       (match fst style with
9770        | RErr -> ()
9771        | RInt _ -> pr "  return (jint) r;\n"
9772        | RBool _ -> pr "  return (jboolean) r;\n"
9773        | RInt64 _ -> pr "  return (jlong) r;\n"
9774        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9775        | RConstOptString _ ->
9776            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9777        | RString _ ->
9778            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9779            pr "  free (r);\n";
9780            pr "  return jr;\n"
9781        | RStringList _ ->
9782            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9783            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9784            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9785            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9786            pr "  for (i = 0; i < r_len; ++i) {\n";
9787            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9788            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9789            pr "    free (r[i]);\n";
9790            pr "  }\n";
9791            pr "  free (r);\n";
9792            pr "  return jr;\n"
9793        | RStruct (_, typ) ->
9794            let jtyp = java_name_of_struct typ in
9795            let cols = cols_of_struct typ in
9796            generate_java_struct_return typ jtyp cols
9797        | RStructList (_, typ) ->
9798            let jtyp = java_name_of_struct typ in
9799            let cols = cols_of_struct typ in
9800            generate_java_struct_list_return typ jtyp cols
9801        | RHashtable _ ->
9802            (* XXX *)
9803            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9804            pr "  return NULL;\n"
9805        | RBufferOut _ ->
9806            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9807            pr "  free (r);\n";
9808            pr "  return jr;\n"
9809       );
9810
9811       pr "}\n";
9812       pr "\n"
9813   ) all_functions
9814
9815 and generate_java_struct_return typ jtyp cols =
9816   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9817   pr "  jr = (*env)->AllocObject (env, cl);\n";
9818   List.iter (
9819     function
9820     | name, FString ->
9821         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9822         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9823     | name, FUUID ->
9824         pr "  {\n";
9825         pr "    char s[33];\n";
9826         pr "    memcpy (s, r->%s, 32);\n" name;
9827         pr "    s[32] = 0;\n";
9828         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9829         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9830         pr "  }\n";
9831     | name, FBuffer ->
9832         pr "  {\n";
9833         pr "    int len = r->%s_len;\n" name;
9834         pr "    char s[len+1];\n";
9835         pr "    memcpy (s, r->%s, len);\n" name;
9836         pr "    s[len] = 0;\n";
9837         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9838         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9839         pr "  }\n";
9840     | name, (FBytes|FUInt64|FInt64) ->
9841         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9842         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9843     | name, (FUInt32|FInt32) ->
9844         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9845         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9846     | name, FOptPercent ->
9847         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9848         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9849     | name, FChar ->
9850         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9851         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9852   ) cols;
9853   pr "  free (r);\n";
9854   pr "  return jr;\n"
9855
9856 and generate_java_struct_list_return typ jtyp cols =
9857   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9858   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9859   pr "  for (i = 0; i < r->len; ++i) {\n";
9860   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9861   List.iter (
9862     function
9863     | name, FString ->
9864         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9865         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9866     | name, FUUID ->
9867         pr "    {\n";
9868         pr "      char s[33];\n";
9869         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9870         pr "      s[32] = 0;\n";
9871         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9872         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9873         pr "    }\n";
9874     | name, FBuffer ->
9875         pr "    {\n";
9876         pr "      int len = r->val[i].%s_len;\n" name;
9877         pr "      char s[len+1];\n";
9878         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9879         pr "      s[len] = 0;\n";
9880         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9881         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9882         pr "    }\n";
9883     | name, (FBytes|FUInt64|FInt64) ->
9884         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9885         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9886     | name, (FUInt32|FInt32) ->
9887         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9888         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9889     | name, FOptPercent ->
9890         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9891         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9892     | name, FChar ->
9893         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9894         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9895   ) cols;
9896   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9897   pr "  }\n";
9898   pr "  guestfs_free_%s_list (r);\n" typ;
9899   pr "  return jr;\n"
9900
9901 and generate_java_makefile_inc () =
9902   generate_header HashStyle GPLv2plus;
9903
9904   pr "java_built_sources = \\\n";
9905   List.iter (
9906     fun (typ, jtyp) ->
9907         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9908   ) java_structs;
9909   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9910
9911 and generate_haskell_hs () =
9912   generate_header HaskellStyle LGPLv2plus;
9913
9914   (* XXX We only know how to generate partial FFI for Haskell
9915    * at the moment.  Please help out!
9916    *)
9917   let can_generate style =
9918     match style with
9919     | RErr, _
9920     | RInt _, _
9921     | RInt64 _, _ -> true
9922     | RBool _, _
9923     | RConstString _, _
9924     | RConstOptString _, _
9925     | RString _, _
9926     | RStringList _, _
9927     | RStruct _, _
9928     | RStructList _, _
9929     | RHashtable _, _
9930     | RBufferOut _, _ -> false in
9931
9932   pr "\
9933 {-# INCLUDE <guestfs.h> #-}
9934 {-# LANGUAGE ForeignFunctionInterface #-}
9935
9936 module Guestfs (
9937   create";
9938
9939   (* List out the names of the actions we want to export. *)
9940   List.iter (
9941     fun (name, style, _, _, _, _, _) ->
9942       if can_generate style then pr ",\n  %s" name
9943   ) all_functions;
9944
9945   pr "
9946   ) where
9947
9948 -- Unfortunately some symbols duplicate ones already present
9949 -- in Prelude.  We don't know which, so we hard-code a list
9950 -- here.
9951 import Prelude hiding (truncate)
9952
9953 import Foreign
9954 import Foreign.C
9955 import Foreign.C.Types
9956 import IO
9957 import Control.Exception
9958 import Data.Typeable
9959
9960 data GuestfsS = GuestfsS            -- represents the opaque C struct
9961 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9962 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9963
9964 -- XXX define properly later XXX
9965 data PV = PV
9966 data VG = VG
9967 data LV = LV
9968 data IntBool = IntBool
9969 data Stat = Stat
9970 data StatVFS = StatVFS
9971 data Hashtable = Hashtable
9972
9973 foreign import ccall unsafe \"guestfs_create\" c_create
9974   :: IO GuestfsP
9975 foreign import ccall unsafe \"&guestfs_close\" c_close
9976   :: FunPtr (GuestfsP -> IO ())
9977 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9978   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9979
9980 create :: IO GuestfsH
9981 create = do
9982   p <- c_create
9983   c_set_error_handler p nullPtr nullPtr
9984   h <- newForeignPtr c_close p
9985   return h
9986
9987 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9988   :: GuestfsP -> IO CString
9989
9990 -- last_error :: GuestfsH -> IO (Maybe String)
9991 -- last_error h = do
9992 --   str <- withForeignPtr h (\\p -> c_last_error p)
9993 --   maybePeek peekCString str
9994
9995 last_error :: GuestfsH -> IO (String)
9996 last_error h = do
9997   str <- withForeignPtr h (\\p -> c_last_error p)
9998   if (str == nullPtr)
9999     then return \"no error\"
10000     else peekCString str
10001
10002 ";
10003
10004   (* Generate wrappers for each foreign function. *)
10005   List.iter (
10006     fun (name, style, _, _, _, _, _) ->
10007       if can_generate style then (
10008         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10009         pr "  :: ";
10010         generate_haskell_prototype ~handle:"GuestfsP" style;
10011         pr "\n";
10012         pr "\n";
10013         pr "%s :: " name;
10014         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10015         pr "\n";
10016         pr "%s %s = do\n" name
10017           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10018         pr "  r <- ";
10019         (* Convert pointer arguments using with* functions. *)
10020         List.iter (
10021           function
10022           | FileIn n
10023           | FileOut n
10024           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10025           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10026           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10027           | Bool _ | Int _ | Int64 _ -> ()
10028         ) (snd style);
10029         (* Convert integer arguments. *)
10030         let args =
10031           List.map (
10032             function
10033             | Bool n -> sprintf "(fromBool %s)" n
10034             | Int n -> sprintf "(fromIntegral %s)" n
10035             | Int64 n -> sprintf "(fromIntegral %s)" n
10036             | FileIn n | FileOut n
10037             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10038           ) (snd style) in
10039         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10040           (String.concat " " ("p" :: args));
10041         (match fst style with
10042          | RErr | RInt _ | RInt64 _ | RBool _ ->
10043              pr "  if (r == -1)\n";
10044              pr "    then do\n";
10045              pr "      err <- last_error h\n";
10046              pr "      fail err\n";
10047          | RConstString _ | RConstOptString _ | RString _
10048          | RStringList _ | RStruct _
10049          | RStructList _ | RHashtable _ | RBufferOut _ ->
10050              pr "  if (r == nullPtr)\n";
10051              pr "    then do\n";
10052              pr "      err <- last_error h\n";
10053              pr "      fail err\n";
10054         );
10055         (match fst style with
10056          | RErr ->
10057              pr "    else return ()\n"
10058          | RInt _ ->
10059              pr "    else return (fromIntegral r)\n"
10060          | RInt64 _ ->
10061              pr "    else return (fromIntegral r)\n"
10062          | RBool _ ->
10063              pr "    else return (toBool r)\n"
10064          | RConstString _
10065          | RConstOptString _
10066          | RString _
10067          | RStringList _
10068          | RStruct _
10069          | RStructList _
10070          | RHashtable _
10071          | RBufferOut _ ->
10072              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10073         );
10074         pr "\n";
10075       )
10076   ) all_functions
10077
10078 and generate_haskell_prototype ~handle ?(hs = false) style =
10079   pr "%s -> " handle;
10080   let string = if hs then "String" else "CString" in
10081   let int = if hs then "Int" else "CInt" in
10082   let bool = if hs then "Bool" else "CInt" in
10083   let int64 = if hs then "Integer" else "Int64" in
10084   List.iter (
10085     fun arg ->
10086       (match arg with
10087        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10088        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10089        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10090        | Bool _ -> pr "%s" bool
10091        | Int _ -> pr "%s" int
10092        | Int64 _ -> pr "%s" int
10093        | FileIn _ -> pr "%s" string
10094        | FileOut _ -> pr "%s" string
10095       );
10096       pr " -> ";
10097   ) (snd style);
10098   pr "IO (";
10099   (match fst style with
10100    | RErr -> if not hs then pr "CInt"
10101    | RInt _ -> pr "%s" int
10102    | RInt64 _ -> pr "%s" int64
10103    | RBool _ -> pr "%s" bool
10104    | RConstString _ -> pr "%s" string
10105    | RConstOptString _ -> pr "Maybe %s" string
10106    | RString _ -> pr "%s" string
10107    | RStringList _ -> pr "[%s]" string
10108    | RStruct (_, typ) ->
10109        let name = java_name_of_struct typ in
10110        pr "%s" name
10111    | RStructList (_, typ) ->
10112        let name = java_name_of_struct typ in
10113        pr "[%s]" name
10114    | RHashtable _ -> pr "Hashtable"
10115    | RBufferOut _ -> pr "%s" string
10116   );
10117   pr ")"
10118
10119 and generate_csharp () =
10120   generate_header CPlusPlusStyle LGPLv2plus;
10121
10122   (* XXX Make this configurable by the C# assembly users. *)
10123   let library = "libguestfs.so.0" in
10124
10125   pr "\
10126 // These C# bindings are highly experimental at present.
10127 //
10128 // Firstly they only work on Linux (ie. Mono).  In order to get them
10129 // to work on Windows (ie. .Net) you would need to port the library
10130 // itself to Windows first.
10131 //
10132 // The second issue is that some calls are known to be incorrect and
10133 // can cause Mono to segfault.  Particularly: calls which pass or
10134 // return string[], or return any structure value.  This is because
10135 // we haven't worked out the correct way to do this from C#.
10136 //
10137 // The third issue is that when compiling you get a lot of warnings.
10138 // We are not sure whether the warnings are important or not.
10139 //
10140 // Fourthly we do not routinely build or test these bindings as part
10141 // of the make && make check cycle, which means that regressions might
10142 // go unnoticed.
10143 //
10144 // Suggestions and patches are welcome.
10145
10146 // To compile:
10147 //
10148 // gmcs Libguestfs.cs
10149 // mono Libguestfs.exe
10150 //
10151 // (You'll probably want to add a Test class / static main function
10152 // otherwise this won't do anything useful).
10153
10154 using System;
10155 using System.IO;
10156 using System.Runtime.InteropServices;
10157 using System.Runtime.Serialization;
10158 using System.Collections;
10159
10160 namespace Guestfs
10161 {
10162   class Error : System.ApplicationException
10163   {
10164     public Error (string message) : base (message) {}
10165     protected Error (SerializationInfo info, StreamingContext context) {}
10166   }
10167
10168   class Guestfs
10169   {
10170     IntPtr _handle;
10171
10172     [DllImport (\"%s\")]
10173     static extern IntPtr guestfs_create ();
10174
10175     public Guestfs ()
10176     {
10177       _handle = guestfs_create ();
10178       if (_handle == IntPtr.Zero)
10179         throw new Error (\"could not create guestfs handle\");
10180     }
10181
10182     [DllImport (\"%s\")]
10183     static extern void guestfs_close (IntPtr h);
10184
10185     ~Guestfs ()
10186     {
10187       guestfs_close (_handle);
10188     }
10189
10190     [DllImport (\"%s\")]
10191     static extern string guestfs_last_error (IntPtr h);
10192
10193 " library library library;
10194
10195   (* Generate C# structure bindings.  We prefix struct names with
10196    * underscore because C# cannot have conflicting struct names and
10197    * method names (eg. "class stat" and "stat").
10198    *)
10199   List.iter (
10200     fun (typ, cols) ->
10201       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10202       pr "    public class _%s {\n" typ;
10203       List.iter (
10204         function
10205         | name, FChar -> pr "      char %s;\n" name
10206         | name, FString -> pr "      string %s;\n" name
10207         | name, FBuffer ->
10208             pr "      uint %s_len;\n" name;
10209             pr "      string %s;\n" name
10210         | name, FUUID ->
10211             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10212             pr "      string %s;\n" name
10213         | name, FUInt32 -> pr "      uint %s;\n" name
10214         | name, FInt32 -> pr "      int %s;\n" name
10215         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10216         | name, FInt64 -> pr "      long %s;\n" name
10217         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10218       ) cols;
10219       pr "    }\n";
10220       pr "\n"
10221   ) structs;
10222
10223   (* Generate C# function bindings. *)
10224   List.iter (
10225     fun (name, style, _, _, _, shortdesc, _) ->
10226       let rec csharp_return_type () =
10227         match fst style with
10228         | RErr -> "void"
10229         | RBool n -> "bool"
10230         | RInt n -> "int"
10231         | RInt64 n -> "long"
10232         | RConstString n
10233         | RConstOptString n
10234         | RString n
10235         | RBufferOut n -> "string"
10236         | RStruct (_,n) -> "_" ^ n
10237         | RHashtable n -> "Hashtable"
10238         | RStringList n -> "string[]"
10239         | RStructList (_,n) -> sprintf "_%s[]" n
10240
10241       and c_return_type () =
10242         match fst style with
10243         | RErr
10244         | RBool _
10245         | RInt _ -> "int"
10246         | RInt64 _ -> "long"
10247         | RConstString _
10248         | RConstOptString _
10249         | RString _
10250         | RBufferOut _ -> "string"
10251         | RStruct (_,n) -> "_" ^ n
10252         | RHashtable _
10253         | RStringList _ -> "string[]"
10254         | RStructList (_,n) -> sprintf "_%s[]" n
10255     
10256       and c_error_comparison () =
10257         match fst style with
10258         | RErr
10259         | RBool _
10260         | RInt _
10261         | RInt64 _ -> "== -1"
10262         | RConstString _
10263         | RConstOptString _
10264         | RString _
10265         | RBufferOut _
10266         | RStruct (_,_)
10267         | RHashtable _
10268         | RStringList _
10269         | RStructList (_,_) -> "== null"
10270     
10271       and generate_extern_prototype () =
10272         pr "    static extern %s guestfs_%s (IntPtr h"
10273           (c_return_type ()) name;
10274         List.iter (
10275           function
10276           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10277           | FileIn n | FileOut n ->
10278               pr ", [In] string %s" n
10279           | StringList n | DeviceList n ->
10280               pr ", [In] string[] %s" n
10281           | Bool n ->
10282               pr ", bool %s" n
10283           | Int n ->
10284               pr ", int %s" n
10285           | Int64 n ->
10286               pr ", long %s" n
10287         ) (snd style);
10288         pr ");\n"
10289
10290       and generate_public_prototype () =
10291         pr "    public %s %s (" (csharp_return_type ()) name;
10292         let comma = ref false in
10293         let next () =
10294           if !comma then pr ", ";
10295           comma := true
10296         in
10297         List.iter (
10298           function
10299           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10300           | FileIn n | FileOut n ->
10301               next (); pr "string %s" n
10302           | StringList n | DeviceList n ->
10303               next (); pr "string[] %s" n
10304           | Bool n ->
10305               next (); pr "bool %s" n
10306           | Int n ->
10307               next (); pr "int %s" n
10308           | Int64 n ->
10309               next (); pr "long %s" n
10310         ) (snd style);
10311         pr ")\n"
10312
10313       and generate_call () =
10314         pr "guestfs_%s (_handle" name;
10315         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10316         pr ");\n";
10317       in
10318
10319       pr "    [DllImport (\"%s\")]\n" library;
10320       generate_extern_prototype ();
10321       pr "\n";
10322       pr "    /// <summary>\n";
10323       pr "    /// %s\n" shortdesc;
10324       pr "    /// </summary>\n";
10325       generate_public_prototype ();
10326       pr "    {\n";
10327       pr "      %s r;\n" (c_return_type ());
10328       pr "      r = ";
10329       generate_call ();
10330       pr "      if (r %s)\n" (c_error_comparison ());
10331       pr "        throw new Error (guestfs_last_error (_handle));\n";
10332       (match fst style with
10333        | RErr -> ()
10334        | RBool _ ->
10335            pr "      return r != 0 ? true : false;\n"
10336        | RHashtable _ ->
10337            pr "      Hashtable rr = new Hashtable ();\n";
10338            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10339            pr "        rr.Add (r[i], r[i+1]);\n";
10340            pr "      return rr;\n"
10341        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10342        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10343        | RStructList _ ->
10344            pr "      return r;\n"
10345       );
10346       pr "    }\n";
10347       pr "\n";
10348   ) all_functions_sorted;
10349
10350   pr "  }
10351 }
10352 "
10353
10354 and generate_bindtests () =
10355   generate_header CStyle LGPLv2plus;
10356
10357   pr "\
10358 #include <stdio.h>
10359 #include <stdlib.h>
10360 #include <inttypes.h>
10361 #include <string.h>
10362
10363 #include \"guestfs.h\"
10364 #include \"guestfs-internal.h\"
10365 #include \"guestfs-internal-actions.h\"
10366 #include \"guestfs_protocol.h\"
10367
10368 #define error guestfs_error
10369 #define safe_calloc guestfs_safe_calloc
10370 #define safe_malloc guestfs_safe_malloc
10371
10372 static void
10373 print_strings (char *const *argv)
10374 {
10375   int argc;
10376
10377   printf (\"[\");
10378   for (argc = 0; argv[argc] != NULL; ++argc) {
10379     if (argc > 0) printf (\", \");
10380     printf (\"\\\"%%s\\\"\", argv[argc]);
10381   }
10382   printf (\"]\\n\");
10383 }
10384
10385 /* The test0 function prints its parameters to stdout. */
10386 ";
10387
10388   let test0, tests =
10389     match test_functions with
10390     | [] -> assert false
10391     | test0 :: tests -> test0, tests in
10392
10393   let () =
10394     let (name, style, _, _, _, _, _) = test0 in
10395     generate_prototype ~extern:false ~semicolon:false ~newline:true
10396       ~handle:"g" ~prefix:"guestfs__" name style;
10397     pr "{\n";
10398     List.iter (
10399       function
10400       | Pathname n
10401       | Device n | Dev_or_Path n
10402       | String n
10403       | FileIn n
10404       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10405       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10406       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10407       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10408       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10409       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10410     ) (snd style);
10411     pr "  /* Java changes stdout line buffering so we need this: */\n";
10412     pr "  fflush (stdout);\n";
10413     pr "  return 0;\n";
10414     pr "}\n";
10415     pr "\n" in
10416
10417   List.iter (
10418     fun (name, style, _, _, _, _, _) ->
10419       if String.sub name (String.length name - 3) 3 <> "err" then (
10420         pr "/* Test normal return. */\n";
10421         generate_prototype ~extern:false ~semicolon:false ~newline:true
10422           ~handle:"g" ~prefix:"guestfs__" name style;
10423         pr "{\n";
10424         (match fst style with
10425          | RErr ->
10426              pr "  return 0;\n"
10427          | RInt _ ->
10428              pr "  int r;\n";
10429              pr "  sscanf (val, \"%%d\", &r);\n";
10430              pr "  return r;\n"
10431          | RInt64 _ ->
10432              pr "  int64_t r;\n";
10433              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10434              pr "  return r;\n"
10435          | RBool _ ->
10436              pr "  return STREQ (val, \"true\");\n"
10437          | RConstString _
10438          | RConstOptString _ ->
10439              (* Can't return the input string here.  Return a static
10440               * string so we ensure we get a segfault if the caller
10441               * tries to free it.
10442               *)
10443              pr "  return \"static string\";\n"
10444          | RString _ ->
10445              pr "  return strdup (val);\n"
10446          | RStringList _ ->
10447              pr "  char **strs;\n";
10448              pr "  int n, i;\n";
10449              pr "  sscanf (val, \"%%d\", &n);\n";
10450              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10451              pr "  for (i = 0; i < n; ++i) {\n";
10452              pr "    strs[i] = safe_malloc (g, 16);\n";
10453              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10454              pr "  }\n";
10455              pr "  strs[n] = NULL;\n";
10456              pr "  return strs;\n"
10457          | RStruct (_, typ) ->
10458              pr "  struct guestfs_%s *r;\n" typ;
10459              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10460              pr "  return r;\n"
10461          | RStructList (_, typ) ->
10462              pr "  struct guestfs_%s_list *r;\n" typ;
10463              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10464              pr "  sscanf (val, \"%%d\", &r->len);\n";
10465              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10466              pr "  return r;\n"
10467          | RHashtable _ ->
10468              pr "  char **strs;\n";
10469              pr "  int n, i;\n";
10470              pr "  sscanf (val, \"%%d\", &n);\n";
10471              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10472              pr "  for (i = 0; i < n; ++i) {\n";
10473              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10474              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10475              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10476              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10477              pr "  }\n";
10478              pr "  strs[n*2] = NULL;\n";
10479              pr "  return strs;\n"
10480          | RBufferOut _ ->
10481              pr "  return strdup (val);\n"
10482         );
10483         pr "}\n";
10484         pr "\n"
10485       ) else (
10486         pr "/* Test error return. */\n";
10487         generate_prototype ~extern:false ~semicolon:false ~newline:true
10488           ~handle:"g" ~prefix:"guestfs__" name style;
10489         pr "{\n";
10490         pr "  error (g, \"error\");\n";
10491         (match fst style with
10492          | RErr | RInt _ | RInt64 _ | RBool _ ->
10493              pr "  return -1;\n"
10494          | RConstString _ | RConstOptString _
10495          | RString _ | RStringList _ | RStruct _
10496          | RStructList _
10497          | RHashtable _
10498          | RBufferOut _ ->
10499              pr "  return NULL;\n"
10500         );
10501         pr "}\n";
10502         pr "\n"
10503       )
10504   ) tests
10505
10506 and generate_ocaml_bindtests () =
10507   generate_header OCamlStyle GPLv2plus;
10508
10509   pr "\
10510 let () =
10511   let g = Guestfs.create () in
10512 ";
10513
10514   let mkargs args =
10515     String.concat " " (
10516       List.map (
10517         function
10518         | CallString s -> "\"" ^ s ^ "\""
10519         | CallOptString None -> "None"
10520         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10521         | CallStringList xs ->
10522             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10523         | CallInt i when i >= 0 -> string_of_int i
10524         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10525         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10526         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10527         | CallBool b -> string_of_bool b
10528       ) args
10529     )
10530   in
10531
10532   generate_lang_bindtests (
10533     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10534   );
10535
10536   pr "print_endline \"EOF\"\n"
10537
10538 and generate_perl_bindtests () =
10539   pr "#!/usr/bin/perl -w\n";
10540   generate_header HashStyle GPLv2plus;
10541
10542   pr "\
10543 use strict;
10544
10545 use Sys::Guestfs;
10546
10547 my $g = Sys::Guestfs->new ();
10548 ";
10549
10550   let mkargs args =
10551     String.concat ", " (
10552       List.map (
10553         function
10554         | CallString s -> "\"" ^ s ^ "\""
10555         | CallOptString None -> "undef"
10556         | CallOptString (Some s) -> sprintf "\"%s\"" s
10557         | CallStringList xs ->
10558             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10559         | CallInt i -> string_of_int i
10560         | CallInt64 i -> Int64.to_string i
10561         | CallBool b -> if b then "1" else "0"
10562       ) args
10563     )
10564   in
10565
10566   generate_lang_bindtests (
10567     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10568   );
10569
10570   pr "print \"EOF\\n\"\n"
10571
10572 and generate_python_bindtests () =
10573   generate_header HashStyle GPLv2plus;
10574
10575   pr "\
10576 import guestfs
10577
10578 g = guestfs.GuestFS ()
10579 ";
10580
10581   let mkargs args =
10582     String.concat ", " (
10583       List.map (
10584         function
10585         | CallString s -> "\"" ^ s ^ "\""
10586         | CallOptString None -> "None"
10587         | CallOptString (Some s) -> sprintf "\"%s\"" s
10588         | CallStringList xs ->
10589             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10590         | CallInt i -> string_of_int i
10591         | CallInt64 i -> Int64.to_string i
10592         | CallBool b -> if b then "1" else "0"
10593       ) args
10594     )
10595   in
10596
10597   generate_lang_bindtests (
10598     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10599   );
10600
10601   pr "print \"EOF\"\n"
10602
10603 and generate_ruby_bindtests () =
10604   generate_header HashStyle GPLv2plus;
10605
10606   pr "\
10607 require 'guestfs'
10608
10609 g = Guestfs::create()
10610 ";
10611
10612   let mkargs args =
10613     String.concat ", " (
10614       List.map (
10615         function
10616         | CallString s -> "\"" ^ s ^ "\""
10617         | CallOptString None -> "nil"
10618         | CallOptString (Some s) -> sprintf "\"%s\"" s
10619         | CallStringList xs ->
10620             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10621         | CallInt i -> string_of_int i
10622         | CallInt64 i -> Int64.to_string i
10623         | CallBool b -> string_of_bool b
10624       ) args
10625     )
10626   in
10627
10628   generate_lang_bindtests (
10629     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10630   );
10631
10632   pr "print \"EOF\\n\"\n"
10633
10634 and generate_java_bindtests () =
10635   generate_header CStyle GPLv2plus;
10636
10637   pr "\
10638 import com.redhat.et.libguestfs.*;
10639
10640 public class Bindtests {
10641     public static void main (String[] argv)
10642     {
10643         try {
10644             GuestFS g = new GuestFS ();
10645 ";
10646
10647   let mkargs args =
10648     String.concat ", " (
10649       List.map (
10650         function
10651         | CallString s -> "\"" ^ s ^ "\""
10652         | CallOptString None -> "null"
10653         | CallOptString (Some s) -> sprintf "\"%s\"" s
10654         | CallStringList xs ->
10655             "new String[]{" ^
10656               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10657         | CallInt i -> string_of_int i
10658         | CallInt64 i -> Int64.to_string i
10659         | CallBool b -> string_of_bool b
10660       ) args
10661     )
10662   in
10663
10664   generate_lang_bindtests (
10665     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10666   );
10667
10668   pr "
10669             System.out.println (\"EOF\");
10670         }
10671         catch (Exception exn) {
10672             System.err.println (exn);
10673             System.exit (1);
10674         }
10675     }
10676 }
10677 "
10678
10679 and generate_haskell_bindtests () =
10680   generate_header HaskellStyle GPLv2plus;
10681
10682   pr "\
10683 module Bindtests where
10684 import qualified Guestfs
10685
10686 main = do
10687   g <- Guestfs.create
10688 ";
10689
10690   let mkargs args =
10691     String.concat " " (
10692       List.map (
10693         function
10694         | CallString s -> "\"" ^ s ^ "\""
10695         | CallOptString None -> "Nothing"
10696         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10697         | CallStringList xs ->
10698             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10699         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10700         | CallInt i -> string_of_int i
10701         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10702         | CallInt64 i -> Int64.to_string i
10703         | CallBool true -> "True"
10704         | CallBool false -> "False"
10705       ) args
10706     )
10707   in
10708
10709   generate_lang_bindtests (
10710     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10711   );
10712
10713   pr "  putStrLn \"EOF\"\n"
10714
10715 (* Language-independent bindings tests - we do it this way to
10716  * ensure there is parity in testing bindings across all languages.
10717  *)
10718 and generate_lang_bindtests call =
10719   call "test0" [CallString "abc"; CallOptString (Some "def");
10720                 CallStringList []; CallBool false;
10721                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10722   call "test0" [CallString "abc"; CallOptString None;
10723                 CallStringList []; CallBool false;
10724                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10725   call "test0" [CallString ""; CallOptString (Some "def");
10726                 CallStringList []; CallBool false;
10727                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10728   call "test0" [CallString ""; CallOptString (Some "");
10729                 CallStringList []; CallBool false;
10730                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10731   call "test0" [CallString "abc"; CallOptString (Some "def");
10732                 CallStringList ["1"]; CallBool false;
10733                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10734   call "test0" [CallString "abc"; CallOptString (Some "def");
10735                 CallStringList ["1"; "2"]; CallBool false;
10736                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10737   call "test0" [CallString "abc"; CallOptString (Some "def");
10738                 CallStringList ["1"]; CallBool true;
10739                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10740   call "test0" [CallString "abc"; CallOptString (Some "def");
10741                 CallStringList ["1"]; CallBool false;
10742                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10743   call "test0" [CallString "abc"; CallOptString (Some "def");
10744                 CallStringList ["1"]; CallBool false;
10745                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10746   call "test0" [CallString "abc"; CallOptString (Some "def");
10747                 CallStringList ["1"]; CallBool false;
10748                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10749   call "test0" [CallString "abc"; CallOptString (Some "def");
10750                 CallStringList ["1"]; CallBool false;
10751                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10752   call "test0" [CallString "abc"; CallOptString (Some "def");
10753                 CallStringList ["1"]; CallBool false;
10754                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10755   call "test0" [CallString "abc"; CallOptString (Some "def");
10756                 CallStringList ["1"]; CallBool false;
10757                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10758
10759 (* XXX Add here tests of the return and error functions. *)
10760
10761 (* Code to generator bindings for virt-inspector.  Currently only
10762  * implemented for OCaml code (for virt-p2v 2.0).
10763  *)
10764 let rng_input = "inspector/virt-inspector.rng"
10765
10766 (* Read the input file and parse it into internal structures.  This is
10767  * by no means a complete RELAX NG parser, but is just enough to be
10768  * able to parse the specific input file.
10769  *)
10770 type rng =
10771   | Element of string * rng list        (* <element name=name/> *)
10772   | Attribute of string * rng list        (* <attribute name=name/> *)
10773   | Interleave of rng list                (* <interleave/> *)
10774   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10775   | OneOrMore of rng                        (* <oneOrMore/> *)
10776   | Optional of rng                        (* <optional/> *)
10777   | Choice of string list                (* <choice><value/>*</choice> *)
10778   | Value of string                        (* <value>str</value> *)
10779   | Text                                (* <text/> *)
10780
10781 let rec string_of_rng = function
10782   | Element (name, xs) ->
10783       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10784   | Attribute (name, xs) ->
10785       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10786   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10787   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10788   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10789   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10790   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10791   | Value value -> "Value \"" ^ value ^ "\""
10792   | Text -> "Text"
10793
10794 and string_of_rng_list xs =
10795   String.concat ", " (List.map string_of_rng xs)
10796
10797 let rec parse_rng ?defines context = function
10798   | [] -> []
10799   | Xml.Element ("element", ["name", name], children) :: rest ->
10800       Element (name, parse_rng ?defines context children)
10801       :: parse_rng ?defines context rest
10802   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10803       Attribute (name, parse_rng ?defines context children)
10804       :: parse_rng ?defines context rest
10805   | Xml.Element ("interleave", [], children) :: rest ->
10806       Interleave (parse_rng ?defines context children)
10807       :: parse_rng ?defines context rest
10808   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10809       let rng = parse_rng ?defines context [child] in
10810       (match rng with
10811        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10812        | _ ->
10813            failwithf "%s: <zeroOrMore> contains more than one child element"
10814              context
10815       )
10816   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10817       let rng = parse_rng ?defines context [child] in
10818       (match rng with
10819        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10820        | _ ->
10821            failwithf "%s: <oneOrMore> contains more than one child element"
10822              context
10823       )
10824   | Xml.Element ("optional", [], [child]) :: rest ->
10825       let rng = parse_rng ?defines context [child] in
10826       (match rng with
10827        | [child] -> Optional child :: parse_rng ?defines context rest
10828        | _ ->
10829            failwithf "%s: <optional> contains more than one child element"
10830              context
10831       )
10832   | Xml.Element ("choice", [], children) :: rest ->
10833       let values = List.map (
10834         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10835         | _ ->
10836             failwithf "%s: can't handle anything except <value> in <choice>"
10837               context
10838       ) children in
10839       Choice values
10840       :: parse_rng ?defines context rest
10841   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10842       Value value :: parse_rng ?defines context rest
10843   | Xml.Element ("text", [], []) :: rest ->
10844       Text :: parse_rng ?defines context rest
10845   | Xml.Element ("ref", ["name", name], []) :: rest ->
10846       (* Look up the reference.  Because of limitations in this parser,
10847        * we can't handle arbitrarily nested <ref> yet.  You can only
10848        * use <ref> from inside <start>.
10849        *)
10850       (match defines with
10851        | None ->
10852            failwithf "%s: contains <ref>, but no refs are defined yet" context
10853        | Some map ->
10854            let rng = StringMap.find name map in
10855            rng @ parse_rng ?defines context rest
10856       )
10857   | x :: _ ->
10858       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10859
10860 let grammar =
10861   let xml = Xml.parse_file rng_input in
10862   match xml with
10863   | Xml.Element ("grammar", _,
10864                  Xml.Element ("start", _, gram) :: defines) ->
10865       (* The <define/> elements are referenced in the <start> section,
10866        * so build a map of those first.
10867        *)
10868       let defines = List.fold_left (
10869         fun map ->
10870           function Xml.Element ("define", ["name", name], defn) ->
10871             StringMap.add name defn map
10872           | _ ->
10873               failwithf "%s: expected <define name=name/>" rng_input
10874       ) StringMap.empty defines in
10875       let defines = StringMap.mapi parse_rng defines in
10876
10877       (* Parse the <start> clause, passing the defines. *)
10878       parse_rng ~defines "<start>" gram
10879   | _ ->
10880       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10881         rng_input
10882
10883 let name_of_field = function
10884   | Element (name, _) | Attribute (name, _)
10885   | ZeroOrMore (Element (name, _))
10886   | OneOrMore (Element (name, _))
10887   | Optional (Element (name, _)) -> name
10888   | Optional (Attribute (name, _)) -> name
10889   | Text -> (* an unnamed field in an element *)
10890       "data"
10891   | rng ->
10892       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10893
10894 (* At the moment this function only generates OCaml types.  However we
10895  * should parameterize it later so it can generate types/structs in a
10896  * variety of languages.
10897  *)
10898 let generate_types xs =
10899   (* A simple type is one that can be printed out directly, eg.
10900    * "string option".  A complex type is one which has a name and has
10901    * to be defined via another toplevel definition, eg. a struct.
10902    *
10903    * generate_type generates code for either simple or complex types.
10904    * In the simple case, it returns the string ("string option").  In
10905    * the complex case, it returns the name ("mountpoint").  In the
10906    * complex case it has to print out the definition before returning,
10907    * so it should only be called when we are at the beginning of a
10908    * new line (BOL context).
10909    *)
10910   let rec generate_type = function
10911     | Text ->                                (* string *)
10912         "string", true
10913     | Choice values ->                        (* [`val1|`val2|...] *)
10914         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10915     | ZeroOrMore rng ->                        (* <rng> list *)
10916         let t, is_simple = generate_type rng in
10917         t ^ " list (* 0 or more *)", is_simple
10918     | OneOrMore rng ->                        (* <rng> list *)
10919         let t, is_simple = generate_type rng in
10920         t ^ " list (* 1 or more *)", is_simple
10921                                         (* virt-inspector hack: bool *)
10922     | Optional (Attribute (name, [Value "1"])) ->
10923         "bool", true
10924     | Optional rng ->                        (* <rng> list *)
10925         let t, is_simple = generate_type rng in
10926         t ^ " option", is_simple
10927                                         (* type name = { fields ... } *)
10928     | Element (name, fields) when is_attrs_interleave fields ->
10929         generate_type_struct name (get_attrs_interleave fields)
10930     | Element (name, [field])                (* type name = field *)
10931     | Attribute (name, [field]) ->
10932         let t, is_simple = generate_type field in
10933         if is_simple then (t, true)
10934         else (
10935           pr "type %s = %s\n" name t;
10936           name, false
10937         )
10938     | Element (name, fields) ->              (* type name = { fields ... } *)
10939         generate_type_struct name fields
10940     | rng ->
10941         failwithf "generate_type failed at: %s" (string_of_rng rng)
10942
10943   and is_attrs_interleave = function
10944     | [Interleave _] -> true
10945     | Attribute _ :: fields -> is_attrs_interleave fields
10946     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
10947     | _ -> false
10948
10949   and get_attrs_interleave = function
10950     | [Interleave fields] -> fields
10951     | ((Attribute _) as field) :: fields
10952     | ((Optional (Attribute _)) as field) :: fields ->
10953         field :: get_attrs_interleave fields
10954     | _ -> assert false
10955
10956   and generate_types xs =
10957     List.iter (fun x -> ignore (generate_type x)) xs
10958
10959   and generate_type_struct name fields =
10960     (* Calculate the types of the fields first.  We have to do this
10961      * before printing anything so we are still in BOL context.
10962      *)
10963     let types = List.map fst (List.map generate_type fields) in
10964
10965     (* Special case of a struct containing just a string and another
10966      * field.  Turn it into an assoc list.
10967      *)
10968     match types with
10969     | ["string"; other] ->
10970         let fname1, fname2 =
10971           match fields with
10972           | [f1; f2] -> name_of_field f1, name_of_field f2
10973           | _ -> assert false in
10974         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
10975         name, false
10976
10977     | types ->
10978         pr "type %s = {\n" name;
10979         List.iter (
10980           fun (field, ftype) ->
10981             let fname = name_of_field field in
10982             pr "  %s_%s : %s;\n" name fname ftype
10983         ) (List.combine fields types);
10984         pr "}\n";
10985         (* Return the name of this type, and
10986          * false because it's not a simple type.
10987          *)
10988         name, false
10989   in
10990
10991   generate_types xs
10992
10993 let generate_parsers xs =
10994   (* As for generate_type above, generate_parser makes a parser for
10995    * some type, and returns the name of the parser it has generated.
10996    * Because it (may) need to print something, it should always be
10997    * called in BOL context.
10998    *)
10999   let rec generate_parser = function
11000     | Text ->                                (* string *)
11001         "string_child_or_empty"
11002     | Choice values ->                        (* [`val1|`val2|...] *)
11003         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11004           (String.concat "|"
11005              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11006     | ZeroOrMore rng ->                        (* <rng> list *)
11007         let pa = generate_parser rng in
11008         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11009     | OneOrMore rng ->                        (* <rng> list *)
11010         let pa = generate_parser rng in
11011         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11012                                         (* virt-inspector hack: bool *)
11013     | Optional (Attribute (name, [Value "1"])) ->
11014         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11015     | Optional rng ->                        (* <rng> list *)
11016         let pa = generate_parser rng in
11017         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11018                                         (* type name = { fields ... } *)
11019     | Element (name, fields) when is_attrs_interleave fields ->
11020         generate_parser_struct name (get_attrs_interleave fields)
11021     | Element (name, [field]) ->        (* type name = field *)
11022         let pa = generate_parser field in
11023         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11024         pr "let %s =\n" parser_name;
11025         pr "  %s\n" pa;
11026         pr "let parse_%s = %s\n" name parser_name;
11027         parser_name
11028     | Attribute (name, [field]) ->
11029         let pa = generate_parser field in
11030         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11031         pr "let %s =\n" parser_name;
11032         pr "  %s\n" pa;
11033         pr "let parse_%s = %s\n" name parser_name;
11034         parser_name
11035     | Element (name, fields) ->              (* type name = { fields ... } *)
11036         generate_parser_struct name ([], fields)
11037     | rng ->
11038         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11039
11040   and is_attrs_interleave = function
11041     | [Interleave _] -> true
11042     | Attribute _ :: fields -> is_attrs_interleave fields
11043     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11044     | _ -> false
11045
11046   and get_attrs_interleave = function
11047     | [Interleave fields] -> [], fields
11048     | ((Attribute _) as field) :: fields
11049     | ((Optional (Attribute _)) as field) :: fields ->
11050         let attrs, interleaves = get_attrs_interleave fields in
11051         (field :: attrs), interleaves
11052     | _ -> assert false
11053
11054   and generate_parsers xs =
11055     List.iter (fun x -> ignore (generate_parser x)) xs
11056
11057   and generate_parser_struct name (attrs, interleaves) =
11058     (* Generate parsers for the fields first.  We have to do this
11059      * before printing anything so we are still in BOL context.
11060      *)
11061     let fields = attrs @ interleaves in
11062     let pas = List.map generate_parser fields in
11063
11064     (* Generate an intermediate tuple from all the fields first.
11065      * If the type is just a string + another field, then we will
11066      * return this directly, otherwise it is turned into a record.
11067      *
11068      * RELAX NG note: This code treats <interleave> and plain lists of
11069      * fields the same.  In other words, it doesn't bother enforcing
11070      * any ordering of fields in the XML.
11071      *)
11072     pr "let parse_%s x =\n" name;
11073     pr "  let t = (\n    ";
11074     let comma = ref false in
11075     List.iter (
11076       fun x ->
11077         if !comma then pr ",\n    ";
11078         comma := true;
11079         match x with
11080         | Optional (Attribute (fname, [field])), pa ->
11081             pr "%s x" pa
11082         | Optional (Element (fname, [field])), pa ->
11083             pr "%s (optional_child %S x)" pa fname
11084         | Attribute (fname, [Text]), _ ->
11085             pr "attribute %S x" fname
11086         | (ZeroOrMore _ | OneOrMore _), pa ->
11087             pr "%s x" pa
11088         | Text, pa ->
11089             pr "%s x" pa
11090         | (field, pa) ->
11091             let fname = name_of_field field in
11092             pr "%s (child %S x)" pa fname
11093     ) (List.combine fields pas);
11094     pr "\n  ) in\n";
11095
11096     (match fields with
11097      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11098          pr "  t\n"
11099
11100      | _ ->
11101          pr "  (Obj.magic t : %s)\n" name
11102 (*
11103          List.iter (
11104            function
11105            | (Optional (Attribute (fname, [field])), pa) ->
11106                pr "  %s_%s =\n" name fname;
11107                pr "    %s x;\n" pa
11108            | (Optional (Element (fname, [field])), pa) ->
11109                pr "  %s_%s =\n" name fname;
11110                pr "    (let x = optional_child %S x in\n" fname;
11111                pr "     %s x);\n" pa
11112            | (field, pa) ->
11113                let fname = name_of_field field in
11114                pr "  %s_%s =\n" name fname;
11115                pr "    (let x = child %S x in\n" fname;
11116                pr "     %s x);\n" pa
11117          ) (List.combine fields pas);
11118          pr "}\n"
11119 *)
11120     );
11121     sprintf "parse_%s" name
11122   in
11123
11124   generate_parsers xs
11125
11126 (* Generate ocaml/guestfs_inspector.mli. *)
11127 let generate_ocaml_inspector_mli () =
11128   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11129
11130   pr "\
11131 (** This is an OCaml language binding to the external [virt-inspector]
11132     program.
11133
11134     For more information, please read the man page [virt-inspector(1)].
11135 *)
11136
11137 ";
11138
11139   generate_types grammar;
11140   pr "(** The nested information returned from the {!inspect} function. *)\n";
11141   pr "\n";
11142
11143   pr "\
11144 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11145 (** To inspect a libvirt domain called [name], pass a singleton
11146     list: [inspect [name]].  When using libvirt only, you may
11147     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11148
11149     To inspect a disk image or images, pass a list of the filenames
11150     of the disk images: [inspect filenames]
11151
11152     This function inspects the given guest or disk images and
11153     returns a list of operating system(s) found and a large amount
11154     of information about them.  In the vast majority of cases,
11155     a virtual machine only contains a single operating system.
11156
11157     If the optional [~xml] parameter is given, then this function
11158     skips running the external virt-inspector program and just
11159     parses the given XML directly (which is expected to be XML
11160     produced from a previous run of virt-inspector).  The list of
11161     names and connect URI are ignored in this case.
11162
11163     This function can throw a wide variety of exceptions, for example
11164     if the external virt-inspector program cannot be found, or if
11165     it doesn't generate valid XML.
11166 *)
11167 "
11168
11169 (* Generate ocaml/guestfs_inspector.ml. *)
11170 let generate_ocaml_inspector_ml () =
11171   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11172
11173   pr "open Unix\n";
11174   pr "\n";
11175
11176   generate_types grammar;
11177   pr "\n";
11178
11179   pr "\
11180 (* Misc functions which are used by the parser code below. *)
11181 let first_child = function
11182   | Xml.Element (_, _, c::_) -> c
11183   | Xml.Element (name, _, []) ->
11184       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11185   | Xml.PCData str ->
11186       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11187
11188 let string_child_or_empty = function
11189   | Xml.Element (_, _, [Xml.PCData s]) -> s
11190   | Xml.Element (_, _, []) -> \"\"
11191   | Xml.Element (x, _, _) ->
11192       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11193                 x ^ \" instead\")
11194   | Xml.PCData str ->
11195       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11196
11197 let optional_child name xml =
11198   let children = Xml.children xml in
11199   try
11200     Some (List.find (function
11201                      | Xml.Element (n, _, _) when n = name -> true
11202                      | _ -> false) children)
11203   with
11204     Not_found -> None
11205
11206 let child name xml =
11207   match optional_child name xml with
11208   | Some c -> c
11209   | None ->
11210       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11211
11212 let attribute name xml =
11213   try Xml.attrib xml name
11214   with Xml.No_attribute _ ->
11215     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11216
11217 ";
11218
11219   generate_parsers grammar;
11220   pr "\n";
11221
11222   pr "\
11223 (* Run external virt-inspector, then use parser to parse the XML. *)
11224 let inspect ?connect ?xml names =
11225   let xml =
11226     match xml with
11227     | None ->
11228         if names = [] then invalid_arg \"inspect: no names given\";
11229         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11230           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11231           names in
11232         let cmd = List.map Filename.quote cmd in
11233         let cmd = String.concat \" \" cmd in
11234         let chan = open_process_in cmd in
11235         let xml = Xml.parse_in chan in
11236         (match close_process_in chan with
11237          | WEXITED 0 -> ()
11238          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11239          | WSIGNALED i | WSTOPPED i ->
11240              failwith (\"external virt-inspector command died or stopped on sig \" ^
11241                        string_of_int i)
11242         );
11243         xml
11244     | Some doc ->
11245         Xml.parse_string doc in
11246   parse_operatingsystems xml
11247 "
11248
11249 (* This is used to generate the src/MAX_PROC_NR file which
11250  * contains the maximum procedure number, a surrogate for the
11251  * ABI version number.  See src/Makefile.am for the details.
11252  *)
11253 and generate_max_proc_nr () =
11254   let proc_nrs = List.map (
11255     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11256   ) daemon_functions in
11257
11258   let max_proc_nr = List.fold_left max 0 proc_nrs in
11259
11260   pr "%d\n" max_proc_nr
11261
11262 let output_to filename k =
11263   let filename_new = filename ^ ".new" in
11264   chan := open_out filename_new;
11265   k ();
11266   close_out !chan;
11267   chan := Pervasives.stdout;
11268
11269   (* Is the new file different from the current file? *)
11270   if Sys.file_exists filename && files_equal filename filename_new then
11271     unlink filename_new                 (* same, so skip it *)
11272   else (
11273     (* different, overwrite old one *)
11274     (try chmod filename 0o644 with Unix_error _ -> ());
11275     rename filename_new filename;
11276     chmod filename 0o444;
11277     printf "written %s\n%!" filename;
11278   )
11279
11280 let perror msg = function
11281   | Unix_error (err, _, _) ->
11282       eprintf "%s: %s\n" msg (error_message err)
11283   | exn ->
11284       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11285
11286 (* Main program. *)
11287 let () =
11288   let lock_fd =
11289     try openfile "HACKING" [O_RDWR] 0
11290     with
11291     | Unix_error (ENOENT, _, _) ->
11292         eprintf "\
11293 You are probably running this from the wrong directory.
11294 Run it from the top source directory using the command
11295   src/generator.ml
11296 ";
11297         exit 1
11298     | exn ->
11299         perror "open: HACKING" exn;
11300         exit 1 in
11301
11302   (* Acquire a lock so parallel builds won't try to run the generator
11303    * twice at the same time.  Subsequent builds will wait for the first
11304    * one to finish.  Note the lock is released implicitly when the
11305    * program exits.
11306    *)
11307   (try lockf lock_fd F_LOCK 1
11308    with exn ->
11309      perror "lock: HACKING" exn;
11310      exit 1);
11311
11312   check_functions ();
11313
11314   output_to "src/guestfs_protocol.x" generate_xdr;
11315   output_to "src/guestfs-structs.h" generate_structs_h;
11316   output_to "src/guestfs-actions.h" generate_actions_h;
11317   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11318   output_to "src/guestfs-actions.c" generate_client_actions;
11319   output_to "src/guestfs-bindtests.c" generate_bindtests;
11320   output_to "src/guestfs-structs.pod" generate_structs_pod;
11321   output_to "src/guestfs-actions.pod" generate_actions_pod;
11322   output_to "src/guestfs-availability.pod" generate_availability_pod;
11323   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11324   output_to "src/libguestfs.syms" generate_linker_script;
11325   output_to "daemon/actions.h" generate_daemon_actions_h;
11326   output_to "daemon/stubs.c" generate_daemon_actions;
11327   output_to "daemon/names.c" generate_daemon_names;
11328   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11329   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11330   output_to "capitests/tests.c" generate_tests;
11331   output_to "fish/cmds.c" generate_fish_cmds;
11332   output_to "fish/completion.c" generate_fish_completion;
11333   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11334   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11335   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11336   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11337   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11338   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11339   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11340   output_to "perl/Guestfs.xs" generate_perl_xs;
11341   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11342   output_to "perl/bindtests.pl" generate_perl_bindtests;
11343   output_to "python/guestfs-py.c" generate_python_c;
11344   output_to "python/guestfs.py" generate_python_py;
11345   output_to "python/bindtests.py" generate_python_bindtests;
11346   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11347   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11348   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11349
11350   List.iter (
11351     fun (typ, jtyp) ->
11352       let cols = cols_of_struct typ in
11353       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11354       output_to filename (generate_java_struct jtyp cols);
11355   ) java_structs;
11356
11357   output_to "java/Makefile.inc" generate_java_makefile_inc;
11358   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11359   output_to "java/Bindtests.java" generate_java_bindtests;
11360   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11361   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11362   output_to "csharp/Libguestfs.cs" generate_csharp;
11363
11364   (* Always generate this file last, and unconditionally.  It's used
11365    * by the Makefile to know when we must re-run the generator.
11366    *)
11367   let chan = open_out "src/stamp-generator" in
11368   fprintf chan "1\n";
11369   close_out chan;
11370
11371   printf "generated %d lines of code\n" !lines