New APIs: Query the relationship between LVM objects.
[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,readonly=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 C<readonly=on> is only added where qemu supports this option.
555
556 Note that this call checks for the existence of C<filename>.  This
557 stops you from specifying other types of drive which are supported
558 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
559 the general C<guestfs_config> call instead.");
560
561   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
562    [],
563    "add qemu parameters",
564    "\
565 This can be used to add arbitrary qemu command line parameters
566 of the form C<-param value>.  Actually it's not quite arbitrary - we
567 prevent you from setting some parameters which would interfere with
568 parameters that we use.
569
570 The first character of C<param> string must be a C<-> (dash).
571
572 C<value> can be NULL.");
573
574   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
575    [],
576    "set the qemu binary",
577    "\
578 Set the qemu binary that we will use.
579
580 The default is chosen when the library was compiled by the
581 configure script.
582
583 You can also override this by setting the C<LIBGUESTFS_QEMU>
584 environment variable.
585
586 Setting C<qemu> to C<NULL> restores the default qemu binary.
587
588 Note that you should call this function as early as possible
589 after creating the handle.  This is because some pre-launch
590 operations depend on testing qemu features (by running C<qemu -help>).
591 If the qemu binary changes, we don't retest features, and
592 so you might see inconsistent results.  Using the environment
593 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
594 the qemu binary at the same time as the handle is created.");
595
596   ("get_qemu", (RConstString "qemu", []), -1, [],
597    [InitNone, Always, TestRun (
598       [["get_qemu"]])],
599    "get the qemu binary",
600    "\
601 Return the current qemu binary.
602
603 This is always non-NULL.  If it wasn't set already, then this will
604 return the default qemu binary name.");
605
606   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
607    [],
608    "set the search path",
609    "\
610 Set the path that libguestfs searches for kernel and initrd.img.
611
612 The default is C<$libdir/guestfs> unless overridden by setting
613 C<LIBGUESTFS_PATH> environment variable.
614
615 Setting C<path> to C<NULL> restores the default path.");
616
617   ("get_path", (RConstString "path", []), -1, [],
618    [InitNone, Always, TestRun (
619       [["get_path"]])],
620    "get the search path",
621    "\
622 Return the current search path.
623
624 This is always non-NULL.  If it wasn't set already, then this will
625 return the default path.");
626
627   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
628    [],
629    "add options to kernel command line",
630    "\
631 This function is used to add additional options to the
632 guest kernel command line.
633
634 The default is C<NULL> unless overridden by setting
635 C<LIBGUESTFS_APPEND> environment variable.
636
637 Setting C<append> to C<NULL> means I<no> additional options
638 are passed (libguestfs always adds a few of its own).");
639
640   ("get_append", (RConstOptString "append", []), -1, [],
641    (* This cannot be tested with the current framework.  The
642     * function can return NULL in normal operations, which the
643     * test framework interprets as an error.
644     *)
645    [],
646    "get the additional kernel options",
647    "\
648 Return the additional kernel options which are added to the
649 guest kernel command line.
650
651 If C<NULL> then no options are added.");
652
653   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
654    [],
655    "set autosync mode",
656    "\
657 If C<autosync> is true, this enables autosync.  Libguestfs will make a
658 best effort attempt to run C<guestfs_umount_all> followed by
659 C<guestfs_sync> when the handle is closed
660 (also if the program exits without closing handles).
661
662 This is disabled by default (except in guestfish where it is
663 enabled by default).");
664
665   ("get_autosync", (RBool "autosync", []), -1, [],
666    [InitNone, Always, TestRun (
667       [["get_autosync"]])],
668    "get autosync mode",
669    "\
670 Get the autosync flag.");
671
672   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
673    [],
674    "set verbose mode",
675    "\
676 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
677
678 Verbose messages are disabled unless the environment variable
679 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
680
681   ("get_verbose", (RBool "verbose", []), -1, [],
682    [],
683    "get verbose mode",
684    "\
685 This returns the verbose messages flag.");
686
687   ("is_ready", (RBool "ready", []), -1, [],
688    [InitNone, Always, TestOutputTrue (
689       [["is_ready"]])],
690    "is ready to accept commands",
691    "\
692 This returns true iff this handle is ready to accept commands
693 (in the C<READY> state).
694
695 For more information on states, see L<guestfs(3)>.");
696
697   ("is_config", (RBool "config", []), -1, [],
698    [InitNone, Always, TestOutputFalse (
699       [["is_config"]])],
700    "is in configuration state",
701    "\
702 This returns true iff this handle is being configured
703 (in the C<CONFIG> state).
704
705 For more information on states, see L<guestfs(3)>.");
706
707   ("is_launching", (RBool "launching", []), -1, [],
708    [InitNone, Always, TestOutputFalse (
709       [["is_launching"]])],
710    "is launching subprocess",
711    "\
712 This returns true iff this handle is launching the subprocess
713 (in the C<LAUNCHING> state).
714
715 For more information on states, see L<guestfs(3)>.");
716
717   ("is_busy", (RBool "busy", []), -1, [],
718    [InitNone, Always, TestOutputFalse (
719       [["is_busy"]])],
720    "is busy processing a command",
721    "\
722 This returns true iff this handle is busy processing a command
723 (in the C<BUSY> state).
724
725 For more information on states, see L<guestfs(3)>.");
726
727   ("get_state", (RInt "state", []), -1, [],
728    [],
729    "get the current state",
730    "\
731 This returns the current state as an opaque integer.  This is
732 only useful for printing debug and internal error messages.
733
734 For more information on states, see L<guestfs(3)>.");
735
736   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
737    [InitNone, Always, TestOutputInt (
738       [["set_memsize"; "500"];
739        ["get_memsize"]], 500)],
740    "set memory allocated to the qemu subprocess",
741    "\
742 This sets the memory size in megabytes allocated to the
743 qemu subprocess.  This only has any effect if called before
744 C<guestfs_launch>.
745
746 You can also change this by setting the environment
747 variable C<LIBGUESTFS_MEMSIZE> before the handle is
748 created.
749
750 For more information on the architecture of libguestfs,
751 see L<guestfs(3)>.");
752
753   ("get_memsize", (RInt "memsize", []), -1, [],
754    [InitNone, Always, TestOutputIntOp (
755       [["get_memsize"]], ">=", 256)],
756    "get memory allocated to the qemu subprocess",
757    "\
758 This gets the memory size in megabytes allocated to the
759 qemu subprocess.
760
761 If C<guestfs_set_memsize> was not called
762 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
763 then this returns the compiled-in default value for memsize.
764
765 For more information on the architecture of libguestfs,
766 see L<guestfs(3)>.");
767
768   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
769    [InitNone, Always, TestOutputIntOp (
770       [["get_pid"]], ">=", 1)],
771    "get PID of qemu subprocess",
772    "\
773 Return the process ID of the qemu subprocess.  If there is no
774 qemu subprocess, then this will return an error.
775
776 This is an internal call used for debugging and testing.");
777
778   ("version", (RStruct ("version", "version"), []), -1, [],
779    [InitNone, Always, TestOutputStruct (
780       [["version"]], [CompareWithInt ("major", 1)])],
781    "get the library version number",
782    "\
783 Return the libguestfs version number that the program is linked
784 against.
785
786 Note that because of dynamic linking this is not necessarily
787 the version of libguestfs that you compiled against.  You can
788 compile the program, and then at runtime dynamically link
789 against a completely different C<libguestfs.so> library.
790
791 This call was added in version C<1.0.58>.  In previous
792 versions of libguestfs there was no way to get the version
793 number.  From C code you can use ELF weak linking tricks to find out if
794 this symbol exists (if it doesn't, then it's an earlier version).
795
796 The call returns a structure with four elements.  The first
797 three (C<major>, C<minor> and C<release>) are numbers and
798 correspond to the usual version triplet.  The fourth element
799 (C<extra>) is a string and is normally empty, but may be
800 used for distro-specific information.
801
802 To construct the original version string:
803 C<$major.$minor.$release$extra>
804
805 I<Note:> Don't use this call to test for availability
806 of features.  Distro backports makes this unreliable.  Use
807 C<guestfs_available> instead.");
808
809   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
810    [InitNone, Always, TestOutputTrue (
811       [["set_selinux"; "true"];
812        ["get_selinux"]])],
813    "set SELinux enabled or disabled at appliance boot",
814    "\
815 This sets the selinux flag that is passed to the appliance
816 at boot time.  The default is C<selinux=0> (disabled).
817
818 Note that if SELinux is enabled, it is always in
819 Permissive mode (C<enforcing=0>).
820
821 For more information on the architecture of libguestfs,
822 see L<guestfs(3)>.");
823
824   ("get_selinux", (RBool "selinux", []), -1, [],
825    [],
826    "get SELinux enabled flag",
827    "\
828 This returns the current setting of the selinux flag which
829 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
830
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
833
834   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
835    [InitNone, Always, TestOutputFalse (
836       [["set_trace"; "false"];
837        ["get_trace"]])],
838    "enable or disable command traces",
839    "\
840 If the command trace flag is set to 1, then commands are
841 printed on stdout before they are executed in a format
842 which is very similar to the one used by guestfish.  In
843 other words, you can run a program with this enabled, and
844 you will get out a script which you can feed to guestfish
845 to perform the same set of actions.
846
847 If you want to trace C API calls into libguestfs (and
848 other libraries) then possibly a better way is to use
849 the external ltrace(1) command.
850
851 Command traces are disabled unless the environment variable
852 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
853
854   ("get_trace", (RBool "trace", []), -1, [],
855    [],
856    "get command trace enabled flag",
857    "\
858 Return the command trace flag.");
859
860   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
861    [InitNone, Always, TestOutputFalse (
862       [["set_direct"; "false"];
863        ["get_direct"]])],
864    "enable or disable direct appliance mode",
865    "\
866 If the direct appliance mode flag is enabled, then stdin and
867 stdout are passed directly through to the appliance once it
868 is launched.
869
870 One consequence of this is that log messages aren't caught
871 by the library and handled by C<guestfs_set_log_message_callback>,
872 but go straight to stdout.
873
874 You probably don't want to use this unless you know what you
875 are doing.
876
877 The default is disabled.");
878
879   ("get_direct", (RBool "direct", []), -1, [],
880    [],
881    "get direct appliance mode flag",
882    "\
883 Return the direct appliance mode flag.");
884
885   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
886    [InitNone, Always, TestOutputTrue (
887       [["set_recovery_proc"; "true"];
888        ["get_recovery_proc"]])],
889    "enable or disable the recovery process",
890    "\
891 If this is called with the parameter C<false> then
892 C<guestfs_launch> does not create a recovery process.  The
893 purpose of the recovery process is to stop runaway qemu
894 processes in the case where the main program aborts abruptly.
895
896 This only has any effect if called before C<guestfs_launch>,
897 and the default is true.
898
899 About the only time when you would want to disable this is
900 if the main process will fork itself into the background
901 (\"daemonize\" itself).  In this case the recovery process
902 thinks that the main program has disappeared and so kills
903 qemu, which is not very helpful.");
904
905   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
906    [],
907    "get recovery process enabled flag",
908    "\
909 Return the recovery process enabled flag.");
910
911   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
912    [],
913    "add a drive specifying the QEMU block emulation to use",
914    "\
915 This is the same as C<guestfs_add_drive> but it allows you
916 to specify the QEMU interface emulation to use at run time.");
917
918   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
919    [],
920    "add a drive read-only specifying the QEMU block emulation to use",
921    "\
922 This is the same as C<guestfs_add_drive_ro> but it allows you
923 to specify the QEMU interface emulation to use at run time.");
924
925 ]
926
927 (* daemon_functions are any functions which cause some action
928  * to take place in the daemon.
929  *)
930
931 let daemon_functions = [
932   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
933    [InitEmpty, Always, TestOutput (
934       [["part_disk"; "/dev/sda"; "mbr"];
935        ["mkfs"; "ext2"; "/dev/sda1"];
936        ["mount"; "/dev/sda1"; "/"];
937        ["write_file"; "/new"; "new file contents"; "0"];
938        ["cat"; "/new"]], "new file contents")],
939    "mount a guest disk at a position in the filesystem",
940    "\
941 Mount a guest disk at a position in the filesystem.  Block devices
942 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
943 the guest.  If those block devices contain partitions, they will have
944 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
945 names can be used.
946
947 The rules are the same as for L<mount(2)>:  A filesystem must
948 first be mounted on C</> before others can be mounted.  Other
949 filesystems can only be mounted on directories which already
950 exist.
951
952 The mounted filesystem is writable, if we have sufficient permissions
953 on the underlying device.
954
955 The filesystem options C<sync> and C<noatime> are set with this
956 call, in order to improve reliability.");
957
958   ("sync", (RErr, []), 2, [],
959    [ InitEmpty, Always, TestRun [["sync"]]],
960    "sync disks, writes are flushed through to the disk image",
961    "\
962 This syncs the disk, so that any writes are flushed through to the
963 underlying disk image.
964
965 You should always call this if you have modified a disk image, before
966 closing the handle.");
967
968   ("touch", (RErr, [Pathname "path"]), 3, [],
969    [InitBasicFS, Always, TestOutputTrue (
970       [["touch"; "/new"];
971        ["exists"; "/new"]])],
972    "update file timestamps or create a new file",
973    "\
974 Touch acts like the L<touch(1)> command.  It can be used to
975 update the timestamps on a file, or, if the file does not exist,
976 to create a new zero-length file.");
977
978   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
979    [InitISOFS, Always, TestOutput (
980       [["cat"; "/known-2"]], "abcdef\n")],
981    "list the contents of a file",
982    "\
983 Return the contents of the file named C<path>.
984
985 Note that this function cannot correctly handle binary files
986 (specifically, files containing C<\\0> character which is treated
987 as end of string).  For those you need to use the C<guestfs_read_file>
988 or C<guestfs_download> functions which have a more complex interface.");
989
990   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
991    [], (* XXX Tricky to test because it depends on the exact format
992         * of the 'ls -l' command, which changes between F10 and F11.
993         *)
994    "list the files in a directory (long format)",
995    "\
996 List the files in C<directory> (relative to the root directory,
997 there is no cwd) in the format of 'ls -la'.
998
999 This command is mostly useful for interactive sessions.  It
1000 is I<not> intended that you try to parse the output string.");
1001
1002   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1003    [InitBasicFS, Always, TestOutputList (
1004       [["touch"; "/new"];
1005        ["touch"; "/newer"];
1006        ["touch"; "/newest"];
1007        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1008    "list the files in a directory",
1009    "\
1010 List the files in C<directory> (relative to the root directory,
1011 there is no cwd).  The '.' and '..' entries are not returned, but
1012 hidden files are shown.
1013
1014 This command is mostly useful for interactive sessions.  Programs
1015 should probably use C<guestfs_readdir> instead.");
1016
1017   ("list_devices", (RStringList "devices", []), 7, [],
1018    [InitEmpty, Always, TestOutputListOfDevices (
1019       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1020    "list the block devices",
1021    "\
1022 List all the block devices.
1023
1024 The full block device names are returned, eg. C</dev/sda>");
1025
1026   ("list_partitions", (RStringList "partitions", []), 8, [],
1027    [InitBasicFS, Always, TestOutputListOfDevices (
1028       [["list_partitions"]], ["/dev/sda1"]);
1029     InitEmpty, Always, TestOutputListOfDevices (
1030       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1031        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1032    "list the partitions",
1033    "\
1034 List all the partitions detected on all block devices.
1035
1036 The full partition device names are returned, eg. C</dev/sda1>
1037
1038 This does not return logical volumes.  For that you will need to
1039 call C<guestfs_lvs>.");
1040
1041   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1042    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1043       [["pvs"]], ["/dev/sda1"]);
1044     InitEmpty, Always, TestOutputListOfDevices (
1045       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1046        ["pvcreate"; "/dev/sda1"];
1047        ["pvcreate"; "/dev/sda2"];
1048        ["pvcreate"; "/dev/sda3"];
1049        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1050    "list the LVM physical volumes (PVs)",
1051    "\
1052 List all the physical volumes detected.  This is the equivalent
1053 of the L<pvs(8)> command.
1054
1055 This returns a list of just the device names that contain
1056 PVs (eg. C</dev/sda2>).
1057
1058 See also C<guestfs_pvs_full>.");
1059
1060   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1061    [InitBasicFSonLVM, Always, TestOutputList (
1062       [["vgs"]], ["VG"]);
1063     InitEmpty, Always, TestOutputList (
1064       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1065        ["pvcreate"; "/dev/sda1"];
1066        ["pvcreate"; "/dev/sda2"];
1067        ["pvcreate"; "/dev/sda3"];
1068        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1069        ["vgcreate"; "VG2"; "/dev/sda3"];
1070        ["vgs"]], ["VG1"; "VG2"])],
1071    "list the LVM volume groups (VGs)",
1072    "\
1073 List all the volumes groups detected.  This is the equivalent
1074 of the L<vgs(8)> command.
1075
1076 This returns a list of just the volume group names that were
1077 detected (eg. C<VolGroup00>).
1078
1079 See also C<guestfs_vgs_full>.");
1080
1081   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1082    [InitBasicFSonLVM, Always, TestOutputList (
1083       [["lvs"]], ["/dev/VG/LV"]);
1084     InitEmpty, Always, TestOutputList (
1085       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1086        ["pvcreate"; "/dev/sda1"];
1087        ["pvcreate"; "/dev/sda2"];
1088        ["pvcreate"; "/dev/sda3"];
1089        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1090        ["vgcreate"; "VG2"; "/dev/sda3"];
1091        ["lvcreate"; "LV1"; "VG1"; "50"];
1092        ["lvcreate"; "LV2"; "VG1"; "50"];
1093        ["lvcreate"; "LV3"; "VG2"; "50"];
1094        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1095    "list the LVM logical volumes (LVs)",
1096    "\
1097 List all the logical volumes detected.  This is the equivalent
1098 of the L<lvs(8)> command.
1099
1100 This returns a list of the logical volume device names
1101 (eg. C</dev/VolGroup00/LogVol00>).
1102
1103 See also C<guestfs_lvs_full>.");
1104
1105   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1106    [], (* XXX how to test? *)
1107    "list the LVM physical volumes (PVs)",
1108    "\
1109 List all the physical volumes detected.  This is the equivalent
1110 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1111
1112   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1113    [], (* XXX how to test? *)
1114    "list the LVM volume groups (VGs)",
1115    "\
1116 List all the volumes groups detected.  This is the equivalent
1117 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1118
1119   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1120    [], (* XXX how to test? *)
1121    "list the LVM logical volumes (LVs)",
1122    "\
1123 List all the logical volumes detected.  This is the equivalent
1124 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1125
1126   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1127    [InitISOFS, Always, TestOutputList (
1128       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1129     InitISOFS, Always, TestOutputList (
1130       [["read_lines"; "/empty"]], [])],
1131    "read file as lines",
1132    "\
1133 Return the contents of the file named C<path>.
1134
1135 The file contents are returned as a list of lines.  Trailing
1136 C<LF> and C<CRLF> character sequences are I<not> returned.
1137
1138 Note that this function cannot correctly handle binary files
1139 (specifically, files containing C<\\0> character which is treated
1140 as end of line).  For those you need to use the C<guestfs_read_file>
1141 function which has a more complex interface.");
1142
1143   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1144    [], (* XXX Augeas code needs tests. *)
1145    "create a new Augeas handle",
1146    "\
1147 Create a new Augeas handle for editing configuration files.
1148 If there was any previous Augeas handle associated with this
1149 guestfs session, then it is closed.
1150
1151 You must call this before using any other C<guestfs_aug_*>
1152 commands.
1153
1154 C<root> is the filesystem root.  C<root> must not be NULL,
1155 use C</> instead.
1156
1157 The flags are the same as the flags defined in
1158 E<lt>augeas.hE<gt>, the logical I<or> of the following
1159 integers:
1160
1161 =over 4
1162
1163 =item C<AUG_SAVE_BACKUP> = 1
1164
1165 Keep the original file with a C<.augsave> extension.
1166
1167 =item C<AUG_SAVE_NEWFILE> = 2
1168
1169 Save changes into a file with extension C<.augnew>, and
1170 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1171
1172 =item C<AUG_TYPE_CHECK> = 4
1173
1174 Typecheck lenses (can be expensive).
1175
1176 =item C<AUG_NO_STDINC> = 8
1177
1178 Do not use standard load path for modules.
1179
1180 =item C<AUG_SAVE_NOOP> = 16
1181
1182 Make save a no-op, just record what would have been changed.
1183
1184 =item C<AUG_NO_LOAD> = 32
1185
1186 Do not load the tree in C<guestfs_aug_init>.
1187
1188 =back
1189
1190 To close the handle, you can call C<guestfs_aug_close>.
1191
1192 To find out more about Augeas, see L<http://augeas.net/>.");
1193
1194   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1195    [], (* XXX Augeas code needs tests. *)
1196    "close the current Augeas handle",
1197    "\
1198 Close the current Augeas handle and free up any resources
1199 used by it.  After calling this, you have to call
1200 C<guestfs_aug_init> again before you can use any other
1201 Augeas functions.");
1202
1203   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1204    [], (* XXX Augeas code needs tests. *)
1205    "define an Augeas variable",
1206    "\
1207 Defines an Augeas variable C<name> whose value is the result
1208 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1209 undefined.
1210
1211 On success this returns the number of nodes in C<expr>, or
1212 C<0> if C<expr> evaluates to something which is not a nodeset.");
1213
1214   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "define an Augeas node",
1217    "\
1218 Defines a variable C<name> whose value is the result of
1219 evaluating C<expr>.
1220
1221 If C<expr> evaluates to an empty nodeset, a node is created,
1222 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1223 C<name> will be the nodeset containing that single node.
1224
1225 On success this returns a pair containing the
1226 number of nodes in the nodeset, and a boolean flag
1227 if a node was created.");
1228
1229   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1230    [], (* XXX Augeas code needs tests. *)
1231    "look up the value of an Augeas path",
1232    "\
1233 Look up the value associated with C<path>.  If C<path>
1234 matches exactly one node, the C<value> is returned.");
1235
1236   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1237    [], (* XXX Augeas code needs tests. *)
1238    "set Augeas path to value",
1239    "\
1240 Set the value associated with C<path> to C<value>.");
1241
1242   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "insert a sibling Augeas node",
1245    "\
1246 Create a new sibling C<label> for C<path>, inserting it into
1247 the tree before or after C<path> (depending on the boolean
1248 flag C<before>).
1249
1250 C<path> must match exactly one existing node in the tree, and
1251 C<label> must be a label, ie. not contain C</>, C<*> or end
1252 with a bracketed index C<[N]>.");
1253
1254   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1255    [], (* XXX Augeas code needs tests. *)
1256    "remove an Augeas path",
1257    "\
1258 Remove C<path> and all of its children.
1259
1260 On success this returns the number of entries which were removed.");
1261
1262   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1263    [], (* XXX Augeas code needs tests. *)
1264    "move Augeas node",
1265    "\
1266 Move the node C<src> to C<dest>.  C<src> must match exactly
1267 one node.  C<dest> is overwritten if it exists.");
1268
1269   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1270    [], (* XXX Augeas code needs tests. *)
1271    "return Augeas nodes which match augpath",
1272    "\
1273 Returns a list of paths which match the path expression C<path>.
1274 The returned paths are sufficiently qualified so that they match
1275 exactly one node in the current tree.");
1276
1277   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1278    [], (* XXX Augeas code needs tests. *)
1279    "write all pending Augeas changes to disk",
1280    "\
1281 This writes all pending changes to disk.
1282
1283 The flags which were passed to C<guestfs_aug_init> affect exactly
1284 how files are saved.");
1285
1286   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "load files into the tree",
1289    "\
1290 Load files into the tree.
1291
1292 See C<aug_load> in the Augeas documentation for the full gory
1293 details.");
1294
1295   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "list Augeas nodes under augpath",
1298    "\
1299 This is just a shortcut for listing C<guestfs_aug_match>
1300 C<path/*> and sorting the resulting nodes into alphabetical order.");
1301
1302   ("rm", (RErr, [Pathname "path"]), 29, [],
1303    [InitBasicFS, Always, TestRun
1304       [["touch"; "/new"];
1305        ["rm"; "/new"]];
1306     InitBasicFS, Always, TestLastFail
1307       [["rm"; "/new"]];
1308     InitBasicFS, Always, TestLastFail
1309       [["mkdir"; "/new"];
1310        ["rm"; "/new"]]],
1311    "remove a file",
1312    "\
1313 Remove the single file C<path>.");
1314
1315   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1316    [InitBasicFS, Always, TestRun
1317       [["mkdir"; "/new"];
1318        ["rmdir"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["rmdir"; "/new"]];
1321     InitBasicFS, Always, TestLastFail
1322       [["touch"; "/new"];
1323        ["rmdir"; "/new"]]],
1324    "remove a directory",
1325    "\
1326 Remove the single directory C<path>.");
1327
1328   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1329    [InitBasicFS, Always, TestOutputFalse
1330       [["mkdir"; "/new"];
1331        ["mkdir"; "/new/foo"];
1332        ["touch"; "/new/foo/bar"];
1333        ["rm_rf"; "/new"];
1334        ["exists"; "/new"]]],
1335    "remove a file or directory recursively",
1336    "\
1337 Remove the file or directory C<path>, recursively removing the
1338 contents if its a directory.  This is like the C<rm -rf> shell
1339 command.");
1340
1341   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1342    [InitBasicFS, Always, TestOutputTrue
1343       [["mkdir"; "/new"];
1344        ["is_dir"; "/new"]];
1345     InitBasicFS, Always, TestLastFail
1346       [["mkdir"; "/new/foo/bar"]]],
1347    "create a directory",
1348    "\
1349 Create a directory named C<path>.");
1350
1351   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1352    [InitBasicFS, Always, TestOutputTrue
1353       [["mkdir_p"; "/new/foo/bar"];
1354        ["is_dir"; "/new/foo/bar"]];
1355     InitBasicFS, Always, TestOutputTrue
1356       [["mkdir_p"; "/new/foo/bar"];
1357        ["is_dir"; "/new/foo"]];
1358     InitBasicFS, Always, TestOutputTrue
1359       [["mkdir_p"; "/new/foo/bar"];
1360        ["is_dir"; "/new"]];
1361     (* Regression tests for RHBZ#503133: *)
1362     InitBasicFS, Always, TestRun
1363       [["mkdir"; "/new"];
1364        ["mkdir_p"; "/new"]];
1365     InitBasicFS, Always, TestLastFail
1366       [["touch"; "/new"];
1367        ["mkdir_p"; "/new"]]],
1368    "create a directory and parents",
1369    "\
1370 Create a directory named C<path>, creating any parent directories
1371 as necessary.  This is like the C<mkdir -p> shell command.");
1372
1373   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1374    [], (* XXX Need stat command to test *)
1375    "change file mode",
1376    "\
1377 Change the mode (permissions) of C<path> to C<mode>.  Only
1378 numeric modes are supported.
1379
1380 I<Note>: When using this command from guestfish, C<mode>
1381 by default would be decimal, unless you prefix it with
1382 C<0> to get octal, ie. use C<0700> not C<700>.");
1383
1384   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1385    [], (* XXX Need stat command to test *)
1386    "change file owner and group",
1387    "\
1388 Change the file owner to C<owner> and group to C<group>.
1389
1390 Only numeric uid and gid are supported.  If you want to use
1391 names, you will need to locate and parse the password file
1392 yourself (Augeas support makes this relatively easy).");
1393
1394   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1395    [InitISOFS, Always, TestOutputTrue (
1396       [["exists"; "/empty"]]);
1397     InitISOFS, Always, TestOutputTrue (
1398       [["exists"; "/directory"]])],
1399    "test if file or directory exists",
1400    "\
1401 This returns C<true> if and only if there is a file, directory
1402 (or anything) with the given C<path> name.
1403
1404 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1405
1406   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1407    [InitISOFS, Always, TestOutputTrue (
1408       [["is_file"; "/known-1"]]);
1409     InitISOFS, Always, TestOutputFalse (
1410       [["is_file"; "/directory"]])],
1411    "test if file exists",
1412    "\
1413 This returns C<true> if and only if there is a file
1414 with the given C<path> name.  Note that it returns false for
1415 other objects like directories.
1416
1417 See also C<guestfs_stat>.");
1418
1419   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1420    [InitISOFS, Always, TestOutputFalse (
1421       [["is_dir"; "/known-3"]]);
1422     InitISOFS, Always, TestOutputTrue (
1423       [["is_dir"; "/directory"]])],
1424    "test if file exists",
1425    "\
1426 This returns C<true> if and only if there is a directory
1427 with the given C<path> name.  Note that it returns false for
1428 other objects like files.
1429
1430 See also C<guestfs_stat>.");
1431
1432   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1433    [InitEmpty, Always, TestOutputListOfDevices (
1434       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1435        ["pvcreate"; "/dev/sda1"];
1436        ["pvcreate"; "/dev/sda2"];
1437        ["pvcreate"; "/dev/sda3"];
1438        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1439    "create an LVM physical volume",
1440    "\
1441 This creates an LVM physical volume on the named C<device>,
1442 where C<device> should usually be a partition name such
1443 as C</dev/sda1>.");
1444
1445   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1446    [InitEmpty, Always, TestOutputList (
1447       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448        ["pvcreate"; "/dev/sda1"];
1449        ["pvcreate"; "/dev/sda2"];
1450        ["pvcreate"; "/dev/sda3"];
1451        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1452        ["vgcreate"; "VG2"; "/dev/sda3"];
1453        ["vgs"]], ["VG1"; "VG2"])],
1454    "create an LVM volume group",
1455    "\
1456 This creates an LVM volume group called C<volgroup>
1457 from the non-empty list of physical volumes C<physvols>.");
1458
1459   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1460    [InitEmpty, Always, TestOutputList (
1461       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462        ["pvcreate"; "/dev/sda1"];
1463        ["pvcreate"; "/dev/sda2"];
1464        ["pvcreate"; "/dev/sda3"];
1465        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1466        ["vgcreate"; "VG2"; "/dev/sda3"];
1467        ["lvcreate"; "LV1"; "VG1"; "50"];
1468        ["lvcreate"; "LV2"; "VG1"; "50"];
1469        ["lvcreate"; "LV3"; "VG2"; "50"];
1470        ["lvcreate"; "LV4"; "VG2"; "50"];
1471        ["lvcreate"; "LV5"; "VG2"; "50"];
1472        ["lvs"]],
1473       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1474        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1475    "create an LVM volume group",
1476    "\
1477 This creates an LVM volume group called C<logvol>
1478 on the volume group C<volgroup>, with C<size> megabytes.");
1479
1480   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1481    [InitEmpty, Always, TestOutput (
1482       [["part_disk"; "/dev/sda"; "mbr"];
1483        ["mkfs"; "ext2"; "/dev/sda1"];
1484        ["mount_options"; ""; "/dev/sda1"; "/"];
1485        ["write_file"; "/new"; "new file contents"; "0"];
1486        ["cat"; "/new"]], "new file contents")],
1487    "make a filesystem",
1488    "\
1489 This creates a filesystem on C<device> (usually a partition
1490 or LVM logical volume).  The filesystem type is C<fstype>, for
1491 example C<ext3>.");
1492
1493   ("sfdisk", (RErr, [Device "device";
1494                      Int "cyls"; Int "heads"; Int "sectors";
1495                      StringList "lines"]), 43, [DangerWillRobinson],
1496    [],
1497    "create partitions on a block device",
1498    "\
1499 This is a direct interface to the L<sfdisk(8)> program for creating
1500 partitions on block devices.
1501
1502 C<device> should be a block device, for example C</dev/sda>.
1503
1504 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1505 and sectors on the device, which are passed directly to sfdisk as
1506 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1507 of these, then the corresponding parameter is omitted.  Usually for
1508 'large' disks, you can just pass C<0> for these, but for small
1509 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1510 out the right geometry and you will need to tell it.
1511
1512 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1513 information refer to the L<sfdisk(8)> manpage.
1514
1515 To create a single partition occupying the whole disk, you would
1516 pass C<lines> as a single element list, when the single element being
1517 the string C<,> (comma).
1518
1519 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1520 C<guestfs_part_init>");
1521
1522   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1523    [InitBasicFS, Always, TestOutput (
1524       [["write_file"; "/new"; "new file contents"; "0"];
1525        ["cat"; "/new"]], "new file contents");
1526     InitBasicFS, Always, TestOutput (
1527       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1528        ["cat"; "/new"]], "\nnew file contents\n");
1529     InitBasicFS, Always, TestOutput (
1530       [["write_file"; "/new"; "\n\n"; "0"];
1531        ["cat"; "/new"]], "\n\n");
1532     InitBasicFS, Always, TestOutput (
1533       [["write_file"; "/new"; ""; "0"];
1534        ["cat"; "/new"]], "");
1535     InitBasicFS, Always, TestOutput (
1536       [["write_file"; "/new"; "\n\n\n"; "0"];
1537        ["cat"; "/new"]], "\n\n\n");
1538     InitBasicFS, Always, TestOutput (
1539       [["write_file"; "/new"; "\n"; "0"];
1540        ["cat"; "/new"]], "\n")],
1541    "create a file",
1542    "\
1543 This call creates a file called C<path>.  The contents of the
1544 file is the string C<content> (which can contain any 8 bit data),
1545 with length C<size>.
1546
1547 As a special case, if C<size> is C<0>
1548 then the length is calculated using C<strlen> (so in this case
1549 the content cannot contain embedded ASCII NULs).
1550
1551 I<NB.> Owing to a bug, writing content containing ASCII NUL
1552 characters does I<not> work, even if the length is specified.
1553 We hope to resolve this bug in a future version.  In the meantime
1554 use C<guestfs_upload>.");
1555
1556   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557    [InitEmpty, Always, TestOutputListOfDevices (
1558       [["part_disk"; "/dev/sda"; "mbr"];
1559        ["mkfs"; "ext2"; "/dev/sda1"];
1560        ["mount_options"; ""; "/dev/sda1"; "/"];
1561        ["mounts"]], ["/dev/sda1"]);
1562     InitEmpty, Always, TestOutputList (
1563       [["part_disk"; "/dev/sda"; "mbr"];
1564        ["mkfs"; "ext2"; "/dev/sda1"];
1565        ["mount_options"; ""; "/dev/sda1"; "/"];
1566        ["umount"; "/"];
1567        ["mounts"]], [])],
1568    "unmount a filesystem",
1569    "\
1570 This unmounts the given filesystem.  The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1573
1574   ("mounts", (RStringList "devices", []), 46, [],
1575    [InitBasicFS, Always, TestOutputListOfDevices (
1576       [["mounts"]], ["/dev/sda1"])],
1577    "show mounted filesystems",
1578    "\
1579 This returns the list of currently mounted filesystems.  It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1581
1582 Some internal mounts are not shown.
1583
1584 See also: C<guestfs_mountpoints>");
1585
1586   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587    [InitBasicFS, Always, TestOutputList (
1588       [["umount_all"];
1589        ["mounts"]], []);
1590     (* check that umount_all can unmount nested mounts correctly: *)
1591     InitEmpty, Always, TestOutputList (
1592       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593        ["mkfs"; "ext2"; "/dev/sda1"];
1594        ["mkfs"; "ext2"; "/dev/sda2"];
1595        ["mkfs"; "ext2"; "/dev/sda3"];
1596        ["mount_options"; ""; "/dev/sda1"; "/"];
1597        ["mkdir"; "/mp1"];
1598        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599        ["mkdir"; "/mp1/mp2"];
1600        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601        ["mkdir"; "/mp1/mp2/mp3"];
1602        ["umount_all"];
1603        ["mounts"]], [])],
1604    "unmount all filesystems",
1605    "\
1606 This unmounts all mounted filesystems.
1607
1608 Some internal mounts are not unmounted by this call.");
1609
1610   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1611    [],
1612    "remove all LVM LVs, VGs and PVs",
1613    "\
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1616
1617   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618    [InitISOFS, Always, TestOutput (
1619       [["file"; "/empty"]], "empty");
1620     InitISOFS, Always, TestOutput (
1621       [["file"; "/known-1"]], "ASCII text");
1622     InitISOFS, Always, TestLastFail (
1623       [["file"; "/notexists"]])],
1624    "determine file type",
1625    "\
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file.  This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1629
1630 This call will also transparently look inside various types
1631 of compressed file.
1632
1633 The exact command which runs is C<file -zbsL path>.  Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1636
1637   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638    [InitBasicFS, Always, TestOutput (
1639       [["upload"; "test-command"; "/test-command"];
1640        ["chmod"; "0o755"; "/test-command"];
1641        ["command"; "/test-command 1"]], "Result1");
1642     InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 2"]], "Result2\n");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 3"]], "\nResult3");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 4"]], "\nResult4\n");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 5"]], "\nResult5\n\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 7"]], "");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 8"]], "\n");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 9"]], "\n\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682     InitBasicFS, Always, TestLastFail (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command"]])],
1686    "run a command from the guest filesystem",
1687    "\
1688 This call runs a command from the guest filesystem.  The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1692
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters.  The list must be
1696 non-empty (ie. must contain a program name).  Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1699
1700 The return value is anything printed to I<stdout> by
1701 the command.
1702
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message.  The error message
1705 string is the content of I<stderr> from the command.
1706
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>.  If you require a program from
1709 another location, you should provide the full path in the
1710 first parameter.
1711
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places.  It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1716 locations.");
1717
1718   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719    [InitBasicFS, Always, TestOutputList (
1720       [["upload"; "test-command"; "/test-command"];
1721        ["chmod"; "0o755"; "/test-command"];
1722        ["command_lines"; "/test-command 1"]], ["Result1"]);
1723     InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 2"]], ["Result2"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 7"]], []);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 8"]], [""]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 9"]], ["";""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763    "run a command, returning lines",
1764    "\
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1767
1768 See also: C<guestfs_sh_lines>");
1769
1770   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771    [InitISOFS, Always, TestOutputStruct (
1772       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773    "get file information",
1774    "\
1775 Returns file information for the given C<path>.
1776
1777 This is the same as the C<stat(2)> system call.");
1778
1779   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780    [InitISOFS, Always, TestOutputStruct (
1781       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782    "get file information for a symbolic link",
1783    "\
1784 Returns file information for the given C<path>.
1785
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1788 refers to.
1789
1790 This is the same as the C<lstat(2)> system call.");
1791
1792   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795    "get file system statistics",
1796    "\
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1800
1801 This is the same as the C<statvfs(2)> system call.");
1802
1803   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1804    [], (* XXX test *)
1805    "get ext2/ext3/ext4 superblock details",
1806    "\
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1809
1810 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1811 manpage for more details.  The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1814
1815   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816    [InitEmpty, Always, TestOutputTrue (
1817       [["blockdev_setro"; "/dev/sda"];
1818        ["blockdev_getro"; "/dev/sda"]])],
1819    "set block device to read-only",
1820    "\
1821 Sets the block device named C<device> to read-only.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826    [InitEmpty, Always, TestOutputFalse (
1827       [["blockdev_setrw"; "/dev/sda"];
1828        ["blockdev_getro"; "/dev/sda"]])],
1829    "set block device to read-write",
1830    "\
1831 Sets the block device named C<device> to read-write.
1832
1833 This uses the L<blockdev(8)> command.");
1834
1835   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "is block device set to read-only",
1840    "\
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847    [InitEmpty, Always, TestOutputInt (
1848       [["blockdev_getss"; "/dev/sda"]], 512)],
1849    "get sectorsize of block device",
1850    "\
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1853
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1855 for that).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862    "get blocksize of block device",
1863    "\
1864 This returns the block size of a device.
1865
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1872    [], (* XXX test *)
1873    "set blocksize of block device",
1874    "\
1875 This sets the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885    "get total size of device in 512-byte sectors",
1886    "\
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1889
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1893
1894 This uses the L<blockdev(8)> command.");
1895
1896   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897    [InitEmpty, Always, TestOutputInt (
1898       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899    "get total size of device in bytes",
1900    "\
1901 This returns the size of the device in bytes.
1902
1903 See also C<guestfs_blockdev_getsz>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908    [InitEmpty, Always, TestRun
1909       [["blockdev_flushbufs"; "/dev/sda"]]],
1910    "flush device buffers",
1911    "\
1912 This tells the kernel to flush internal buffers associated
1913 with C<device>.
1914
1915 This uses the L<blockdev(8)> command.");
1916
1917   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918    [InitEmpty, Always, TestRun
1919       [["blockdev_rereadpt"; "/dev/sda"]]],
1920    "reread partition table",
1921    "\
1922 Reread the partition table on C<device>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927    [InitBasicFS, Always, TestOutput (
1928       (* Pick a file from cwd which isn't likely to change. *)
1929       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930        ["checksum"; "md5"; "/COPYING.LIB"]],
1931       Digest.to_hex (Digest.file "COPYING.LIB"))],
1932    "upload a file from the local machine",
1933    "\
1934 Upload local file C<filename> to C<remotefilename> on the
1935 filesystem.
1936
1937 C<filename> can also be a named pipe.
1938
1939 See also C<guestfs_download>.");
1940
1941   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942    [InitBasicFS, Always, TestOutput (
1943       (* Pick a file from cwd which isn't likely to change. *)
1944       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946        ["upload"; "testdownload.tmp"; "/upload"];
1947        ["checksum"; "md5"; "/upload"]],
1948       Digest.to_hex (Digest.file "COPYING.LIB"))],
1949    "download a file to the local machine",
1950    "\
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1953
1954 C<filename> can also be a named pipe.
1955
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1957
1958   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959    [InitISOFS, Always, TestOutput (
1960       [["checksum"; "crc"; "/known-3"]], "2891671662");
1961     InitISOFS, Always, TestLastFail (
1962       [["checksum"; "crc"; "/notexists"]]);
1963     InitISOFS, Always, TestOutput (
1964       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965     InitISOFS, Always, TestOutput (
1966       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1975    "compute MD5, SHAx or CRC checksum of file",
1976    "\
1977 This call computes the MD5, SHAx or CRC checksum of the
1978 file named C<path>.
1979
1980 The type of checksum to compute is given by the C<csumtype>
1981 parameter which must have one of the following values:
1982
1983 =over 4
1984
1985 =item C<crc>
1986
1987 Compute the cyclic redundancy check (CRC) specified by POSIX
1988 for the C<cksum> command.
1989
1990 =item C<md5>
1991
1992 Compute the MD5 hash (using the C<md5sum> program).
1993
1994 =item C<sha1>
1995
1996 Compute the SHA1 hash (using the C<sha1sum> program).
1997
1998 =item C<sha224>
1999
2000 Compute the SHA224 hash (using the C<sha224sum> program).
2001
2002 =item C<sha256>
2003
2004 Compute the SHA256 hash (using the C<sha256sum> program).
2005
2006 =item C<sha384>
2007
2008 Compute the SHA384 hash (using the C<sha384sum> program).
2009
2010 =item C<sha512>
2011
2012 Compute the SHA512 hash (using the C<sha512sum> program).
2013
2014 =back
2015
2016 The checksum is returned as a printable string.");
2017
2018   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2019    [InitBasicFS, Always, TestOutput (
2020       [["tar_in"; "../images/helloworld.tar"; "/"];
2021        ["cat"; "/hello"]], "hello\n")],
2022    "unpack tarfile to directory",
2023    "\
2024 This command uploads and unpacks local file C<tarfile> (an
2025 I<uncompressed> tar file) into C<directory>.
2026
2027 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2028
2029   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2030    [],
2031    "pack directory into tarfile",
2032    "\
2033 This command packs the contents of C<directory> and downloads
2034 it to local file C<tarfile>.
2035
2036 To download a compressed tarball, use C<guestfs_tgz_out>.");
2037
2038   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2039    [InitBasicFS, Always, TestOutput (
2040       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2041        ["cat"; "/hello"]], "hello\n")],
2042    "unpack compressed tarball to directory",
2043    "\
2044 This command uploads and unpacks local file C<tarball> (a
2045 I<gzip compressed> tar file) into C<directory>.
2046
2047 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2048
2049   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2050    [],
2051    "pack directory into compressed tarball",
2052    "\
2053 This command packs the contents of C<directory> and downloads
2054 it to local file C<tarball>.
2055
2056 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2057
2058   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2059    [InitBasicFS, Always, TestLastFail (
2060       [["umount"; "/"];
2061        ["mount_ro"; "/dev/sda1"; "/"];
2062        ["touch"; "/new"]]);
2063     InitBasicFS, Always, TestOutput (
2064       [["write_file"; "/new"; "data"; "0"];
2065        ["umount"; "/"];
2066        ["mount_ro"; "/dev/sda1"; "/"];
2067        ["cat"; "/new"]], "data")],
2068    "mount a guest disk, read-only",
2069    "\
2070 This is the same as the C<guestfs_mount> command, but it
2071 mounts the filesystem with the read-only (I<-o ro>) flag.");
2072
2073   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2074    [],
2075    "mount a guest disk with mount options",
2076    "\
2077 This is the same as the C<guestfs_mount> command, but it
2078 allows you to set the mount options as for the
2079 L<mount(8)> I<-o> flag.");
2080
2081   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2082    [],
2083    "mount a guest disk with mount options and vfstype",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 allows you to set both the mount options and the vfstype
2087 as for the L<mount(8)> I<-o> and I<-t> flags.");
2088
2089   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2090    [],
2091    "debugging and internals",
2092    "\
2093 The C<guestfs_debug> command exposes some internals of
2094 C<guestfsd> (the guestfs daemon) that runs inside the
2095 qemu subprocess.
2096
2097 There is no comprehensive help for this command.  You have
2098 to look at the file C<daemon/debug.c> in the libguestfs source
2099 to find out what you can do.");
2100
2101   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2102    [InitEmpty, Always, TestOutputList (
2103       [["part_disk"; "/dev/sda"; "mbr"];
2104        ["pvcreate"; "/dev/sda1"];
2105        ["vgcreate"; "VG"; "/dev/sda1"];
2106        ["lvcreate"; "LV1"; "VG"; "50"];
2107        ["lvcreate"; "LV2"; "VG"; "50"];
2108        ["lvremove"; "/dev/VG/LV1"];
2109        ["lvs"]], ["/dev/VG/LV2"]);
2110     InitEmpty, Always, TestOutputList (
2111       [["part_disk"; "/dev/sda"; "mbr"];
2112        ["pvcreate"; "/dev/sda1"];
2113        ["vgcreate"; "VG"; "/dev/sda1"];
2114        ["lvcreate"; "LV1"; "VG"; "50"];
2115        ["lvcreate"; "LV2"; "VG"; "50"];
2116        ["lvremove"; "/dev/VG"];
2117        ["lvs"]], []);
2118     InitEmpty, Always, TestOutputList (
2119       [["part_disk"; "/dev/sda"; "mbr"];
2120        ["pvcreate"; "/dev/sda1"];
2121        ["vgcreate"; "VG"; "/dev/sda1"];
2122        ["lvcreate"; "LV1"; "VG"; "50"];
2123        ["lvcreate"; "LV2"; "VG"; "50"];
2124        ["lvremove"; "/dev/VG"];
2125        ["vgs"]], ["VG"])],
2126    "remove an LVM logical volume",
2127    "\
2128 Remove an LVM logical volume C<device>, where C<device> is
2129 the path to the LV, such as C</dev/VG/LV>.
2130
2131 You can also remove all LVs in a volume group by specifying
2132 the VG name, C</dev/VG>.");
2133
2134   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2135    [InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["vgremove"; "VG"];
2142        ["lvs"]], []);
2143     InitEmpty, Always, TestOutputList (
2144       [["part_disk"; "/dev/sda"; "mbr"];
2145        ["pvcreate"; "/dev/sda1"];
2146        ["vgcreate"; "VG"; "/dev/sda1"];
2147        ["lvcreate"; "LV1"; "VG"; "50"];
2148        ["lvcreate"; "LV2"; "VG"; "50"];
2149        ["vgremove"; "VG"];
2150        ["vgs"]], [])],
2151    "remove an LVM volume group",
2152    "\
2153 Remove an LVM volume group C<vgname>, (for example C<VG>).
2154
2155 This also forcibly removes all logical volumes in the volume
2156 group (if any).");
2157
2158   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2159    [InitEmpty, Always, TestOutputListOfDevices (
2160       [["part_disk"; "/dev/sda"; "mbr"];
2161        ["pvcreate"; "/dev/sda1"];
2162        ["vgcreate"; "VG"; "/dev/sda1"];
2163        ["lvcreate"; "LV1"; "VG"; "50"];
2164        ["lvcreate"; "LV2"; "VG"; "50"];
2165        ["vgremove"; "VG"];
2166        ["pvremove"; "/dev/sda1"];
2167        ["lvs"]], []);
2168     InitEmpty, Always, TestOutputListOfDevices (
2169       [["part_disk"; "/dev/sda"; "mbr"];
2170        ["pvcreate"; "/dev/sda1"];
2171        ["vgcreate"; "VG"; "/dev/sda1"];
2172        ["lvcreate"; "LV1"; "VG"; "50"];
2173        ["lvcreate"; "LV2"; "VG"; "50"];
2174        ["vgremove"; "VG"];
2175        ["pvremove"; "/dev/sda1"];
2176        ["vgs"]], []);
2177     InitEmpty, Always, TestOutputListOfDevices (
2178       [["part_disk"; "/dev/sda"; "mbr"];
2179        ["pvcreate"; "/dev/sda1"];
2180        ["vgcreate"; "VG"; "/dev/sda1"];
2181        ["lvcreate"; "LV1"; "VG"; "50"];
2182        ["lvcreate"; "LV2"; "VG"; "50"];
2183        ["vgremove"; "VG"];
2184        ["pvremove"; "/dev/sda1"];
2185        ["pvs"]], [])],
2186    "remove an LVM physical volume",
2187    "\
2188 This wipes a physical volume C<device> so that LVM will no longer
2189 recognise it.
2190
2191 The implementation uses the C<pvremove> command which refuses to
2192 wipe physical volumes that contain any volume groups, so you have
2193 to remove those first.");
2194
2195   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2196    [InitBasicFS, Always, TestOutput (
2197       [["set_e2label"; "/dev/sda1"; "testlabel"];
2198        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2199    "set the ext2/3/4 filesystem label",
2200    "\
2201 This sets the ext2/3/4 filesystem label of the filesystem on
2202 C<device> to C<label>.  Filesystem labels are limited to
2203 16 characters.
2204
2205 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2206 to return the existing label on a filesystem.");
2207
2208   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2209    [],
2210    "get the ext2/3/4 filesystem label",
2211    "\
2212 This returns the ext2/3/4 filesystem label of the filesystem on
2213 C<device>.");
2214
2215   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2216    (let uuid = uuidgen () in
2217     [InitBasicFS, Always, TestOutput (
2218        [["set_e2uuid"; "/dev/sda1"; uuid];
2219         ["get_e2uuid"; "/dev/sda1"]], uuid);
2220      InitBasicFS, Always, TestOutput (
2221        [["set_e2uuid"; "/dev/sda1"; "clear"];
2222         ["get_e2uuid"; "/dev/sda1"]], "");
2223      (* We can't predict what UUIDs will be, so just check the commands run. *)
2224      InitBasicFS, Always, TestRun (
2225        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2226      InitBasicFS, Always, TestRun (
2227        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2228    "set the ext2/3/4 filesystem UUID",
2229    "\
2230 This sets the ext2/3/4 filesystem UUID of the filesystem on
2231 C<device> to C<uuid>.  The format of the UUID and alternatives
2232 such as C<clear>, C<random> and C<time> are described in the
2233 L<tune2fs(8)> manpage.
2234
2235 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2236 to return the existing UUID of a filesystem.");
2237
2238   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2239    [],
2240    "get the ext2/3/4 filesystem UUID",
2241    "\
2242 This returns the ext2/3/4 filesystem UUID of the filesystem on
2243 C<device>.");
2244
2245   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2246    [InitBasicFS, Always, TestOutputInt (
2247       [["umount"; "/dev/sda1"];
2248        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2249     InitBasicFS, Always, TestOutputInt (
2250       [["umount"; "/dev/sda1"];
2251        ["zero"; "/dev/sda1"];
2252        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2253    "run the filesystem checker",
2254    "\
2255 This runs the filesystem checker (fsck) on C<device> which
2256 should have filesystem type C<fstype>.
2257
2258 The returned integer is the status.  See L<fsck(8)> for the
2259 list of status codes from C<fsck>.
2260
2261 Notes:
2262
2263 =over 4
2264
2265 =item *
2266
2267 Multiple status codes can be summed together.
2268
2269 =item *
2270
2271 A non-zero return code can mean \"success\", for example if
2272 errors have been corrected on the filesystem.
2273
2274 =item *
2275
2276 Checking or repairing NTFS volumes is not supported
2277 (by linux-ntfs).
2278
2279 =back
2280
2281 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2282
2283   ("zero", (RErr, [Device "device"]), 85, [],
2284    [InitBasicFS, Always, TestOutput (
2285       [["umount"; "/dev/sda1"];
2286        ["zero"; "/dev/sda1"];
2287        ["file"; "/dev/sda1"]], "data")],
2288    "write zeroes to the device",
2289    "\
2290 This command writes zeroes over the first few blocks of C<device>.
2291
2292 How many blocks are zeroed isn't specified (but it's I<not> enough
2293 to securely wipe the device).  It should be sufficient to remove
2294 any partition tables, filesystem superblocks and so on.
2295
2296 See also: C<guestfs_scrub_device>.");
2297
2298   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2299    (* Test disabled because grub-install incompatible with virtio-blk driver.
2300     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2301     *)
2302    [InitBasicFS, Disabled, TestOutputTrue (
2303       [["grub_install"; "/"; "/dev/sda1"];
2304        ["is_dir"; "/boot"]])],
2305    "install GRUB",
2306    "\
2307 This command installs GRUB (the Grand Unified Bootloader) on
2308 C<device>, with the root directory being C<root>.");
2309
2310   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2311    [InitBasicFS, Always, TestOutput (
2312       [["write_file"; "/old"; "file content"; "0"];
2313        ["cp"; "/old"; "/new"];
2314        ["cat"; "/new"]], "file content");
2315     InitBasicFS, Always, TestOutputTrue (
2316       [["write_file"; "/old"; "file content"; "0"];
2317        ["cp"; "/old"; "/new"];
2318        ["is_file"; "/old"]]);
2319     InitBasicFS, Always, TestOutput (
2320       [["write_file"; "/old"; "file content"; "0"];
2321        ["mkdir"; "/dir"];
2322        ["cp"; "/old"; "/dir/new"];
2323        ["cat"; "/dir/new"]], "file content")],
2324    "copy a file",
2325    "\
2326 This copies a file from C<src> to C<dest> where C<dest> is
2327 either a destination filename or destination directory.");
2328
2329   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2330    [InitBasicFS, Always, TestOutput (
2331       [["mkdir"; "/olddir"];
2332        ["mkdir"; "/newdir"];
2333        ["write_file"; "/olddir/file"; "file content"; "0"];
2334        ["cp_a"; "/olddir"; "/newdir"];
2335        ["cat"; "/newdir/olddir/file"]], "file content")],
2336    "copy a file or directory recursively",
2337    "\
2338 This copies a file or directory from C<src> to C<dest>
2339 recursively using the C<cp -a> command.");
2340
2341   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2342    [InitBasicFS, Always, TestOutput (
2343       [["write_file"; "/old"; "file content"; "0"];
2344        ["mv"; "/old"; "/new"];
2345        ["cat"; "/new"]], "file content");
2346     InitBasicFS, Always, TestOutputFalse (
2347       [["write_file"; "/old"; "file content"; "0"];
2348        ["mv"; "/old"; "/new"];
2349        ["is_file"; "/old"]])],
2350    "move a file",
2351    "\
2352 This moves a file from C<src> to C<dest> where C<dest> is
2353 either a destination filename or destination directory.");
2354
2355   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2356    [InitEmpty, Always, TestRun (
2357       [["drop_caches"; "3"]])],
2358    "drop kernel page cache, dentries and inodes",
2359    "\
2360 This instructs the guest kernel to drop its page cache,
2361 and/or dentries and inode caches.  The parameter C<whattodrop>
2362 tells the kernel what precisely to drop, see
2363 L<http://linux-mm.org/Drop_Caches>
2364
2365 Setting C<whattodrop> to 3 should drop everything.
2366
2367 This automatically calls L<sync(2)> before the operation,
2368 so that the maximum guest memory is freed.");
2369
2370   ("dmesg", (RString "kmsgs", []), 91, [],
2371    [InitEmpty, Always, TestRun (
2372       [["dmesg"]])],
2373    "return kernel messages",
2374    "\
2375 This returns the kernel messages (C<dmesg> output) from
2376 the guest kernel.  This is sometimes useful for extended
2377 debugging of problems.
2378
2379 Another way to get the same information is to enable
2380 verbose messages with C<guestfs_set_verbose> or by setting
2381 the environment variable C<LIBGUESTFS_DEBUG=1> before
2382 running the program.");
2383
2384   ("ping_daemon", (RErr, []), 92, [],
2385    [InitEmpty, Always, TestRun (
2386       [["ping_daemon"]])],
2387    "ping the guest daemon",
2388    "\
2389 This is a test probe into the guestfs daemon running inside
2390 the qemu subprocess.  Calling this function checks that the
2391 daemon responds to the ping message, without affecting the daemon
2392 or attached block device(s) in any other way.");
2393
2394   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2395    [InitBasicFS, Always, TestOutputTrue (
2396       [["write_file"; "/file1"; "contents of a file"; "0"];
2397        ["cp"; "/file1"; "/file2"];
2398        ["equal"; "/file1"; "/file2"]]);
2399     InitBasicFS, Always, TestOutputFalse (
2400       [["write_file"; "/file1"; "contents of a file"; "0"];
2401        ["write_file"; "/file2"; "contents of another file"; "0"];
2402        ["equal"; "/file1"; "/file2"]]);
2403     InitBasicFS, Always, TestLastFail (
2404       [["equal"; "/file1"; "/file2"]])],
2405    "test if two files have equal contents",
2406    "\
2407 This compares the two files C<file1> and C<file2> and returns
2408 true if their content is exactly equal, or false otherwise.
2409
2410 The external L<cmp(1)> program is used for the comparison.");
2411
2412   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2413    [InitISOFS, Always, TestOutputList (
2414       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2415     InitISOFS, Always, TestOutputList (
2416       [["strings"; "/empty"]], [])],
2417    "print the printable strings in a file",
2418    "\
2419 This runs the L<strings(1)> command on a file and returns
2420 the list of printable strings found.");
2421
2422   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2423    [InitISOFS, Always, TestOutputList (
2424       [["strings_e"; "b"; "/known-5"]], []);
2425     InitBasicFS, Disabled, TestOutputList (
2426       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2427        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2428    "print the printable strings in a file",
2429    "\
2430 This is like the C<guestfs_strings> command, but allows you to
2431 specify the encoding.
2432
2433 See the L<strings(1)> manpage for the full list of encodings.
2434
2435 Commonly useful encodings are C<l> (lower case L) which will
2436 show strings inside Windows/x86 files.
2437
2438 The returned strings are transcoded to UTF-8.");
2439
2440   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2441    [InitISOFS, Always, TestOutput (
2442       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2443     (* Test for RHBZ#501888c2 regression which caused large hexdump
2444      * commands to segfault.
2445      *)
2446     InitISOFS, Always, TestRun (
2447       [["hexdump"; "/100krandom"]])],
2448    "dump a file in hexadecimal",
2449    "\
2450 This runs C<hexdump -C> on the given C<path>.  The result is
2451 the human-readable, canonical hex dump of the file.");
2452
2453   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2454    [InitNone, Always, TestOutput (
2455       [["part_disk"; "/dev/sda"; "mbr"];
2456        ["mkfs"; "ext3"; "/dev/sda1"];
2457        ["mount_options"; ""; "/dev/sda1"; "/"];
2458        ["write_file"; "/new"; "test file"; "0"];
2459        ["umount"; "/dev/sda1"];
2460        ["zerofree"; "/dev/sda1"];
2461        ["mount_options"; ""; "/dev/sda1"; "/"];
2462        ["cat"; "/new"]], "test file")],
2463    "zero unused inodes and disk blocks on ext2/3 filesystem",
2464    "\
2465 This runs the I<zerofree> program on C<device>.  This program
2466 claims to zero unused inodes and disk blocks on an ext2/3
2467 filesystem, thus making it possible to compress the filesystem
2468 more effectively.
2469
2470 You should B<not> run this program if the filesystem is
2471 mounted.
2472
2473 It is possible that using this program can damage the filesystem
2474 or data on the filesystem.");
2475
2476   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2477    [],
2478    "resize an LVM physical volume",
2479    "\
2480 This resizes (expands or shrinks) an existing LVM physical
2481 volume to match the new size of the underlying device.");
2482
2483   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2484                        Int "cyls"; Int "heads"; Int "sectors";
2485                        String "line"]), 99, [DangerWillRobinson],
2486    [],
2487    "modify a single partition on a block device",
2488    "\
2489 This runs L<sfdisk(8)> option to modify just the single
2490 partition C<n> (note: C<n> counts from 1).
2491
2492 For other parameters, see C<guestfs_sfdisk>.  You should usually
2493 pass C<0> for the cyls/heads/sectors parameters.
2494
2495 See also: C<guestfs_part_add>");
2496
2497   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2498    [],
2499    "display the partition table",
2500    "\
2501 This displays the partition table on C<device>, in the
2502 human-readable output of the L<sfdisk(8)> command.  It is
2503 not intended to be parsed.
2504
2505 See also: C<guestfs_part_list>");
2506
2507   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2508    [],
2509    "display the kernel geometry",
2510    "\
2511 This displays the kernel's idea of the geometry of C<device>.
2512
2513 The result is in human-readable format, and not designed to
2514 be parsed.");
2515
2516   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2517    [],
2518    "display the disk geometry from the partition table",
2519    "\
2520 This displays the disk geometry of C<device> read from the
2521 partition table.  Especially in the case where the underlying
2522 block device has been resized, this can be different from the
2523 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2524
2525 The result is in human-readable format, and not designed to
2526 be parsed.");
2527
2528   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2529    [],
2530    "activate or deactivate all volume groups",
2531    "\
2532 This command activates or (if C<activate> is false) deactivates
2533 all logical volumes in all volume groups.
2534 If activated, then they are made known to the
2535 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2536 then those devices disappear.
2537
2538 This command is the same as running C<vgchange -a y|n>");
2539
2540   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2541    [],
2542    "activate or deactivate some volume groups",
2543    "\
2544 This command activates or (if C<activate> is false) deactivates
2545 all logical volumes in the listed volume groups C<volgroups>.
2546 If activated, then they are made known to the
2547 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2548 then those devices disappear.
2549
2550 This command is the same as running C<vgchange -a y|n volgroups...>
2551
2552 Note that if C<volgroups> is an empty list then B<all> volume groups
2553 are activated or deactivated.");
2554
2555   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2556    [InitNone, Always, TestOutput (
2557       [["part_disk"; "/dev/sda"; "mbr"];
2558        ["pvcreate"; "/dev/sda1"];
2559        ["vgcreate"; "VG"; "/dev/sda1"];
2560        ["lvcreate"; "LV"; "VG"; "10"];
2561        ["mkfs"; "ext2"; "/dev/VG/LV"];
2562        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2563        ["write_file"; "/new"; "test content"; "0"];
2564        ["umount"; "/"];
2565        ["lvresize"; "/dev/VG/LV"; "20"];
2566        ["e2fsck_f"; "/dev/VG/LV"];
2567        ["resize2fs"; "/dev/VG/LV"];
2568        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2569        ["cat"; "/new"]], "test content")],
2570    "resize an LVM logical volume",
2571    "\
2572 This resizes (expands or shrinks) an existing LVM logical
2573 volume to C<mbytes>.  When reducing, data in the reduced part
2574 is lost.");
2575
2576   ("resize2fs", (RErr, [Device "device"]), 106, [],
2577    [], (* lvresize tests this *)
2578    "resize an ext2/ext3 filesystem",
2579    "\
2580 This resizes an ext2 or ext3 filesystem to match the size of
2581 the underlying device.
2582
2583 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2584 on the C<device> before calling this command.  For unknown reasons
2585 C<resize2fs> sometimes gives an error about this and sometimes not.
2586 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2587 calling this function.");
2588
2589   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2590    [InitBasicFS, Always, TestOutputList (
2591       [["find"; "/"]], ["lost+found"]);
2592     InitBasicFS, Always, TestOutputList (
2593       [["touch"; "/a"];
2594        ["mkdir"; "/b"];
2595        ["touch"; "/b/c"];
2596        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2597     InitBasicFS, Always, TestOutputList (
2598       [["mkdir_p"; "/a/b/c"];
2599        ["touch"; "/a/b/c/d"];
2600        ["find"; "/a/b/"]], ["c"; "c/d"])],
2601    "find all files and directories",
2602    "\
2603 This command lists out all files and directories, recursively,
2604 starting at C<directory>.  It is essentially equivalent to
2605 running the shell command C<find directory -print> but some
2606 post-processing happens on the output, described below.
2607
2608 This returns a list of strings I<without any prefix>.  Thus
2609 if the directory structure was:
2610
2611  /tmp/a
2612  /tmp/b
2613  /tmp/c/d
2614
2615 then the returned list from C<guestfs_find> C</tmp> would be
2616 4 elements:
2617
2618  a
2619  b
2620  c
2621  c/d
2622
2623 If C<directory> is not a directory, then this command returns
2624 an error.
2625
2626 The returned list is sorted.
2627
2628 See also C<guestfs_find0>.");
2629
2630   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2631    [], (* lvresize tests this *)
2632    "check an ext2/ext3 filesystem",
2633    "\
2634 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2635 filesystem checker on C<device>, noninteractively (C<-p>),
2636 even if the filesystem appears to be clean (C<-f>).
2637
2638 This command is only needed because of C<guestfs_resize2fs>
2639 (q.v.).  Normally you should use C<guestfs_fsck>.");
2640
2641   ("sleep", (RErr, [Int "secs"]), 109, [],
2642    [InitNone, Always, TestRun (
2643       [["sleep"; "1"]])],
2644    "sleep for some seconds",
2645    "\
2646 Sleep for C<secs> seconds.");
2647
2648   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2649    [InitNone, Always, TestOutputInt (
2650       [["part_disk"; "/dev/sda"; "mbr"];
2651        ["mkfs"; "ntfs"; "/dev/sda1"];
2652        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2653     InitNone, Always, TestOutputInt (
2654       [["part_disk"; "/dev/sda"; "mbr"];
2655        ["mkfs"; "ext2"; "/dev/sda1"];
2656        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2657    "probe NTFS volume",
2658    "\
2659 This command runs the L<ntfs-3g.probe(8)> command which probes
2660 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2661 be mounted read-write, and some cannot be mounted at all).
2662
2663 C<rw> is a boolean flag.  Set it to true if you want to test
2664 if the volume can be mounted read-write.  Set it to false if
2665 you want to test if the volume can be mounted read-only.
2666
2667 The return value is an integer which C<0> if the operation
2668 would succeed, or some non-zero value documented in the
2669 L<ntfs-3g.probe(8)> manual page.");
2670
2671   ("sh", (RString "output", [String "command"]), 111, [],
2672    [], (* XXX needs tests *)
2673    "run a command via the shell",
2674    "\
2675 This call runs a command from the guest filesystem via the
2676 guest's C</bin/sh>.
2677
2678 This is like C<guestfs_command>, but passes the command to:
2679
2680  /bin/sh -c \"command\"
2681
2682 Depending on the guest's shell, this usually results in
2683 wildcards being expanded, shell expressions being interpolated
2684 and so on.
2685
2686 All the provisos about C<guestfs_command> apply to this call.");
2687
2688   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2689    [], (* XXX needs tests *)
2690    "run a command via the shell returning lines",
2691    "\
2692 This is the same as C<guestfs_sh>, but splits the result
2693 into a list of lines.
2694
2695 See also: C<guestfs_command_lines>");
2696
2697   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2698    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2699     * code in stubs.c, since all valid glob patterns must start with "/".
2700     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2701     *)
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/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2707     InitBasicFS, Always, TestOutputList (
2708       [["mkdir_p"; "/a/b/c"];
2709        ["touch"; "/a/b/c/d"];
2710        ["touch"; "/a/b/c/e"];
2711        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2712     InitBasicFS, Always, TestOutputList (
2713       [["mkdir_p"; "/a/b/c"];
2714        ["touch"; "/a/b/c/d"];
2715        ["touch"; "/a/b/c/e"];
2716        ["glob_expand"; "/a/*/x/*"]], [])],
2717    "expand a wildcard path",
2718    "\
2719 This command searches for all the pathnames matching
2720 C<pattern> according to the wildcard expansion rules
2721 used by the shell.
2722
2723 If no paths match, then this returns an empty list
2724 (note: not an error).
2725
2726 It is just a wrapper around the C L<glob(3)> function
2727 with flags C<GLOB_MARK|GLOB_BRACE>.
2728 See that manual page for more details.");
2729
2730   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2731    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2732       [["scrub_device"; "/dev/sdc"]])],
2733    "scrub (securely wipe) a device",
2734    "\
2735 This command writes patterns over C<device> to make data retrieval
2736 more difficult.
2737
2738 It is an interface to the L<scrub(1)> program.  See that
2739 manual page for more details.");
2740
2741   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2742    [InitBasicFS, Always, TestRun (
2743       [["write_file"; "/file"; "content"; "0"];
2744        ["scrub_file"; "/file"]])],
2745    "scrub (securely wipe) a file",
2746    "\
2747 This command writes patterns over a file to make data retrieval
2748 more difficult.
2749
2750 The file is I<removed> after scrubbing.
2751
2752 It is an interface to the L<scrub(1)> program.  See that
2753 manual page for more details.");
2754
2755   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2756    [], (* XXX needs testing *)
2757    "scrub (securely wipe) free space",
2758    "\
2759 This command creates the directory C<dir> and then fills it
2760 with files until the filesystem is full, and scrubs the files
2761 as for C<guestfs_scrub_file>, and deletes them.
2762 The intention is to scrub any free space on the partition
2763 containing C<dir>.
2764
2765 It is an interface to the L<scrub(1)> program.  See that
2766 manual page for more details.");
2767
2768   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2769    [InitBasicFS, Always, TestRun (
2770       [["mkdir"; "/tmp"];
2771        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2772    "create a temporary directory",
2773    "\
2774 This command creates a temporary directory.  The
2775 C<template> parameter should be a full pathname for the
2776 temporary directory name with the final six characters being
2777 \"XXXXXX\".
2778
2779 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2780 the second one being suitable for Windows filesystems.
2781
2782 The name of the temporary directory that was created
2783 is returned.
2784
2785 The temporary directory is created with mode 0700
2786 and is owned by root.
2787
2788 The caller is responsible for deleting the temporary
2789 directory and its contents after use.
2790
2791 See also: L<mkdtemp(3)>");
2792
2793   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2794    [InitISOFS, Always, TestOutputInt (
2795       [["wc_l"; "/10klines"]], 10000)],
2796    "count lines in a file",
2797    "\
2798 This command counts the lines in a file, using the
2799 C<wc -l> external command.");
2800
2801   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2802    [InitISOFS, Always, TestOutputInt (
2803       [["wc_w"; "/10klines"]], 10000)],
2804    "count words in a file",
2805    "\
2806 This command counts the words in a file, using the
2807 C<wc -w> external command.");
2808
2809   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2810    [InitISOFS, Always, TestOutputInt (
2811       [["wc_c"; "/100kallspaces"]], 102400)],
2812    "count characters in a file",
2813    "\
2814 This command counts the characters in a file, using the
2815 C<wc -c> external command.");
2816
2817   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2818    [InitISOFS, Always, TestOutputList (
2819       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2820    "return first 10 lines of a file",
2821    "\
2822 This command returns up to the first 10 lines of a file as
2823 a list of strings.");
2824
2825   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2826    [InitISOFS, Always, TestOutputList (
2827       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2828     InitISOFS, Always, TestOutputList (
2829       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2830     InitISOFS, Always, TestOutputList (
2831       [["head_n"; "0"; "/10klines"]], [])],
2832    "return first N lines of a file",
2833    "\
2834 If the parameter C<nrlines> is a positive number, this returns the first
2835 C<nrlines> lines of the file C<path>.
2836
2837 If the parameter C<nrlines> is a negative number, this returns lines
2838 from the file C<path>, excluding the last C<nrlines> lines.
2839
2840 If the parameter C<nrlines> is zero, this returns an empty list.");
2841
2842   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2843    [InitISOFS, Always, TestOutputList (
2844       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2845    "return last 10 lines of a file",
2846    "\
2847 This command returns up to the last 10 lines of a file as
2848 a list of strings.");
2849
2850   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2851    [InitISOFS, Always, TestOutputList (
2852       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2853     InitISOFS, Always, TestOutputList (
2854       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2855     InitISOFS, Always, TestOutputList (
2856       [["tail_n"; "0"; "/10klines"]], [])],
2857    "return last N lines of a file",
2858    "\
2859 If the parameter C<nrlines> is a positive number, this returns the last
2860 C<nrlines> lines of the file C<path>.
2861
2862 If the parameter C<nrlines> is a negative number, this returns lines
2863 from the file C<path>, starting with the C<-nrlines>th line.
2864
2865 If the parameter C<nrlines> is zero, this returns an empty list.");
2866
2867   ("df", (RString "output", []), 125, [],
2868    [], (* XXX Tricky to test because it depends on the exact format
2869         * of the 'df' command and other imponderables.
2870         *)
2871    "report file system disk space usage",
2872    "\
2873 This command runs the C<df> command to report disk space used.
2874
2875 This command is mostly useful for interactive sessions.  It
2876 is I<not> intended that you try to parse the output string.
2877 Use C<statvfs> from programs.");
2878
2879   ("df_h", (RString "output", []), 126, [],
2880    [], (* XXX Tricky to test because it depends on the exact format
2881         * of the 'df' command and other imponderables.
2882         *)
2883    "report file system disk space usage (human readable)",
2884    "\
2885 This command runs the C<df -h> command to report disk space used
2886 in human-readable format.
2887
2888 This command is mostly useful for interactive sessions.  It
2889 is I<not> intended that you try to parse the output string.
2890 Use C<statvfs> from programs.");
2891
2892   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2893    [InitISOFS, Always, TestOutputInt (
2894       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2895    "estimate file space usage",
2896    "\
2897 This command runs the C<du -s> command to estimate file space
2898 usage for C<path>.
2899
2900 C<path> can be a file or a directory.  If C<path> is a directory
2901 then the estimate includes the contents of the directory and all
2902 subdirectories (recursively).
2903
2904 The result is the estimated size in I<kilobytes>
2905 (ie. units of 1024 bytes).");
2906
2907   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2908    [InitISOFS, Always, TestOutputList (
2909       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2910    "list files in an initrd",
2911    "\
2912 This command lists out files contained in an initrd.
2913
2914 The files are listed without any initial C</> character.  The
2915 files are listed in the order they appear (not necessarily
2916 alphabetical).  Directory names are listed as separate items.
2917
2918 Old Linux kernels (2.4 and earlier) used a compressed ext2
2919 filesystem as initrd.  We I<only> support the newer initramfs
2920 format (compressed cpio files).");
2921
2922   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2923    [],
2924    "mount a file using the loop device",
2925    "\
2926 This command lets you mount C<file> (a filesystem image
2927 in a file) on a mount point.  It is entirely equivalent to
2928 the command C<mount -o loop file mountpoint>.");
2929
2930   ("mkswap", (RErr, [Device "device"]), 130, [],
2931    [InitEmpty, Always, TestRun (
2932       [["part_disk"; "/dev/sda"; "mbr"];
2933        ["mkswap"; "/dev/sda1"]])],
2934    "create a swap partition",
2935    "\
2936 Create a swap partition on C<device>.");
2937
2938   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2939    [InitEmpty, Always, TestRun (
2940       [["part_disk"; "/dev/sda"; "mbr"];
2941        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2942    "create a swap partition with a label",
2943    "\
2944 Create a swap partition on C<device> with label C<label>.
2945
2946 Note that you cannot attach a swap label to a block device
2947 (eg. C</dev/sda>), just to a partition.  This appears to be
2948 a limitation of the kernel or swap tools.");
2949
2950   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2951    (let uuid = uuidgen () in
2952     [InitEmpty, Always, TestRun (
2953        [["part_disk"; "/dev/sda"; "mbr"];
2954         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2955    "create a swap partition with an explicit UUID",
2956    "\
2957 Create a swap partition on C<device> with UUID C<uuid>.");
2958
2959   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2960    [InitBasicFS, Always, TestOutputStruct (
2961       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2962        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2963        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2964     InitBasicFS, Always, TestOutputStruct (
2965       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2966        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2967    "make block, character or FIFO devices",
2968    "\
2969 This call creates block or character special devices, or
2970 named pipes (FIFOs).
2971
2972 The C<mode> parameter should be the mode, using the standard
2973 constants.  C<devmajor> and C<devminor> are the
2974 device major and minor numbers, only used when creating block
2975 and character special devices.");
2976
2977   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2978    [InitBasicFS, Always, TestOutputStruct (
2979       [["mkfifo"; "0o777"; "/node"];
2980        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2981    "make FIFO (named pipe)",
2982    "\
2983 This call creates a FIFO (named pipe) called C<path> with
2984 mode C<mode>.  It is just a convenient wrapper around
2985 C<guestfs_mknod>.");
2986
2987   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2988    [InitBasicFS, Always, TestOutputStruct (
2989       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2990        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2991    "make block device node",
2992    "\
2993 This call creates a block 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   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2998    [InitBasicFS, Always, TestOutputStruct (
2999       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3000        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3001    "make char device node",
3002    "\
3003 This call creates a char device node called C<path> with
3004 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3005 It is just a convenient wrapper around C<guestfs_mknod>.");
3006
3007   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3008    [], (* XXX umask is one of those stateful things that we should
3009         * reset between each test.
3010         *)
3011    "set file mode creation mask (umask)",
3012    "\
3013 This function sets the mask used for creating new files and
3014 device nodes to C<mask & 0777>.
3015
3016 Typical umask values would be C<022> which creates new files
3017 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3018 C<002> which creates new files with permissions like
3019 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3020
3021 The default umask is C<022>.  This is important because it
3022 means that directories and device nodes will be created with
3023 C<0644> or C<0755> mode even if you specify C<0777>.
3024
3025 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3026
3027 This call returns the previous umask.");
3028
3029   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3030    [],
3031    "read directories entries",
3032    "\
3033 This returns the list of directory entries in directory C<dir>.
3034
3035 All entries in the directory are returned, including C<.> and
3036 C<..>.  The entries are I<not> sorted, but returned in the same
3037 order as the underlying filesystem.
3038
3039 Also this call returns basic file type information about each
3040 file.  The C<ftyp> field will contain one of the following characters:
3041
3042 =over 4
3043
3044 =item 'b'
3045
3046 Block special
3047
3048 =item 'c'
3049
3050 Char special
3051
3052 =item 'd'
3053
3054 Directory
3055
3056 =item 'f'
3057
3058 FIFO (named pipe)
3059
3060 =item 'l'
3061
3062 Symbolic link
3063
3064 =item 'r'
3065
3066 Regular file
3067
3068 =item 's'
3069
3070 Socket
3071
3072 =item 'u'
3073
3074 Unknown file type
3075
3076 =item '?'
3077
3078 The L<readdir(3)> returned a C<d_type> field with an
3079 unexpected value
3080
3081 =back
3082
3083 This function is primarily intended for use by programs.  To
3084 get a simple list of names, use C<guestfs_ls>.  To get a printable
3085 directory for human consumption, use C<guestfs_ll>.");
3086
3087   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3088    [],
3089    "create partitions on a block device",
3090    "\
3091 This is a simplified interface to the C<guestfs_sfdisk>
3092 command, where partition sizes are specified in megabytes
3093 only (rounded to the nearest cylinder) and you don't need
3094 to specify the cyls, heads and sectors parameters which
3095 were rarely if ever used anyway.
3096
3097 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3098 and C<guestfs_part_disk>");
3099
3100   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3101    [],
3102    "determine file type inside a compressed file",
3103    "\
3104 This command runs C<file> after first decompressing C<path>
3105 using C<method>.
3106
3107 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3108
3109 Since 1.0.63, use C<guestfs_file> instead which can now
3110 process compressed files.");
3111
3112   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3113    [],
3114    "list extended attributes of a file or directory",
3115    "\
3116 This call lists the extended attributes of the file or directory
3117 C<path>.
3118
3119 At the system call level, this is a combination of the
3120 L<listxattr(2)> and L<getxattr(2)> calls.
3121
3122 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3123
3124   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3125    [],
3126    "list extended attributes of a file or directory",
3127    "\
3128 This is the same as C<guestfs_getxattrs>, but if C<path>
3129 is a symbolic link, then it returns the extended attributes
3130 of the link itself.");
3131
3132   ("setxattr", (RErr, [String "xattr";
3133                        String "val"; Int "vallen"; (* will be BufferIn *)
3134                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3135    [],
3136    "set extended attribute of a file or directory",
3137    "\
3138 This call sets the extended attribute named C<xattr>
3139 of the file C<path> to the value C<val> (of length C<vallen>).
3140 The value is arbitrary 8 bit data.
3141
3142 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3143
3144   ("lsetxattr", (RErr, [String "xattr";
3145                         String "val"; Int "vallen"; (* will be BufferIn *)
3146                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3147    [],
3148    "set extended attribute of a file or directory",
3149    "\
3150 This is the same as C<guestfs_setxattr>, but if C<path>
3151 is a symbolic link, then it sets an extended attribute
3152 of the link itself.");
3153
3154   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3155    [],
3156    "remove extended attribute of a file or directory",
3157    "\
3158 This call removes the extended attribute named C<xattr>
3159 of the file C<path>.
3160
3161 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3162
3163   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3164    [],
3165    "remove extended attribute of a file or directory",
3166    "\
3167 This is the same as C<guestfs_removexattr>, but if C<path>
3168 is a symbolic link, then it removes an extended attribute
3169 of the link itself.");
3170
3171   ("mountpoints", (RHashtable "mps", []), 147, [],
3172    [],
3173    "show mountpoints",
3174    "\
3175 This call is similar to C<guestfs_mounts>.  That call returns
3176 a list of devices.  This one returns a hash table (map) of
3177 device name to directory where the device is mounted.");
3178
3179   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3180    (* This is a special case: while you would expect a parameter
3181     * of type "Pathname", that doesn't work, because it implies
3182     * NEED_ROOT in the generated calling code in stubs.c, and
3183     * this function cannot use NEED_ROOT.
3184     *)
3185    [],
3186    "create a mountpoint",
3187    "\
3188 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3189 specialized calls that can be used to create extra mountpoints
3190 before mounting the first filesystem.
3191
3192 These calls are I<only> necessary in some very limited circumstances,
3193 mainly the case where you want to mount a mix of unrelated and/or
3194 read-only filesystems together.
3195
3196 For example, live CDs often contain a \"Russian doll\" nest of
3197 filesystems, an ISO outer layer, with a squashfs image inside, with
3198 an ext2/3 image inside that.  You can unpack this as follows
3199 in guestfish:
3200
3201  add-ro Fedora-11-i686-Live.iso
3202  run
3203  mkmountpoint /cd
3204  mkmountpoint /squash
3205  mkmountpoint /ext3
3206  mount /dev/sda /cd
3207  mount-loop /cd/LiveOS/squashfs.img /squash
3208  mount-loop /squash/LiveOS/ext3fs.img /ext3
3209
3210 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3211
3212   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3213    [],
3214    "remove a mountpoint",
3215    "\
3216 This calls removes a mountpoint that was previously created
3217 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3218 for full details.");
3219
3220   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3221    [InitISOFS, Always, TestOutputBuffer (
3222       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3223    "read a file",
3224    "\
3225 This calls returns the contents of the file C<path> as a
3226 buffer.
3227
3228 Unlike C<guestfs_cat>, this function can correctly
3229 handle files that contain embedded ASCII NUL characters.
3230 However unlike C<guestfs_download>, this function is limited
3231 in the total size of file that can be handled.");
3232
3233   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3234    [InitISOFS, Always, TestOutputList (
3235       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3236     InitISOFS, Always, TestOutputList (
3237       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3238    "return lines matching a pattern",
3239    "\
3240 This calls the external C<grep> program and returns the
3241 matching lines.");
3242
3243   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3244    [InitISOFS, Always, TestOutputList (
3245       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3246    "return lines matching a pattern",
3247    "\
3248 This calls the external C<egrep> program and returns the
3249 matching lines.");
3250
3251   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3252    [InitISOFS, Always, TestOutputList (
3253       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3254    "return lines matching a pattern",
3255    "\
3256 This calls the external C<fgrep> program and returns the
3257 matching lines.");
3258
3259   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3260    [InitISOFS, Always, TestOutputList (
3261       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3262    "return lines matching a pattern",
3263    "\
3264 This calls the external C<grep -i> program and returns the
3265 matching lines.");
3266
3267   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3268    [InitISOFS, Always, TestOutputList (
3269       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3270    "return lines matching a pattern",
3271    "\
3272 This calls the external C<egrep -i> program and returns the
3273 matching lines.");
3274
3275   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3276    [InitISOFS, Always, TestOutputList (
3277       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3278    "return lines matching a pattern",
3279    "\
3280 This calls the external C<fgrep -i> program and returns the
3281 matching lines.");
3282
3283   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3284    [InitISOFS, Always, TestOutputList (
3285       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3286    "return lines matching a pattern",
3287    "\
3288 This calls the external C<zgrep> program and returns the
3289 matching lines.");
3290
3291   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3292    [InitISOFS, Always, TestOutputList (
3293       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3294    "return lines matching a pattern",
3295    "\
3296 This calls the external C<zegrep> program and returns the
3297 matching lines.");
3298
3299   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3300    [InitISOFS, Always, TestOutputList (
3301       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3302    "return lines matching a pattern",
3303    "\
3304 This calls the external C<zfgrep> program and returns the
3305 matching lines.");
3306
3307   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3308    [InitISOFS, Always, TestOutputList (
3309       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3310    "return lines matching a pattern",
3311    "\
3312 This calls the external C<zgrep -i> program and returns the
3313 matching lines.");
3314
3315   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3316    [InitISOFS, Always, TestOutputList (
3317       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3318    "return lines matching a pattern",
3319    "\
3320 This calls the external C<zegrep -i> program and returns the
3321 matching lines.");
3322
3323   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3326    "return lines matching a pattern",
3327    "\
3328 This calls the external C<zfgrep -i> program and returns the
3329 matching lines.");
3330
3331   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3332    [InitISOFS, Always, TestOutput (
3333       [["realpath"; "/../directory"]], "/directory")],
3334    "canonicalized absolute pathname",
3335    "\
3336 Return the canonicalized absolute pathname of C<path>.  The
3337 returned path has no C<.>, C<..> or symbolic link path elements.");
3338
3339   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3340    [InitBasicFS, Always, TestOutputStruct (
3341       [["touch"; "/a"];
3342        ["ln"; "/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> command.");
3347
3348   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3349    [InitBasicFS, Always, TestOutputStruct (
3350       [["touch"; "/a"];
3351        ["touch"; "/b"];
3352        ["ln_f"; "/a"; "/b"];
3353        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3354    "create a hard link",
3355    "\
3356 This command creates a hard link using the C<ln -f> command.
3357 The C<-f> option removes the link (C<linkname>) if it exists already.");
3358
3359   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3360    [InitBasicFS, Always, TestOutputStruct (
3361       [["touch"; "/a"];
3362        ["ln_s"; "a"; "/b"];
3363        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3364    "create a symbolic link",
3365    "\
3366 This command creates a symbolic link using the C<ln -s> command.");
3367
3368   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3369    [InitBasicFS, Always, TestOutput (
3370       [["mkdir_p"; "/a/b"];
3371        ["touch"; "/a/b/c"];
3372        ["ln_sf"; "../d"; "/a/b/c"];
3373        ["readlink"; "/a/b/c"]], "../d")],
3374    "create a symbolic link",
3375    "\
3376 This command creates a symbolic link using the C<ln -sf> command,
3377 The C<-f> option removes the link (C<linkname>) if it exists already.");
3378
3379   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3380    [] (* XXX tested above *),
3381    "read the target of a symbolic link",
3382    "\
3383 This command reads the target of a symbolic link.");
3384
3385   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3386    [InitBasicFS, Always, TestOutputStruct (
3387       [["fallocate"; "/a"; "1000000"];
3388        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3389    "preallocate a file in the guest filesystem",
3390    "\
3391 This command preallocates a file (containing zero bytes) named
3392 C<path> of size C<len> bytes.  If the file exists already, it
3393 is overwritten.
3394
3395 Do not confuse this with the guestfish-specific
3396 C<alloc> command which allocates a file in the host and
3397 attaches it as a device.");
3398
3399   ("swapon_device", (RErr, [Device "device"]), 170, [],
3400    [InitPartition, Always, TestRun (
3401       [["mkswap"; "/dev/sda1"];
3402        ["swapon_device"; "/dev/sda1"];
3403        ["swapoff_device"; "/dev/sda1"]])],
3404    "enable swap on device",
3405    "\
3406 This command enables the libguestfs appliance to use the
3407 swap device or partition named C<device>.  The increased
3408 memory is made available for all commands, for example
3409 those run using C<guestfs_command> or C<guestfs_sh>.
3410
3411 Note that you should not swap to existing guest swap
3412 partitions unless you know what you are doing.  They may
3413 contain hibernation information, or other information that
3414 the guest doesn't want you to trash.  You also risk leaking
3415 information about the host to the guest this way.  Instead,
3416 attach a new host device to the guest and swap on that.");
3417
3418   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3419    [], (* XXX tested by swapon_device *)
3420    "disable swap on device",
3421    "\
3422 This command disables the libguestfs appliance swap
3423 device or partition named C<device>.
3424 See C<guestfs_swapon_device>.");
3425
3426   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3427    [InitBasicFS, Always, TestRun (
3428       [["fallocate"; "/swap"; "8388608"];
3429        ["mkswap_file"; "/swap"];
3430        ["swapon_file"; "/swap"];
3431        ["swapoff_file"; "/swap"]])],
3432    "enable swap on file",
3433    "\
3434 This command enables swap to a file.
3435 See C<guestfs_swapon_device> for other notes.");
3436
3437   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3438    [], (* XXX tested by swapon_file *)
3439    "disable swap on file",
3440    "\
3441 This command disables the libguestfs appliance swap on file.");
3442
3443   ("swapon_label", (RErr, [String "label"]), 174, [],
3444    [InitEmpty, Always, TestRun (
3445       [["part_disk"; "/dev/sdb"; "mbr"];
3446        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3447        ["swapon_label"; "swapit"];
3448        ["swapoff_label"; "swapit"];
3449        ["zero"; "/dev/sdb"];
3450        ["blockdev_rereadpt"; "/dev/sdb"]])],
3451    "enable swap on labeled swap partition",
3452    "\
3453 This command enables swap to a labeled swap partition.
3454 See C<guestfs_swapon_device> for other notes.");
3455
3456   ("swapoff_label", (RErr, [String "label"]), 175, [],
3457    [], (* XXX tested by swapon_label *)
3458    "disable swap on labeled swap partition",
3459    "\
3460 This command disables the libguestfs appliance swap on
3461 labeled swap partition.");
3462
3463   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3464    (let uuid = uuidgen () in
3465     [InitEmpty, Always, TestRun (
3466        [["mkswap_U"; uuid; "/dev/sdb"];
3467         ["swapon_uuid"; uuid];
3468         ["swapoff_uuid"; uuid]])]),
3469    "enable swap on swap partition by UUID",
3470    "\
3471 This command enables swap to a swap partition with the given UUID.
3472 See C<guestfs_swapon_device> for other notes.");
3473
3474   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3475    [], (* XXX tested by swapon_uuid *)
3476    "disable swap on swap partition by UUID",
3477    "\
3478 This command disables the libguestfs appliance swap partition
3479 with the given UUID.");
3480
3481   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3482    [InitBasicFS, Always, TestRun (
3483       [["fallocate"; "/swap"; "8388608"];
3484        ["mkswap_file"; "/swap"]])],
3485    "create a swap file",
3486    "\
3487 Create a swap file.
3488
3489 This command just writes a swap file signature to an existing
3490 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3491
3492   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3493    [InitISOFS, Always, TestRun (
3494       [["inotify_init"; "0"]])],
3495    "create an inotify handle",
3496    "\
3497 This command creates a new inotify handle.
3498 The inotify subsystem can be used to notify events which happen to
3499 objects in the guest filesystem.
3500
3501 C<maxevents> is the maximum number of events which will be
3502 queued up between calls to C<guestfs_inotify_read> or
3503 C<guestfs_inotify_files>.
3504 If this is passed as C<0>, then the kernel (or previously set)
3505 default is used.  For Linux 2.6.29 the default was 16384 events.
3506 Beyond this limit, the kernel throws away events, but records
3507 the fact that it threw them away by setting a flag
3508 C<IN_Q_OVERFLOW> in the returned structure list (see
3509 C<guestfs_inotify_read>).
3510
3511 Before any events are generated, you have to add some
3512 watches to the internal watch list.  See:
3513 C<guestfs_inotify_add_watch>,
3514 C<guestfs_inotify_rm_watch> and
3515 C<guestfs_inotify_watch_all>.
3516
3517 Queued up events should be read periodically by calling
3518 C<guestfs_inotify_read>
3519 (or C<guestfs_inotify_files> which is just a helpful
3520 wrapper around C<guestfs_inotify_read>).  If you don't
3521 read the events out often enough then you risk the internal
3522 queue overflowing.
3523
3524 The handle should be closed after use by calling
3525 C<guestfs_inotify_close>.  This also removes any
3526 watches automatically.
3527
3528 See also L<inotify(7)> for an overview of the inotify interface
3529 as exposed by the Linux kernel, which is roughly what we expose
3530 via libguestfs.  Note that there is one global inotify handle
3531 per libguestfs instance.");
3532
3533   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3534    [InitBasicFS, Always, TestOutputList (
3535       [["inotify_init"; "0"];
3536        ["inotify_add_watch"; "/"; "1073741823"];
3537        ["touch"; "/a"];
3538        ["touch"; "/b"];
3539        ["inotify_files"]], ["a"; "b"])],
3540    "add an inotify watch",
3541    "\
3542 Watch C<path> for the events listed in C<mask>.
3543
3544 Note that if C<path> is a directory then events within that
3545 directory are watched, but this does I<not> happen recursively
3546 (in subdirectories).
3547
3548 Note for non-C or non-Linux callers: the inotify events are
3549 defined by the Linux kernel ABI and are listed in
3550 C</usr/include/sys/inotify.h>.");
3551
3552   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3553    [],
3554    "remove an inotify watch",
3555    "\
3556 Remove a previously defined inotify watch.
3557 See C<guestfs_inotify_add_watch>.");
3558
3559   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3560    [],
3561    "return list of inotify events",
3562    "\
3563 Return the complete queue of events that have happened
3564 since the previous read call.
3565
3566 If no events have happened, this returns an empty list.
3567
3568 I<Note>: In order to make sure that all events have been
3569 read, you must call this function repeatedly until it
3570 returns an empty list.  The reason is that the call will
3571 read events up to the maximum appliance-to-host message
3572 size and leave remaining events in the queue.");
3573
3574   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3575    [],
3576    "return list of watched files that had events",
3577    "\
3578 This function is a helpful wrapper around C<guestfs_inotify_read>
3579 which just returns a list of pathnames of objects that were
3580 touched.  The returned pathnames are sorted and deduplicated.");
3581
3582   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3583    [],
3584    "close the inotify handle",
3585    "\
3586 This closes the inotify handle which was previously
3587 opened by inotify_init.  It removes all watches, throws
3588 away any pending events, and deallocates all resources.");
3589
3590   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3591    [],
3592    "set SELinux security context",
3593    "\
3594 This sets the SELinux security context of the daemon
3595 to the string C<context>.
3596
3597 See the documentation about SELINUX in L<guestfs(3)>.");
3598
3599   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3600    [],
3601    "get SELinux security context",
3602    "\
3603 This gets the SELinux security context of the daemon.
3604
3605 See the documentation about SELINUX in L<guestfs(3)>,
3606 and C<guestfs_setcon>");
3607
3608   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3609    [InitEmpty, Always, TestOutput (
3610       [["part_disk"; "/dev/sda"; "mbr"];
3611        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3612        ["mount_options"; ""; "/dev/sda1"; "/"];
3613        ["write_file"; "/new"; "new file contents"; "0"];
3614        ["cat"; "/new"]], "new file contents")],
3615    "make a filesystem with block size",
3616    "\
3617 This call is similar to C<guestfs_mkfs>, but it allows you to
3618 control the block size of the resulting filesystem.  Supported
3619 block sizes depend on the filesystem type, but typically they
3620 are C<1024>, C<2048> or C<4096> only.");
3621
3622   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3623    [InitEmpty, Always, TestOutput (
3624       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3625        ["mke2journal"; "4096"; "/dev/sda1"];
3626        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3627        ["mount_options"; ""; "/dev/sda2"; "/"];
3628        ["write_file"; "/new"; "new file contents"; "0"];
3629        ["cat"; "/new"]], "new file contents")],
3630    "make ext2/3/4 external journal",
3631    "\
3632 This creates an ext2 external journal on C<device>.  It is equivalent
3633 to the command:
3634
3635  mke2fs -O journal_dev -b blocksize device");
3636
3637   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3638    [InitEmpty, Always, TestOutput (
3639       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3640        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3641        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3642        ["mount_options"; ""; "/dev/sda2"; "/"];
3643        ["write_file"; "/new"; "new file contents"; "0"];
3644        ["cat"; "/new"]], "new file contents")],
3645    "make ext2/3/4 external journal with label",
3646    "\
3647 This creates an ext2 external journal on C<device> with label C<label>.");
3648
3649   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3650    (let uuid = uuidgen () in
3651     [InitEmpty, Always, TestOutput (
3652        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3653         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3654         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3655         ["mount_options"; ""; "/dev/sda2"; "/"];
3656         ["write_file"; "/new"; "new file contents"; "0"];
3657         ["cat"; "/new"]], "new file contents")]),
3658    "make ext2/3/4 external journal with UUID",
3659    "\
3660 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3661
3662   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3663    [],
3664    "make ext2/3/4 filesystem with external journal",
3665    "\
3666 This creates an ext2/3/4 filesystem on C<device> with
3667 an external journal on C<journal>.  It is equivalent
3668 to the command:
3669
3670  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3671
3672 See also C<guestfs_mke2journal>.");
3673
3674   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3675    [],
3676    "make ext2/3/4 filesystem with external journal",
3677    "\
3678 This creates an ext2/3/4 filesystem on C<device> with
3679 an external journal on the journal labeled C<label>.
3680
3681 See also C<guestfs_mke2journal_L>.");
3682
3683   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3684    [],
3685    "make ext2/3/4 filesystem with external journal",
3686    "\
3687 This creates an ext2/3/4 filesystem on C<device> with
3688 an external journal on the journal with UUID C<uuid>.
3689
3690 See also C<guestfs_mke2journal_U>.");
3691
3692   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3693    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3694    "load a kernel module",
3695    "\
3696 This loads a kernel module in the appliance.
3697
3698 The kernel module must have been whitelisted when libguestfs
3699 was built (see C<appliance/kmod.whitelist.in> in the source).");
3700
3701   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3702    [InitNone, Always, TestOutput (
3703       [["echo_daemon"; "This is a test"]], "This is a test"
3704     )],
3705    "echo arguments back to the client",
3706    "\
3707 This command concatenate the list of C<words> passed with single spaces between
3708 them and returns the resulting string.
3709
3710 You can use this command to test the connection through to the daemon.
3711
3712 See also C<guestfs_ping_daemon>.");
3713
3714   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3715    [], (* There is a regression test for this. *)
3716    "find all files and directories, returning NUL-separated list",
3717    "\
3718 This command lists out all files and directories, recursively,
3719 starting at C<directory>, placing the resulting list in the
3720 external file called C<files>.
3721
3722 This command works the same way as C<guestfs_find> with the
3723 following exceptions:
3724
3725 =over 4
3726
3727 =item *
3728
3729 The resulting list is written to an external file.
3730
3731 =item *
3732
3733 Items (filenames) in the result are separated
3734 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3735
3736 =item *
3737
3738 This command is not limited in the number of names that it
3739 can return.
3740
3741 =item *
3742
3743 The result list is not sorted.
3744
3745 =back");
3746
3747   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3748    [InitISOFS, Always, TestOutput (
3749       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3750     InitISOFS, Always, TestOutput (
3751       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3752     InitISOFS, Always, TestOutput (
3753       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3754     InitISOFS, Always, TestLastFail (
3755       [["case_sensitive_path"; "/Known-1/"]]);
3756     InitBasicFS, Always, TestOutput (
3757       [["mkdir"; "/a"];
3758        ["mkdir"; "/a/bbb"];
3759        ["touch"; "/a/bbb/c"];
3760        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3761     InitBasicFS, Always, TestOutput (
3762       [["mkdir"; "/a"];
3763        ["mkdir"; "/a/bbb"];
3764        ["touch"; "/a/bbb/c"];
3765        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3766     InitBasicFS, Always, TestLastFail (
3767       [["mkdir"; "/a"];
3768        ["mkdir"; "/a/bbb"];
3769        ["touch"; "/a/bbb/c"];
3770        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3771    "return true path on case-insensitive filesystem",
3772    "\
3773 This can be used to resolve case insensitive paths on
3774 a filesystem which is case sensitive.  The use case is
3775 to resolve paths which you have read from Windows configuration
3776 files or the Windows Registry, to the true path.
3777
3778 The command handles a peculiarity of the Linux ntfs-3g
3779 filesystem driver (and probably others), which is that although
3780 the underlying filesystem is case-insensitive, the driver
3781 exports the filesystem to Linux as case-sensitive.
3782
3783 One consequence of this is that special directories such
3784 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3785 (or other things) depending on the precise details of how
3786 they were created.  In Windows itself this would not be
3787 a problem.
3788
3789 Bug or feature?  You decide:
3790 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3791
3792 This function resolves the true case of each element in the
3793 path and returns the case-sensitive path.
3794
3795 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3796 might return C<\"/WINDOWS/system32\"> (the exact return value
3797 would depend on details of how the directories were originally
3798 created under Windows).
3799
3800 I<Note>:
3801 This function does not handle drive names, backslashes etc.
3802
3803 See also C<guestfs_realpath>.");
3804
3805   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3806    [InitBasicFS, Always, TestOutput (
3807       [["vfs_type"; "/dev/sda1"]], "ext2")],
3808    "get the Linux VFS type corresponding to a mounted device",
3809    "\
3810 This command gets the block device type corresponding to
3811 a mounted device called C<device>.
3812
3813 Usually the result is the name of the Linux VFS module that
3814 is used to mount this device (probably determined automatically
3815 if you used the C<guestfs_mount> call).");
3816
3817   ("truncate", (RErr, [Pathname "path"]), 199, [],
3818    [InitBasicFS, Always, TestOutputStruct (
3819       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3820        ["truncate"; "/test"];
3821        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3822    "truncate a file to zero size",
3823    "\
3824 This command truncates C<path> to a zero-length file.  The
3825 file must exist already.");
3826
3827   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3828    [InitBasicFS, Always, TestOutputStruct (
3829       [["touch"; "/test"];
3830        ["truncate_size"; "/test"; "1000"];
3831        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3832    "truncate a file to a particular size",
3833    "\
3834 This command truncates C<path> to size C<size> bytes.  The file
3835 must exist already.  If the file is smaller than C<size> then
3836 the file is extended to the required size with null bytes.");
3837
3838   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3839    [InitBasicFS, Always, TestOutputStruct (
3840       [["touch"; "/test"];
3841        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3842        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3843    "set timestamp of a file with nanosecond precision",
3844    "\
3845 This command sets the timestamps of a file with nanosecond
3846 precision.
3847
3848 C<atsecs, atnsecs> are the last access time (atime) in secs and
3849 nanoseconds from the epoch.
3850
3851 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3852 secs and nanoseconds from the epoch.
3853
3854 If the C<*nsecs> field contains the special value C<-1> then
3855 the corresponding timestamp is set to the current time.  (The
3856 C<*secs> field is ignored in this case).
3857
3858 If the C<*nsecs> field contains the special value C<-2> then
3859 the corresponding timestamp is left unchanged.  (The
3860 C<*secs> field is ignored in this case).");
3861
3862   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3863    [InitBasicFS, Always, TestOutputStruct (
3864       [["mkdir_mode"; "/test"; "0o111"];
3865        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3866    "create a directory with a particular mode",
3867    "\
3868 This command creates a directory, setting the initial permissions
3869 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3870
3871   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3872    [], (* XXX *)
3873    "change file owner and group",
3874    "\
3875 Change the file owner to C<owner> and group to C<group>.
3876 This is like C<guestfs_chown> but if C<path> is a symlink then
3877 the link itself is changed, not the target.
3878
3879 Only numeric uid and gid are supported.  If you want to use
3880 names, you will need to locate and parse the password file
3881 yourself (Augeas support makes this relatively easy).");
3882
3883   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3884    [], (* XXX *)
3885    "lstat on multiple files",
3886    "\
3887 This call allows you to perform the C<guestfs_lstat> operation
3888 on multiple files, where all files are in the directory C<path>.
3889 C<names> is the list of files from this directory.
3890
3891 On return you get a list of stat structs, with a one-to-one
3892 correspondence to the C<names> list.  If any name did not exist
3893 or could not be lstat'd, then the C<ino> field of that structure
3894 is set to C<-1>.
3895
3896 This call is intended for programs that want to efficiently
3897 list a directory contents without making many round-trips.
3898 See also C<guestfs_lxattrlist> for a similarly efficient call
3899 for getting extended attributes.  Very long directory listings
3900 might cause the protocol message size to be exceeded, causing
3901 this call to fail.  The caller must split up such requests
3902 into smaller groups of names.");
3903
3904   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3905    [], (* XXX *)
3906    "lgetxattr on multiple files",
3907    "\
3908 This call allows you to get the extended attributes
3909 of multiple files, where all files are in the directory C<path>.
3910 C<names> is the list of files from this directory.
3911
3912 On return you get a flat list of xattr structs which must be
3913 interpreted sequentially.  The first xattr struct always has a zero-length
3914 C<attrname>.  C<attrval> in this struct is zero-length
3915 to indicate there was an error doing C<lgetxattr> for this
3916 file, I<or> is a C string which is a decimal number
3917 (the number of following attributes for this file, which could
3918 be C<\"0\">).  Then after the first xattr struct are the
3919 zero or more attributes for the first named file.
3920 This repeats for the second and subsequent files.
3921
3922 This call is intended for programs that want to efficiently
3923 list a directory contents without making many round-trips.
3924 See also C<guestfs_lstatlist> for a similarly efficient call
3925 for getting standard stats.  Very long directory listings
3926 might cause the protocol message size to be exceeded, causing
3927 this call to fail.  The caller must split up such requests
3928 into smaller groups of names.");
3929
3930   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3931    [], (* XXX *)
3932    "readlink on multiple files",
3933    "\
3934 This call allows you to do a C<readlink> operation
3935 on multiple files, where all files are in the directory C<path>.
3936 C<names> is the list of files from this directory.
3937
3938 On return you get a list of strings, with a one-to-one
3939 correspondence to the C<names> list.  Each string is the
3940 value of the symbol link.
3941
3942 If the C<readlink(2)> operation fails on any name, then
3943 the corresponding result string is the empty string C<\"\">.
3944 However the whole operation is completed even if there
3945 were C<readlink(2)> errors, and so you can call this
3946 function with names where you don't know if they are
3947 symbolic links already (albeit slightly less efficient).
3948
3949 This call is intended for programs that want to efficiently
3950 list a directory contents without making many round-trips.
3951 Very long directory listings might cause the protocol
3952 message size to be exceeded, causing
3953 this call to fail.  The caller must split up such requests
3954 into smaller groups of names.");
3955
3956   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3957    [InitISOFS, Always, TestOutputBuffer (
3958       [["pread"; "/known-4"; "1"; "3"]], "\n");
3959     InitISOFS, Always, TestOutputBuffer (
3960       [["pread"; "/empty"; "0"; "100"]], "")],
3961    "read part of a file",
3962    "\
3963 This command lets you read part of a file.  It reads C<count>
3964 bytes of the file, starting at C<offset>, from file C<path>.
3965
3966 This may read fewer bytes than requested.  For further details
3967 see the L<pread(2)> system call.");
3968
3969   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3970    [InitEmpty, Always, TestRun (
3971       [["part_init"; "/dev/sda"; "gpt"]])],
3972    "create an empty partition table",
3973    "\
3974 This creates an empty partition table on C<device> of one of the
3975 partition types listed below.  Usually C<parttype> should be
3976 either C<msdos> or C<gpt> (for large disks).
3977
3978 Initially there are no partitions.  Following this, you should
3979 call C<guestfs_part_add> for each partition required.
3980
3981 Possible values for C<parttype> are:
3982
3983 =over 4
3984
3985 =item B<efi> | B<gpt>
3986
3987 Intel EFI / GPT partition table.
3988
3989 This is recommended for >= 2 TB partitions that will be accessed
3990 from Linux and Intel-based Mac OS X.  It also has limited backwards
3991 compatibility with the C<mbr> format.
3992
3993 =item B<mbr> | B<msdos>
3994
3995 The standard PC \"Master Boot Record\" (MBR) format used
3996 by MS-DOS and Windows.  This partition type will B<only> work
3997 for device sizes up to 2 TB.  For large disks we recommend
3998 using C<gpt>.
3999
4000 =back
4001
4002 Other partition table types that may work but are not
4003 supported include:
4004
4005 =over 4
4006
4007 =item B<aix>
4008
4009 AIX disk labels.
4010
4011 =item B<amiga> | B<rdb>
4012
4013 Amiga \"Rigid Disk Block\" format.
4014
4015 =item B<bsd>
4016
4017 BSD disk labels.
4018
4019 =item B<dasd>
4020
4021 DASD, used on IBM mainframes.
4022
4023 =item B<dvh>
4024
4025 MIPS/SGI volumes.
4026
4027 =item B<mac>
4028
4029 Old Mac partition format.  Modern Macs use C<gpt>.
4030
4031 =item B<pc98>
4032
4033 NEC PC-98 format, common in Japan apparently.
4034
4035 =item B<sun>
4036
4037 Sun disk labels.
4038
4039 =back");
4040
4041   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4042    [InitEmpty, Always, TestRun (
4043       [["part_init"; "/dev/sda"; "mbr"];
4044        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4045     InitEmpty, Always, TestRun (
4046       [["part_init"; "/dev/sda"; "gpt"];
4047        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4048        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4049     InitEmpty, Always, TestRun (
4050       [["part_init"; "/dev/sda"; "mbr"];
4051        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4052        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4053        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4054        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4055    "add a partition to the device",
4056    "\
4057 This command adds a partition to C<device>.  If there is no partition
4058 table on the device, call C<guestfs_part_init> first.
4059
4060 The C<prlogex> parameter is the type of partition.  Normally you
4061 should pass C<p> or C<primary> here, but MBR partition tables also
4062 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4063 types.
4064
4065 C<startsect> and C<endsect> are the start and end of the partition
4066 in I<sectors>.  C<endsect> may be negative, which means it counts
4067 backwards from the end of the disk (C<-1> is the last sector).
4068
4069 Creating a partition which covers the whole disk is not so easy.
4070 Use C<guestfs_part_disk> to do that.");
4071
4072   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4073    [InitEmpty, Always, TestRun (
4074       [["part_disk"; "/dev/sda"; "mbr"]]);
4075     InitEmpty, Always, TestRun (
4076       [["part_disk"; "/dev/sda"; "gpt"]])],
4077    "partition whole disk with a single primary partition",
4078    "\
4079 This command is simply a combination of C<guestfs_part_init>
4080 followed by C<guestfs_part_add> to create a single primary partition
4081 covering the whole disk.
4082
4083 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4084 but other possible values are described in C<guestfs_part_init>.");
4085
4086   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4087    [InitEmpty, Always, TestRun (
4088       [["part_disk"; "/dev/sda"; "mbr"];
4089        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4090    "make a partition bootable",
4091    "\
4092 This sets the bootable flag on partition numbered C<partnum> on
4093 device C<device>.  Note that partitions are numbered from 1.
4094
4095 The bootable flag is used by some PC BIOSes to determine which
4096 partition to boot from.  It is by no means universally recognized,
4097 and in any case if your operating system installed a boot
4098 sector on the device itself, then that takes precedence.");
4099
4100   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4101    [InitEmpty, Always, TestRun (
4102       [["part_disk"; "/dev/sda"; "gpt"];
4103        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4104    "set partition name",
4105    "\
4106 This sets the partition name on partition numbered C<partnum> on
4107 device C<device>.  Note that partitions are numbered from 1.
4108
4109 The partition name can only be set on certain types of partition
4110 table.  This works on C<gpt> but not on C<mbr> partitions.");
4111
4112   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4113    [], (* XXX Add a regression test for this. *)
4114    "list partitions on a device",
4115    "\
4116 This command parses the partition table on C<device> and
4117 returns the list of partitions found.
4118
4119 The fields in the returned structure are:
4120
4121 =over 4
4122
4123 =item B<part_num>
4124
4125 Partition number, counting from 1.
4126
4127 =item B<part_start>
4128
4129 Start of the partition I<in bytes>.  To get sectors you have to
4130 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4131
4132 =item B<part_end>
4133
4134 End of the partition in bytes.
4135
4136 =item B<part_size>
4137
4138 Size of the partition in bytes.
4139
4140 =back");
4141
4142   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4143    [InitEmpty, Always, TestOutput (
4144       [["part_disk"; "/dev/sda"; "gpt"];
4145        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4146    "get the partition table type",
4147    "\
4148 This command examines the partition table on C<device> and
4149 returns the partition table type (format) being used.
4150
4151 Common return values include: C<msdos> (a DOS/Windows style MBR
4152 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4153 values are possible, although unusual.  See C<guestfs_part_init>
4154 for a full list.");
4155
4156   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4157    [InitBasicFS, Always, TestOutputBuffer (
4158       [["fill"; "0x63"; "10"; "/test"];
4159        ["read_file"; "/test"]], "cccccccccc")],
4160    "fill a file with octets",
4161    "\
4162 This command creates a new file called C<path>.  The initial
4163 content of the file is C<len> octets of C<c>, where C<c>
4164 must be a number in the range C<[0..255]>.
4165
4166 To fill a file with zero bytes (sparsely), it is
4167 much more efficient to use C<guestfs_truncate_size>.");
4168
4169   ("available", (RErr, [StringList "groups"]), 216, [],
4170    [InitNone, Always, TestRun [["available"; ""]]],
4171    "test availability of some parts of the API",
4172    "\
4173 This command is used to check the availability of some
4174 groups of functionality in the appliance, which not all builds of
4175 the libguestfs appliance will be able to provide.
4176
4177 The libguestfs groups, and the functions that those
4178 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4179
4180 The argument C<groups> is a list of group names, eg:
4181 C<[\"inotify\", \"augeas\"]> would check for the availability of
4182 the Linux inotify functions and Augeas (configuration file
4183 editing) functions.
4184
4185 The command returns no error if I<all> requested groups are available.
4186
4187 It fails with an error if one or more of the requested
4188 groups is unavailable in the appliance.
4189
4190 If an unknown group name is included in the
4191 list of groups then an error is always returned.
4192
4193 I<Notes:>
4194
4195 =over 4
4196
4197 =item *
4198
4199 You must call C<guestfs_launch> before calling this function.
4200
4201 The reason is because we don't know what groups are
4202 supported by the appliance/daemon until it is running and can
4203 be queried.
4204
4205 =item *
4206
4207 If a group of functions is available, this does not necessarily
4208 mean that they will work.  You still have to check for errors
4209 when calling individual API functions even if they are
4210 available.
4211
4212 =item *
4213
4214 It is usually the job of distro packagers to build
4215 complete functionality into the libguestfs appliance.
4216 Upstream libguestfs, if built from source with all
4217 requirements satisfied, will support everything.
4218
4219 =item *
4220
4221 This call was added in version C<1.0.80>.  In previous
4222 versions of libguestfs all you could do would be to speculatively
4223 execute a command to find out if the daemon implemented it.
4224 See also C<guestfs_version>.
4225
4226 =back");
4227
4228   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4229    [InitBasicFS, Always, TestOutputBuffer (
4230       [["write_file"; "/src"; "hello, world"; "0"];
4231        ["dd"; "/src"; "/dest"];
4232        ["read_file"; "/dest"]], "hello, world")],
4233    "copy from source to destination using dd",
4234    "\
4235 This command copies from one source device or file C<src>
4236 to another destination device or file C<dest>.  Normally you
4237 would use this to copy to or from a device or partition, for
4238 example to duplicate a filesystem.
4239
4240 If the destination is a device, it must be as large or larger
4241 than the source file or device, otherwise the copy will fail.
4242 This command cannot do partial copies.");
4243
4244   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4245    [InitBasicFS, Always, TestOutputInt (
4246       [["write_file"; "/file"; "hello, world"; "0"];
4247        ["filesize"; "/file"]], 12)],
4248    "return the size of the file in bytes",
4249    "\
4250 This command returns the size of C<file> in bytes.
4251
4252 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4253 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4254 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4255
4256   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4257    [InitBasicFSonLVM, Always, TestOutputList (
4258       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4259        ["lvs"]], ["/dev/VG/LV2"])],
4260    "rename an LVM logical volume",
4261    "\
4262 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4263
4264   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4265    [InitBasicFSonLVM, Always, TestOutputList (
4266       [["umount"; "/"];
4267        ["vg_activate"; "false"; "VG"];
4268        ["vgrename"; "VG"; "VG2"];
4269        ["vg_activate"; "true"; "VG2"];
4270        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4271        ["vgs"]], ["VG2"])],
4272    "rename an LVM volume group",
4273    "\
4274 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4275
4276   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4277    [InitISOFS, Always, TestOutputBuffer (
4278       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4279    "list the contents of a single file in an initrd",
4280    "\
4281 This command unpacks the file C<filename> from the initrd file
4282 called C<initrdpath>.  The filename must be given I<without> the
4283 initial C</> character.
4284
4285 For example, in guestfish you could use the following command
4286 to examine the boot script (usually called C</init>)
4287 contained in a Linux initrd or initramfs image:
4288
4289  initrd-cat /boot/initrd-<version>.img init
4290
4291 See also C<guestfs_initrd_list>.");
4292
4293   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4294    [],
4295    "get the UUID of a physical volume",
4296    "\
4297 This command returns the UUID of the LVM PV C<device>.");
4298
4299   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4300    [],
4301    "get the UUID of a volume group",
4302    "\
4303 This command returns the UUID of the LVM VG named C<vgname>.");
4304
4305   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4306    [],
4307    "get the UUID of a logical volume",
4308    "\
4309 This command returns the UUID of the LVM LV C<device>.");
4310
4311   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4312    [],
4313    "get the PV UUIDs containing the volume group",
4314    "\
4315 Given a VG called C<vgname>, this returns the UUIDs of all
4316 the physical volumes that this volume group resides on.
4317
4318 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4319 calls to associate physical volumes and volume groups.
4320
4321 See also C<guestfs_vglvuuids>.");
4322
4323   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4324    [],
4325    "get the LV UUIDs of all LVs in the volume group",
4326    "\
4327 Given a VG called C<vgname>, this returns the UUIDs of all
4328 the logical volumes created in this volume group.
4329
4330 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4331 calls to associate logical volumes and volume groups.
4332
4333 See also C<guestfs_vgpvuuids>.");
4334
4335 ]
4336
4337 let all_functions = non_daemon_functions @ daemon_functions
4338
4339 (* In some places we want the functions to be displayed sorted
4340  * alphabetically, so this is useful:
4341  *)
4342 let all_functions_sorted =
4343   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4344                compare n1 n2) all_functions
4345
4346 (* Field types for structures. *)
4347 type field =
4348   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4349   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4350   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4351   | FUInt32
4352   | FInt32
4353   | FUInt64
4354   | FInt64
4355   | FBytes                      (* Any int measure that counts bytes. *)
4356   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4357   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4358
4359 (* Because we generate extra parsing code for LVM command line tools,
4360  * we have to pull out the LVM columns separately here.
4361  *)
4362 let lvm_pv_cols = [
4363   "pv_name", FString;
4364   "pv_uuid", FUUID;
4365   "pv_fmt", FString;
4366   "pv_size", FBytes;
4367   "dev_size", FBytes;
4368   "pv_free", FBytes;
4369   "pv_used", FBytes;
4370   "pv_attr", FString (* XXX *);
4371   "pv_pe_count", FInt64;
4372   "pv_pe_alloc_count", FInt64;
4373   "pv_tags", FString;
4374   "pe_start", FBytes;
4375   "pv_mda_count", FInt64;
4376   "pv_mda_free", FBytes;
4377   (* Not in Fedora 10:
4378      "pv_mda_size", FBytes;
4379   *)
4380 ]
4381 let lvm_vg_cols = [
4382   "vg_name", FString;
4383   "vg_uuid", FUUID;
4384   "vg_fmt", FString;
4385   "vg_attr", FString (* XXX *);
4386   "vg_size", FBytes;
4387   "vg_free", FBytes;
4388   "vg_sysid", FString;
4389   "vg_extent_size", FBytes;
4390   "vg_extent_count", FInt64;
4391   "vg_free_count", FInt64;
4392   "max_lv", FInt64;
4393   "max_pv", FInt64;
4394   "pv_count", FInt64;
4395   "lv_count", FInt64;
4396   "snap_count", FInt64;
4397   "vg_seqno", FInt64;
4398   "vg_tags", FString;
4399   "vg_mda_count", FInt64;
4400   "vg_mda_free", FBytes;
4401   (* Not in Fedora 10:
4402      "vg_mda_size", FBytes;
4403   *)
4404 ]
4405 let lvm_lv_cols = [
4406   "lv_name", FString;
4407   "lv_uuid", FUUID;
4408   "lv_attr", FString (* XXX *);
4409   "lv_major", FInt64;
4410   "lv_minor", FInt64;
4411   "lv_kernel_major", FInt64;
4412   "lv_kernel_minor", FInt64;
4413   "lv_size", FBytes;
4414   "seg_count", FInt64;
4415   "origin", FString;
4416   "snap_percent", FOptPercent;
4417   "copy_percent", FOptPercent;
4418   "move_pv", FString;
4419   "lv_tags", FString;
4420   "mirror_log", FString;
4421   "modules", FString;
4422 ]
4423
4424 (* Names and fields in all structures (in RStruct and RStructList)
4425  * that we support.
4426  *)
4427 let structs = [
4428   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4429    * not use this struct in any new code.
4430    *)
4431   "int_bool", [
4432     "i", FInt32;                (* for historical compatibility *)
4433     "b", FInt32;                (* for historical compatibility *)
4434   ];
4435
4436   (* LVM PVs, VGs, LVs. *)
4437   "lvm_pv", lvm_pv_cols;
4438   "lvm_vg", lvm_vg_cols;
4439   "lvm_lv", lvm_lv_cols;
4440
4441   (* Column names and types from stat structures.
4442    * NB. Can't use things like 'st_atime' because glibc header files
4443    * define some of these as macros.  Ugh.
4444    *)
4445   "stat", [
4446     "dev", FInt64;
4447     "ino", FInt64;
4448     "mode", FInt64;
4449     "nlink", FInt64;
4450     "uid", FInt64;
4451     "gid", FInt64;
4452     "rdev", FInt64;
4453     "size", FInt64;
4454     "blksize", FInt64;
4455     "blocks", FInt64;
4456     "atime", FInt64;
4457     "mtime", FInt64;
4458     "ctime", FInt64;
4459   ];
4460   "statvfs", [
4461     "bsize", FInt64;
4462     "frsize", FInt64;
4463     "blocks", FInt64;
4464     "bfree", FInt64;
4465     "bavail", FInt64;
4466     "files", FInt64;
4467     "ffree", FInt64;
4468     "favail", FInt64;
4469     "fsid", FInt64;
4470     "flag", FInt64;
4471     "namemax", FInt64;
4472   ];
4473
4474   (* Column names in dirent structure. *)
4475   "dirent", [
4476     "ino", FInt64;
4477     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4478     "ftyp", FChar;
4479     "name", FString;
4480   ];
4481
4482   (* Version numbers. *)
4483   "version", [
4484     "major", FInt64;
4485     "minor", FInt64;
4486     "release", FInt64;
4487     "extra", FString;
4488   ];
4489
4490   (* Extended attribute. *)
4491   "xattr", [
4492     "attrname", FString;
4493     "attrval", FBuffer;
4494   ];
4495
4496   (* Inotify events. *)
4497   "inotify_event", [
4498     "in_wd", FInt64;
4499     "in_mask", FUInt32;
4500     "in_cookie", FUInt32;
4501     "in_name", FString;
4502   ];
4503
4504   (* Partition table entry. *)
4505   "partition", [
4506     "part_num", FInt32;
4507     "part_start", FBytes;
4508     "part_end", FBytes;
4509     "part_size", FBytes;
4510   ];
4511 ] (* end of structs *)
4512
4513 (* Ugh, Java has to be different ..
4514  * These names are also used by the Haskell bindings.
4515  *)
4516 let java_structs = [
4517   "int_bool", "IntBool";
4518   "lvm_pv", "PV";
4519   "lvm_vg", "VG";
4520   "lvm_lv", "LV";
4521   "stat", "Stat";
4522   "statvfs", "StatVFS";
4523   "dirent", "Dirent";
4524   "version", "Version";
4525   "xattr", "XAttr";
4526   "inotify_event", "INotifyEvent";
4527   "partition", "Partition";
4528 ]
4529
4530 (* What structs are actually returned. *)
4531 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4532
4533 (* Returns a list of RStruct/RStructList structs that are returned
4534  * by any function.  Each element of returned list is a pair:
4535  *
4536  * (structname, RStructOnly)
4537  *    == there exists function which returns RStruct (_, structname)
4538  * (structname, RStructListOnly)
4539  *    == there exists function which returns RStructList (_, structname)
4540  * (structname, RStructAndList)
4541  *    == there are functions returning both RStruct (_, structname)
4542  *                                      and RStructList (_, structname)
4543  *)
4544 let rstructs_used_by functions =
4545   (* ||| is a "logical OR" for rstructs_used_t *)
4546   let (|||) a b =
4547     match a, b with
4548     | RStructAndList, _
4549     | _, RStructAndList -> RStructAndList
4550     | RStructOnly, RStructListOnly
4551     | RStructListOnly, RStructOnly -> RStructAndList
4552     | RStructOnly, RStructOnly -> RStructOnly
4553     | RStructListOnly, RStructListOnly -> RStructListOnly
4554   in
4555
4556   let h = Hashtbl.create 13 in
4557
4558   (* if elem->oldv exists, update entry using ||| operator,
4559    * else just add elem->newv to the hash
4560    *)
4561   let update elem newv =
4562     try  let oldv = Hashtbl.find h elem in
4563          Hashtbl.replace h elem (newv ||| oldv)
4564     with Not_found -> Hashtbl.add h elem newv
4565   in
4566
4567   List.iter (
4568     fun (_, style, _, _, _, _, _) ->
4569       match fst style with
4570       | RStruct (_, structname) -> update structname RStructOnly
4571       | RStructList (_, structname) -> update structname RStructListOnly
4572       | _ -> ()
4573   ) functions;
4574
4575   (* return key->values as a list of (key,value) *)
4576   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4577
4578 (* Used for testing language bindings. *)
4579 type callt =
4580   | CallString of string
4581   | CallOptString of string option
4582   | CallStringList of string list
4583   | CallInt of int
4584   | CallInt64 of int64
4585   | CallBool of bool
4586
4587 (* Used to memoize the result of pod2text. *)
4588 let pod2text_memo_filename = "src/.pod2text.data"
4589 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4590   try
4591     let chan = open_in pod2text_memo_filename in
4592     let v = input_value chan in
4593     close_in chan;
4594     v
4595   with
4596     _ -> Hashtbl.create 13
4597 let pod2text_memo_updated () =
4598   let chan = open_out pod2text_memo_filename in
4599   output_value chan pod2text_memo;
4600   close_out chan
4601
4602 (* Useful functions.
4603  * Note we don't want to use any external OCaml libraries which
4604  * makes this a bit harder than it should be.
4605  *)
4606 module StringMap = Map.Make (String)
4607
4608 let failwithf fs = ksprintf failwith fs
4609
4610 let unique = let i = ref 0 in fun () -> incr i; !i
4611
4612 let replace_char s c1 c2 =
4613   let s2 = String.copy s in
4614   let r = ref false in
4615   for i = 0 to String.length s2 - 1 do
4616     if String.unsafe_get s2 i = c1 then (
4617       String.unsafe_set s2 i c2;
4618       r := true
4619     )
4620   done;
4621   if not !r then s else s2
4622
4623 let isspace c =
4624   c = ' '
4625   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4626
4627 let triml ?(test = isspace) str =
4628   let i = ref 0 in
4629   let n = ref (String.length str) in
4630   while !n > 0 && test str.[!i]; do
4631     decr n;
4632     incr i
4633   done;
4634   if !i = 0 then str
4635   else String.sub str !i !n
4636
4637 let trimr ?(test = isspace) str =
4638   let n = ref (String.length str) in
4639   while !n > 0 && test str.[!n-1]; do
4640     decr n
4641   done;
4642   if !n = String.length str then str
4643   else String.sub str 0 !n
4644
4645 let trim ?(test = isspace) str =
4646   trimr ~test (triml ~test str)
4647
4648 let rec find s sub =
4649   let len = String.length s in
4650   let sublen = String.length sub in
4651   let rec loop i =
4652     if i <= len-sublen then (
4653       let rec loop2 j =
4654         if j < sublen then (
4655           if s.[i+j] = sub.[j] then loop2 (j+1)
4656           else -1
4657         ) else
4658           i (* found *)
4659       in
4660       let r = loop2 0 in
4661       if r = -1 then loop (i+1) else r
4662     ) else
4663       -1 (* not found *)
4664   in
4665   loop 0
4666
4667 let rec replace_str s s1 s2 =
4668   let len = String.length s in
4669   let sublen = String.length s1 in
4670   let i = find s s1 in
4671   if i = -1 then s
4672   else (
4673     let s' = String.sub s 0 i in
4674     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4675     s' ^ s2 ^ replace_str s'' s1 s2
4676   )
4677
4678 let rec string_split sep str =
4679   let len = String.length str in
4680   let seplen = String.length sep in
4681   let i = find str sep in
4682   if i = -1 then [str]
4683   else (
4684     let s' = String.sub str 0 i in
4685     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4686     s' :: string_split sep s''
4687   )
4688
4689 let files_equal n1 n2 =
4690   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4691   match Sys.command cmd with
4692   | 0 -> true
4693   | 1 -> false
4694   | i -> failwithf "%s: failed with error code %d" cmd i
4695
4696 let rec filter_map f = function
4697   | [] -> []
4698   | x :: xs ->
4699       match f x with
4700       | Some y -> y :: filter_map f xs
4701       | None -> filter_map f xs
4702
4703 let rec find_map f = function
4704   | [] -> raise Not_found
4705   | x :: xs ->
4706       match f x with
4707       | Some y -> y
4708       | None -> find_map f xs
4709
4710 let iteri f xs =
4711   let rec loop i = function
4712     | [] -> ()
4713     | x :: xs -> f i x; loop (i+1) xs
4714   in
4715   loop 0 xs
4716
4717 let mapi f xs =
4718   let rec loop i = function
4719     | [] -> []
4720     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4721   in
4722   loop 0 xs
4723
4724 let count_chars c str =
4725   let count = ref 0 in
4726   for i = 0 to String.length str - 1 do
4727     if c = String.unsafe_get str i then incr count
4728   done;
4729   !count
4730
4731 let name_of_argt = function
4732   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4733   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4734   | FileIn n | FileOut n -> n
4735
4736 let java_name_of_struct typ =
4737   try List.assoc typ java_structs
4738   with Not_found ->
4739     failwithf
4740       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4741
4742 let cols_of_struct typ =
4743   try List.assoc typ structs
4744   with Not_found ->
4745     failwithf "cols_of_struct: unknown struct %s" typ
4746
4747 let seq_of_test = function
4748   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4749   | TestOutputListOfDevices (s, _)
4750   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4751   | TestOutputTrue s | TestOutputFalse s
4752   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4753   | TestOutputStruct (s, _)
4754   | TestLastFail s -> s
4755
4756 (* Handling for function flags. *)
4757 let protocol_limit_warning =
4758   "Because of the message protocol, there is a transfer limit
4759 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4760
4761 let danger_will_robinson =
4762   "B<This command is dangerous.  Without careful use you
4763 can easily destroy all your data>."
4764
4765 let deprecation_notice flags =
4766   try
4767     let alt =
4768       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4769     let txt =
4770       sprintf "This function is deprecated.
4771 In new code, use the C<%s> call instead.
4772
4773 Deprecated functions will not be removed from the API, but the
4774 fact that they are deprecated indicates that there are problems
4775 with correct use of these functions." alt in
4776     Some txt
4777   with
4778     Not_found -> None
4779
4780 (* Create list of optional groups. *)
4781 let optgroups =
4782   let h = Hashtbl.create 13 in
4783   List.iter (
4784     fun (name, _, _, flags, _, _, _) ->
4785       List.iter (
4786         function
4787         | Optional group ->
4788             let names = try Hashtbl.find h group with Not_found -> [] in
4789             Hashtbl.replace h group (name :: names)
4790         | _ -> ()
4791       ) flags
4792   ) daemon_functions;
4793   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4794   let groups =
4795     List.map (
4796       fun group -> group, List.sort compare (Hashtbl.find h group)
4797     ) groups in
4798   List.sort (fun x y -> compare (fst x) (fst y)) groups
4799
4800 (* Check function names etc. for consistency. *)
4801 let check_functions () =
4802   let contains_uppercase str =
4803     let len = String.length str in
4804     let rec loop i =
4805       if i >= len then false
4806       else (
4807         let c = str.[i] in
4808         if c >= 'A' && c <= 'Z' then true
4809         else loop (i+1)
4810       )
4811     in
4812     loop 0
4813   in
4814
4815   (* Check function names. *)
4816   List.iter (
4817     fun (name, _, _, _, _, _, _) ->
4818       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4819         failwithf "function name %s does not need 'guestfs' prefix" name;
4820       if name = "" then
4821         failwithf "function name is empty";
4822       if name.[0] < 'a' || name.[0] > 'z' then
4823         failwithf "function name %s must start with lowercase a-z" name;
4824       if String.contains name '-' then
4825         failwithf "function name %s should not contain '-', use '_' instead."
4826           name
4827   ) all_functions;
4828
4829   (* Check function parameter/return names. *)
4830   List.iter (
4831     fun (name, style, _, _, _, _, _) ->
4832       let check_arg_ret_name n =
4833         if contains_uppercase n then
4834           failwithf "%s param/ret %s should not contain uppercase chars"
4835             name n;
4836         if String.contains n '-' || String.contains n '_' then
4837           failwithf "%s param/ret %s should not contain '-' or '_'"
4838             name n;
4839         if n = "value" then
4840           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;
4841         if n = "int" || n = "char" || n = "short" || n = "long" then
4842           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4843         if n = "i" || n = "n" then
4844           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4845         if n = "argv" || n = "args" then
4846           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4847
4848         (* List Haskell, OCaml and C keywords here.
4849          * http://www.haskell.org/haskellwiki/Keywords
4850          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4851          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4852          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4853          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4854          * Omitting _-containing words, since they're handled above.
4855          * Omitting the OCaml reserved word, "val", is ok,
4856          * and saves us from renaming several parameters.
4857          *)
4858         let reserved = [
4859           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4860           "char"; "class"; "const"; "constraint"; "continue"; "data";
4861           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4862           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4863           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4864           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4865           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4866           "interface";
4867           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4868           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4869           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4870           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4871           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4872           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4873           "volatile"; "when"; "where"; "while";
4874           ] in
4875         if List.mem n reserved then
4876           failwithf "%s has param/ret using reserved word %s" name n;
4877       in
4878
4879       (match fst style with
4880        | RErr -> ()
4881        | RInt n | RInt64 n | RBool n
4882        | RConstString n | RConstOptString n | RString n
4883        | RStringList n | RStruct (n, _) | RStructList (n, _)
4884        | RHashtable n | RBufferOut n ->
4885            check_arg_ret_name n
4886       );
4887       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4888   ) all_functions;
4889
4890   (* Check short descriptions. *)
4891   List.iter (
4892     fun (name, _, _, _, _, shortdesc, _) ->
4893       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4894         failwithf "short description of %s should begin with lowercase." name;
4895       let c = shortdesc.[String.length shortdesc-1] in
4896       if c = '\n' || c = '.' then
4897         failwithf "short description of %s should not end with . or \\n." name
4898   ) all_functions;
4899
4900   (* Check long dscriptions. *)
4901   List.iter (
4902     fun (name, _, _, _, _, _, longdesc) ->
4903       if longdesc.[String.length longdesc-1] = '\n' then
4904         failwithf "long description of %s should not end with \\n." name
4905   ) all_functions;
4906
4907   (* Check proc_nrs. *)
4908   List.iter (
4909     fun (name, _, proc_nr, _, _, _, _) ->
4910       if proc_nr <= 0 then
4911         failwithf "daemon function %s should have proc_nr > 0" name
4912   ) daemon_functions;
4913
4914   List.iter (
4915     fun (name, _, proc_nr, _, _, _, _) ->
4916       if proc_nr <> -1 then
4917         failwithf "non-daemon function %s should have proc_nr -1" name
4918   ) non_daemon_functions;
4919
4920   let proc_nrs =
4921     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4922       daemon_functions in
4923   let proc_nrs =
4924     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4925   let rec loop = function
4926     | [] -> ()
4927     | [_] -> ()
4928     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4929         loop rest
4930     | (name1,nr1) :: (name2,nr2) :: _ ->
4931         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4932           name1 name2 nr1 nr2
4933   in
4934   loop proc_nrs;
4935
4936   (* Check tests. *)
4937   List.iter (
4938     function
4939       (* Ignore functions that have no tests.  We generate a
4940        * warning when the user does 'make check' instead.
4941        *)
4942     | name, _, _, _, [], _, _ -> ()
4943     | name, _, _, _, tests, _, _ ->
4944         let funcs =
4945           List.map (
4946             fun (_, _, test) ->
4947               match seq_of_test test with
4948               | [] ->
4949                   failwithf "%s has a test containing an empty sequence" name
4950               | cmds -> List.map List.hd cmds
4951           ) tests in
4952         let funcs = List.flatten funcs in
4953
4954         let tested = List.mem name funcs in
4955
4956         if not tested then
4957           failwithf "function %s has tests but does not test itself" name
4958   ) all_functions
4959
4960 (* 'pr' prints to the current output file. *)
4961 let chan = ref Pervasives.stdout
4962 let lines = ref 0
4963 let pr fs =
4964   ksprintf
4965     (fun str ->
4966        let i = count_chars '\n' str in
4967        lines := !lines + i;
4968        output_string !chan str
4969     ) fs
4970
4971 let copyright_years =
4972   let this_year = 1900 + (localtime (time ())).tm_year in
4973   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4974
4975 (* Generate a header block in a number of standard styles. *)
4976 type comment_style =
4977     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4978 type license = GPLv2plus | LGPLv2plus
4979
4980 let generate_header ?(extra_inputs = []) comment license =
4981   let inputs = "src/generator.ml" :: extra_inputs in
4982   let c = match comment with
4983     | CStyle ->         pr "/* "; " *"
4984     | CPlusPlusStyle -> pr "// "; "//"
4985     | HashStyle ->      pr "# ";  "#"
4986     | OCamlStyle ->     pr "(* "; " *"
4987     | HaskellStyle ->   pr "{- "; "  " in
4988   pr "libguestfs generated file\n";
4989   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4990   List.iter (pr "%s   %s\n" c) inputs;
4991   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4992   pr "%s\n" c;
4993   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4994   pr "%s\n" c;
4995   (match license with
4996    | GPLv2plus ->
4997        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4998        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4999        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5000        pr "%s (at your option) any later version.\n" c;
5001        pr "%s\n" c;
5002        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5003        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5004        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5005        pr "%s GNU General Public License for more details.\n" c;
5006        pr "%s\n" c;
5007        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5008        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5009        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5010
5011    | LGPLv2plus ->
5012        pr "%s This library is free software; you can redistribute it and/or\n" c;
5013        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5014        pr "%s License as published by the Free Software Foundation; either\n" c;
5015        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5016        pr "%s\n" c;
5017        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5018        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5019        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5020        pr "%s Lesser General Public License for more details.\n" c;
5021        pr "%s\n" c;
5022        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5023        pr "%s License along with this library; if not, write to the Free Software\n" c;
5024        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5025   );
5026   (match comment with
5027    | CStyle -> pr " */\n"
5028    | CPlusPlusStyle
5029    | HashStyle -> ()
5030    | OCamlStyle -> pr " *)\n"
5031    | HaskellStyle -> pr "-}\n"
5032   );
5033   pr "\n"
5034
5035 (* Start of main code generation functions below this line. *)
5036
5037 (* Generate the pod documentation for the C API. *)
5038 let rec generate_actions_pod () =
5039   List.iter (
5040     fun (shortname, style, _, flags, _, _, longdesc) ->
5041       if not (List.mem NotInDocs flags) then (
5042         let name = "guestfs_" ^ shortname in
5043         pr "=head2 %s\n\n" name;
5044         pr " ";
5045         generate_prototype ~extern:false ~handle:"handle" name style;
5046         pr "\n\n";
5047         pr "%s\n\n" longdesc;
5048         (match fst style with
5049          | RErr ->
5050              pr "This function returns 0 on success or -1 on error.\n\n"
5051          | RInt _ ->
5052              pr "On error this function returns -1.\n\n"
5053          | RInt64 _ ->
5054              pr "On error this function returns -1.\n\n"
5055          | RBool _ ->
5056              pr "This function returns a C truth value on success or -1 on error.\n\n"
5057          | RConstString _ ->
5058              pr "This function returns a string, or NULL on error.
5059 The string is owned by the guest handle and must I<not> be freed.\n\n"
5060          | RConstOptString _ ->
5061              pr "This function returns a string which may be NULL.
5062 There is way to return an error from this function.
5063 The string is owned by the guest handle and must I<not> be freed.\n\n"
5064          | RString _ ->
5065              pr "This function returns a string, or NULL on error.
5066 I<The caller must free the returned string after use>.\n\n"
5067          | RStringList _ ->
5068              pr "This function returns a NULL-terminated array of strings
5069 (like L<environ(3)>), or NULL if there was an error.
5070 I<The caller must free the strings and the array after use>.\n\n"
5071          | RStruct (_, typ) ->
5072              pr "This function returns a C<struct guestfs_%s *>,
5073 or NULL if there was an error.
5074 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5075          | RStructList (_, typ) ->
5076              pr "This function returns a C<struct guestfs_%s_list *>
5077 (see E<lt>guestfs-structs.hE<gt>),
5078 or NULL if there was an error.
5079 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5080          | RHashtable _ ->
5081              pr "This function returns a NULL-terminated array of
5082 strings, or NULL if there was an error.
5083 The array of strings will always have length C<2n+1>, where
5084 C<n> keys and values alternate, followed by the trailing NULL entry.
5085 I<The caller must free the strings and the array after use>.\n\n"
5086          | RBufferOut _ ->
5087              pr "This function returns a buffer, or NULL on error.
5088 The size of the returned buffer is written to C<*size_r>.
5089 I<The caller must free the returned buffer after use>.\n\n"
5090         );
5091         if List.mem ProtocolLimitWarning flags then
5092           pr "%s\n\n" protocol_limit_warning;
5093         if List.mem DangerWillRobinson flags then
5094           pr "%s\n\n" danger_will_robinson;
5095         match deprecation_notice flags with
5096         | None -> ()
5097         | Some txt -> pr "%s\n\n" txt
5098       )
5099   ) all_functions_sorted
5100
5101 and generate_structs_pod () =
5102   (* Structs documentation. *)
5103   List.iter (
5104     fun (typ, cols) ->
5105       pr "=head2 guestfs_%s\n" typ;
5106       pr "\n";
5107       pr " struct guestfs_%s {\n" typ;
5108       List.iter (
5109         function
5110         | name, FChar -> pr "   char %s;\n" name
5111         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5112         | name, FInt32 -> pr "   int32_t %s;\n" name
5113         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5114         | name, FInt64 -> pr "   int64_t %s;\n" name
5115         | name, FString -> pr "   char *%s;\n" name
5116         | name, FBuffer ->
5117             pr "   /* The next two fields describe a byte array. */\n";
5118             pr "   uint32_t %s_len;\n" name;
5119             pr "   char *%s;\n" name
5120         | name, FUUID ->
5121             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5122             pr "   char %s[32];\n" name
5123         | name, FOptPercent ->
5124             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5125             pr "   float %s;\n" name
5126       ) cols;
5127       pr " };\n";
5128       pr " \n";
5129       pr " struct guestfs_%s_list {\n" typ;
5130       pr "   uint32_t len; /* Number of elements in list. */\n";
5131       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5132       pr " };\n";
5133       pr " \n";
5134       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5135       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5136         typ typ;
5137       pr "\n"
5138   ) structs
5139
5140 and generate_availability_pod () =
5141   (* Availability documentation. *)
5142   pr "=over 4\n";
5143   pr "\n";
5144   List.iter (
5145     fun (group, functions) ->
5146       pr "=item B<%s>\n" group;
5147       pr "\n";
5148       pr "The following functions:\n";
5149       List.iter (pr "L</guestfs_%s>\n") functions;
5150       pr "\n"
5151   ) optgroups;
5152   pr "=back\n";
5153   pr "\n"
5154
5155 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5156  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5157  *
5158  * We have to use an underscore instead of a dash because otherwise
5159  * rpcgen generates incorrect code.
5160  *
5161  * This header is NOT exported to clients, but see also generate_structs_h.
5162  *)
5163 and generate_xdr () =
5164   generate_header CStyle LGPLv2plus;
5165
5166   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5167   pr "typedef string str<>;\n";
5168   pr "\n";
5169
5170   (* Internal structures. *)
5171   List.iter (
5172     function
5173     | typ, cols ->
5174         pr "struct guestfs_int_%s {\n" typ;
5175         List.iter (function
5176                    | name, FChar -> pr "  char %s;\n" name
5177                    | name, FString -> pr "  string %s<>;\n" name
5178                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5179                    | name, FUUID -> pr "  opaque %s[32];\n" name
5180                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5181                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5182                    | name, FOptPercent -> pr "  float %s;\n" name
5183                   ) cols;
5184         pr "};\n";
5185         pr "\n";
5186         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5187         pr "\n";
5188   ) structs;
5189
5190   List.iter (
5191     fun (shortname, style, _, _, _, _, _) ->
5192       let name = "guestfs_" ^ shortname in
5193
5194       (match snd style with
5195        | [] -> ()
5196        | args ->
5197            pr "struct %s_args {\n" name;
5198            List.iter (
5199              function
5200              | Pathname n | Device n | Dev_or_Path n | String n ->
5201                  pr "  string %s<>;\n" n
5202              | OptString n -> pr "  str *%s;\n" n
5203              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5204              | Bool n -> pr "  bool %s;\n" n
5205              | Int n -> pr "  int %s;\n" n
5206              | Int64 n -> pr "  hyper %s;\n" n
5207              | FileIn _ | FileOut _ -> ()
5208            ) args;
5209            pr "};\n\n"
5210       );
5211       (match fst style with
5212        | RErr -> ()
5213        | RInt n ->
5214            pr "struct %s_ret {\n" name;
5215            pr "  int %s;\n" n;
5216            pr "};\n\n"
5217        | RInt64 n ->
5218            pr "struct %s_ret {\n" name;
5219            pr "  hyper %s;\n" n;
5220            pr "};\n\n"
5221        | RBool n ->
5222            pr "struct %s_ret {\n" name;
5223            pr "  bool %s;\n" n;
5224            pr "};\n\n"
5225        | RConstString _ | RConstOptString _ ->
5226            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5227        | RString n ->
5228            pr "struct %s_ret {\n" name;
5229            pr "  string %s<>;\n" n;
5230            pr "};\n\n"
5231        | RStringList n ->
5232            pr "struct %s_ret {\n" name;
5233            pr "  str %s<>;\n" n;
5234            pr "};\n\n"
5235        | RStruct (n, typ) ->
5236            pr "struct %s_ret {\n" name;
5237            pr "  guestfs_int_%s %s;\n" typ n;
5238            pr "};\n\n"
5239        | RStructList (n, typ) ->
5240            pr "struct %s_ret {\n" name;
5241            pr "  guestfs_int_%s_list %s;\n" typ n;
5242            pr "};\n\n"
5243        | RHashtable n ->
5244            pr "struct %s_ret {\n" name;
5245            pr "  str %s<>;\n" n;
5246            pr "};\n\n"
5247        | RBufferOut n ->
5248            pr "struct %s_ret {\n" name;
5249            pr "  opaque %s<>;\n" n;
5250            pr "};\n\n"
5251       );
5252   ) daemon_functions;
5253
5254   (* Table of procedure numbers. *)
5255   pr "enum guestfs_procedure {\n";
5256   List.iter (
5257     fun (shortname, _, proc_nr, _, _, _, _) ->
5258       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5259   ) daemon_functions;
5260   pr "  GUESTFS_PROC_NR_PROCS\n";
5261   pr "};\n";
5262   pr "\n";
5263
5264   (* Having to choose a maximum message size is annoying for several
5265    * reasons (it limits what we can do in the API), but it (a) makes
5266    * the protocol a lot simpler, and (b) provides a bound on the size
5267    * of the daemon which operates in limited memory space.
5268    *)
5269   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5270   pr "\n";
5271
5272   (* Message header, etc. *)
5273   pr "\
5274 /* The communication protocol is now documented in the guestfs(3)
5275  * manpage.
5276  */
5277
5278 const GUESTFS_PROGRAM = 0x2000F5F5;
5279 const GUESTFS_PROTOCOL_VERSION = 1;
5280
5281 /* These constants must be larger than any possible message length. */
5282 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5283 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5284
5285 enum guestfs_message_direction {
5286   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5287   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5288 };
5289
5290 enum guestfs_message_status {
5291   GUESTFS_STATUS_OK = 0,
5292   GUESTFS_STATUS_ERROR = 1
5293 };
5294
5295 const GUESTFS_ERROR_LEN = 256;
5296
5297 struct guestfs_message_error {
5298   string error_message<GUESTFS_ERROR_LEN>;
5299 };
5300
5301 struct guestfs_message_header {
5302   unsigned prog;                     /* GUESTFS_PROGRAM */
5303   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5304   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5305   guestfs_message_direction direction;
5306   unsigned serial;                   /* message serial number */
5307   guestfs_message_status status;
5308 };
5309
5310 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5311
5312 struct guestfs_chunk {
5313   int cancel;                        /* if non-zero, transfer is cancelled */
5314   /* data size is 0 bytes if the transfer has finished successfully */
5315   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5316 };
5317 "
5318
5319 (* Generate the guestfs-structs.h file. *)
5320 and generate_structs_h () =
5321   generate_header CStyle LGPLv2plus;
5322
5323   (* This is a public exported header file containing various
5324    * structures.  The structures are carefully written to have
5325    * exactly the same in-memory format as the XDR structures that
5326    * we use on the wire to the daemon.  The reason for creating
5327    * copies of these structures here is just so we don't have to
5328    * export the whole of guestfs_protocol.h (which includes much
5329    * unrelated and XDR-dependent stuff that we don't want to be
5330    * public, or required by clients).
5331    *
5332    * To reiterate, we will pass these structures to and from the
5333    * client with a simple assignment or memcpy, so the format
5334    * must be identical to what rpcgen / the RFC defines.
5335    *)
5336
5337   (* Public structures. *)
5338   List.iter (
5339     fun (typ, cols) ->
5340       pr "struct guestfs_%s {\n" typ;
5341       List.iter (
5342         function
5343         | name, FChar -> pr "  char %s;\n" name
5344         | name, FString -> pr "  char *%s;\n" name
5345         | name, FBuffer ->
5346             pr "  uint32_t %s_len;\n" name;
5347             pr "  char *%s;\n" name
5348         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5349         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5350         | name, FInt32 -> pr "  int32_t %s;\n" name
5351         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5352         | name, FInt64 -> pr "  int64_t %s;\n" name
5353         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5354       ) cols;
5355       pr "};\n";
5356       pr "\n";
5357       pr "struct guestfs_%s_list {\n" typ;
5358       pr "  uint32_t len;\n";
5359       pr "  struct guestfs_%s *val;\n" typ;
5360       pr "};\n";
5361       pr "\n";
5362       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5363       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5364       pr "\n"
5365   ) structs
5366
5367 (* Generate the guestfs-actions.h file. *)
5368 and generate_actions_h () =
5369   generate_header CStyle LGPLv2plus;
5370   List.iter (
5371     fun (shortname, style, _, _, _, _, _) ->
5372       let name = "guestfs_" ^ shortname in
5373       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5374         name style
5375   ) all_functions
5376
5377 (* Generate the guestfs-internal-actions.h file. *)
5378 and generate_internal_actions_h () =
5379   generate_header CStyle LGPLv2plus;
5380   List.iter (
5381     fun (shortname, style, _, _, _, _, _) ->
5382       let name = "guestfs__" ^ shortname in
5383       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5384         name style
5385   ) non_daemon_functions
5386
5387 (* Generate the client-side dispatch stubs. *)
5388 and generate_client_actions () =
5389   generate_header CStyle LGPLv2plus;
5390
5391   pr "\
5392 #include <stdio.h>
5393 #include <stdlib.h>
5394 #include <stdint.h>
5395 #include <inttypes.h>
5396
5397 #include \"guestfs.h\"
5398 #include \"guestfs-internal.h\"
5399 #include \"guestfs-internal-actions.h\"
5400 #include \"guestfs_protocol.h\"
5401
5402 #define error guestfs_error
5403 //#define perrorf guestfs_perrorf
5404 #define safe_malloc guestfs_safe_malloc
5405 #define safe_realloc guestfs_safe_realloc
5406 //#define safe_strdup guestfs_safe_strdup
5407 #define safe_memdup guestfs_safe_memdup
5408
5409 /* Check the return message from a call for validity. */
5410 static int
5411 check_reply_header (guestfs_h *g,
5412                     const struct guestfs_message_header *hdr,
5413                     unsigned int proc_nr, unsigned int serial)
5414 {
5415   if (hdr->prog != GUESTFS_PROGRAM) {
5416     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5417     return -1;
5418   }
5419   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5420     error (g, \"wrong protocol version (%%d/%%d)\",
5421            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5422     return -1;
5423   }
5424   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5425     error (g, \"unexpected message direction (%%d/%%d)\",
5426            hdr->direction, GUESTFS_DIRECTION_REPLY);
5427     return -1;
5428   }
5429   if (hdr->proc != proc_nr) {
5430     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5431     return -1;
5432   }
5433   if (hdr->serial != serial) {
5434     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5435     return -1;
5436   }
5437
5438   return 0;
5439 }
5440
5441 /* Check we are in the right state to run a high-level action. */
5442 static int
5443 check_state (guestfs_h *g, const char *caller)
5444 {
5445   if (!guestfs__is_ready (g)) {
5446     if (guestfs__is_config (g) || guestfs__is_launching (g))
5447       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5448         caller);
5449     else
5450       error (g, \"%%s called from the wrong state, %%d != READY\",
5451         caller, guestfs__get_state (g));
5452     return -1;
5453   }
5454   return 0;
5455 }
5456
5457 ";
5458
5459   (* Generate code to generate guestfish call traces. *)
5460   let trace_call shortname style =
5461     pr "  if (guestfs__get_trace (g)) {\n";
5462
5463     let needs_i =
5464       List.exists (function
5465                    | StringList _ | DeviceList _ -> true
5466                    | _ -> false) (snd style) in
5467     if needs_i then (
5468       pr "    int i;\n";
5469       pr "\n"
5470     );
5471
5472     pr "    printf (\"%s\");\n" shortname;
5473     List.iter (
5474       function
5475       | String n                        (* strings *)
5476       | Device n
5477       | Pathname n
5478       | Dev_or_Path n
5479       | FileIn n
5480       | FileOut n ->
5481           (* guestfish doesn't support string escaping, so neither do we *)
5482           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5483       | OptString n ->                  (* string option *)
5484           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5485           pr "    else printf (\" null\");\n"
5486       | StringList n
5487       | DeviceList n ->                 (* string list *)
5488           pr "    putchar (' ');\n";
5489           pr "    putchar ('\"');\n";
5490           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5491           pr "      if (i > 0) putchar (' ');\n";
5492           pr "      fputs (%s[i], stdout);\n" n;
5493           pr "    }\n";
5494           pr "    putchar ('\"');\n";
5495       | Bool n ->                       (* boolean *)
5496           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5497       | Int n ->                        (* int *)
5498           pr "    printf (\" %%d\", %s);\n" n
5499       | Int64 n ->
5500           pr "    printf (\" %%\" PRIi64, %s);\n" n
5501     ) (snd style);
5502     pr "    putchar ('\\n');\n";
5503     pr "  }\n";
5504     pr "\n";
5505   in
5506
5507   (* For non-daemon functions, generate a wrapper around each function. *)
5508   List.iter (
5509     fun (shortname, style, _, _, _, _, _) ->
5510       let name = "guestfs_" ^ shortname in
5511
5512       generate_prototype ~extern:false ~semicolon:false ~newline:true
5513         ~handle:"g" name style;
5514       pr "{\n";
5515       trace_call shortname style;
5516       pr "  return guestfs__%s " shortname;
5517       generate_c_call_args ~handle:"g" style;
5518       pr ";\n";
5519       pr "}\n";
5520       pr "\n"
5521   ) non_daemon_functions;
5522
5523   (* Client-side stubs for each function. *)
5524   List.iter (
5525     fun (shortname, style, _, _, _, _, _) ->
5526       let name = "guestfs_" ^ shortname in
5527
5528       (* Generate the action stub. *)
5529       generate_prototype ~extern:false ~semicolon:false ~newline:true
5530         ~handle:"g" name style;
5531
5532       let error_code =
5533         match fst style with
5534         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5535         | RConstString _ | RConstOptString _ ->
5536             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5537         | RString _ | RStringList _
5538         | RStruct _ | RStructList _
5539         | RHashtable _ | RBufferOut _ ->
5540             "NULL" in
5541
5542       pr "{\n";
5543
5544       (match snd style with
5545        | [] -> ()
5546        | _ -> pr "  struct %s_args args;\n" name
5547       );
5548
5549       pr "  guestfs_message_header hdr;\n";
5550       pr "  guestfs_message_error err;\n";
5551       let has_ret =
5552         match fst style with
5553         | RErr -> false
5554         | RConstString _ | RConstOptString _ ->
5555             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5556         | RInt _ | RInt64 _
5557         | RBool _ | RString _ | RStringList _
5558         | RStruct _ | RStructList _
5559         | RHashtable _ | RBufferOut _ ->
5560             pr "  struct %s_ret ret;\n" name;
5561             true in
5562
5563       pr "  int serial;\n";
5564       pr "  int r;\n";
5565       pr "\n";
5566       trace_call shortname style;
5567       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5568       pr "  guestfs___set_busy (g);\n";
5569       pr "\n";
5570
5571       (* Send the main header and arguments. *)
5572       (match snd style with
5573        | [] ->
5574            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5575              (String.uppercase shortname)
5576        | args ->
5577            List.iter (
5578              function
5579              | Pathname n | Device n | Dev_or_Path n | String n ->
5580                  pr "  args.%s = (char *) %s;\n" n n
5581              | OptString n ->
5582                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5583              | StringList n | DeviceList n ->
5584                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5585                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5586              | Bool n ->
5587                  pr "  args.%s = %s;\n" n n
5588              | Int n ->
5589                  pr "  args.%s = %s;\n" n n
5590              | Int64 n ->
5591                  pr "  args.%s = %s;\n" n n
5592              | FileIn _ | FileOut _ -> ()
5593            ) args;
5594            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5595              (String.uppercase shortname);
5596            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5597              name;
5598       );
5599       pr "  if (serial == -1) {\n";
5600       pr "    guestfs___end_busy (g);\n";
5601       pr "    return %s;\n" error_code;
5602       pr "  }\n";
5603       pr "\n";
5604
5605       (* Send any additional files (FileIn) requested. *)
5606       let need_read_reply_label = ref false in
5607       List.iter (
5608         function
5609         | FileIn n ->
5610             pr "  r = guestfs___send_file (g, %s);\n" n;
5611             pr "  if (r == -1) {\n";
5612             pr "    guestfs___end_busy (g);\n";
5613             pr "    return %s;\n" error_code;
5614             pr "  }\n";
5615             pr "  if (r == -2) /* daemon cancelled */\n";
5616             pr "    goto read_reply;\n";
5617             need_read_reply_label := true;
5618             pr "\n";
5619         | _ -> ()
5620       ) (snd style);
5621
5622       (* Wait for the reply from the remote end. *)
5623       if !need_read_reply_label then pr " read_reply:\n";
5624       pr "  memset (&hdr, 0, sizeof hdr);\n";
5625       pr "  memset (&err, 0, sizeof err);\n";
5626       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5627       pr "\n";
5628       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5629       if not has_ret then
5630         pr "NULL, NULL"
5631       else
5632         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5633       pr ");\n";
5634
5635       pr "  if (r == -1) {\n";
5636       pr "    guestfs___end_busy (g);\n";
5637       pr "    return %s;\n" error_code;
5638       pr "  }\n";
5639       pr "\n";
5640
5641       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5642         (String.uppercase shortname);
5643       pr "    guestfs___end_busy (g);\n";
5644       pr "    return %s;\n" error_code;
5645       pr "  }\n";
5646       pr "\n";
5647
5648       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5649       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5650       pr "    free (err.error_message);\n";
5651       pr "    guestfs___end_busy (g);\n";
5652       pr "    return %s;\n" error_code;
5653       pr "  }\n";
5654       pr "\n";
5655
5656       (* Expecting to receive further files (FileOut)? *)
5657       List.iter (
5658         function
5659         | FileOut n ->
5660             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5661             pr "    guestfs___end_busy (g);\n";
5662             pr "    return %s;\n" error_code;
5663             pr "  }\n";
5664             pr "\n";
5665         | _ -> ()
5666       ) (snd style);
5667
5668       pr "  guestfs___end_busy (g);\n";
5669
5670       (match fst style with
5671        | RErr -> pr "  return 0;\n"
5672        | RInt n | RInt64 n | RBool n ->
5673            pr "  return ret.%s;\n" n
5674        | RConstString _ | RConstOptString _ ->
5675            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5676        | RString n ->
5677            pr "  return ret.%s; /* caller will free */\n" n
5678        | RStringList n | RHashtable n ->
5679            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5680            pr "  ret.%s.%s_val =\n" n n;
5681            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5682            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5683              n n;
5684            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5685            pr "  return ret.%s.%s_val;\n" n n
5686        | RStruct (n, _) ->
5687            pr "  /* caller will free this */\n";
5688            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5689        | RStructList (n, _) ->
5690            pr "  /* caller will free this */\n";
5691            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5692        | RBufferOut n ->
5693            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5694            pr "   * _val might be NULL here.  To make the API saner for\n";
5695            pr "   * callers, we turn this case into a unique pointer (using\n";
5696            pr "   * malloc(1)).\n";
5697            pr "   */\n";
5698            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5699            pr "    *size_r = ret.%s.%s_len;\n" n n;
5700            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5701            pr "  } else {\n";
5702            pr "    free (ret.%s.%s_val);\n" n n;
5703            pr "    char *p = safe_malloc (g, 1);\n";
5704            pr "    *size_r = ret.%s.%s_len;\n" n n;
5705            pr "    return p;\n";
5706            pr "  }\n";
5707       );
5708
5709       pr "}\n\n"
5710   ) daemon_functions;
5711
5712   (* Functions to free structures. *)
5713   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5714   pr " * structure format is identical to the XDR format.  See note in\n";
5715   pr " * generator.ml.\n";
5716   pr " */\n";
5717   pr "\n";
5718
5719   List.iter (
5720     fun (typ, _) ->
5721       pr "void\n";
5722       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5723       pr "{\n";
5724       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5725       pr "  free (x);\n";
5726       pr "}\n";
5727       pr "\n";
5728
5729       pr "void\n";
5730       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5731       pr "{\n";
5732       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5733       pr "  free (x);\n";
5734       pr "}\n";
5735       pr "\n";
5736
5737   ) structs;
5738
5739 (* Generate daemon/actions.h. *)
5740 and generate_daemon_actions_h () =
5741   generate_header CStyle GPLv2plus;
5742
5743   pr "#include \"../src/guestfs_protocol.h\"\n";
5744   pr "\n";
5745
5746   List.iter (
5747     fun (name, style, _, _, _, _, _) ->
5748       generate_prototype
5749         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5750         name style;
5751   ) daemon_functions
5752
5753 (* Generate the linker script which controls the visibility of
5754  * symbols in the public ABI and ensures no other symbols get
5755  * exported accidentally.
5756  *)
5757 and generate_linker_script () =
5758   generate_header HashStyle GPLv2plus;
5759
5760   let globals = [
5761     "guestfs_create";
5762     "guestfs_close";
5763     "guestfs_get_error_handler";
5764     "guestfs_get_out_of_memory_handler";
5765     "guestfs_last_error";
5766     "guestfs_set_error_handler";
5767     "guestfs_set_launch_done_callback";
5768     "guestfs_set_log_message_callback";
5769     "guestfs_set_out_of_memory_handler";
5770     "guestfs_set_subprocess_quit_callback";
5771
5772     (* Unofficial parts of the API: the bindings code use these
5773      * functions, so it is useful to export them.
5774      *)
5775     "guestfs_safe_calloc";
5776     "guestfs_safe_malloc";
5777   ] in
5778   let functions =
5779     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5780       all_functions in
5781   let structs =
5782     List.concat (
5783       List.map (fun (typ, _) ->
5784                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5785         structs
5786     ) in
5787   let globals = List.sort compare (globals @ functions @ structs) in
5788
5789   pr "{\n";
5790   pr "    global:\n";
5791   List.iter (pr "        %s;\n") globals;
5792   pr "\n";
5793
5794   pr "    local:\n";
5795   pr "        *;\n";
5796   pr "};\n"
5797
5798 (* Generate the server-side stubs. *)
5799 and generate_daemon_actions () =
5800   generate_header CStyle GPLv2plus;
5801
5802   pr "#include <config.h>\n";
5803   pr "\n";
5804   pr "#include <stdio.h>\n";
5805   pr "#include <stdlib.h>\n";
5806   pr "#include <string.h>\n";
5807   pr "#include <inttypes.h>\n";
5808   pr "#include <rpc/types.h>\n";
5809   pr "#include <rpc/xdr.h>\n";
5810   pr "\n";
5811   pr "#include \"daemon.h\"\n";
5812   pr "#include \"c-ctype.h\"\n";
5813   pr "#include \"../src/guestfs_protocol.h\"\n";
5814   pr "#include \"actions.h\"\n";
5815   pr "\n";
5816
5817   List.iter (
5818     fun (name, style, _, _, _, _, _) ->
5819       (* Generate server-side stubs. *)
5820       pr "static void %s_stub (XDR *xdr_in)\n" name;
5821       pr "{\n";
5822       let error_code =
5823         match fst style with
5824         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5825         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5826         | RBool _ -> pr "  int r;\n"; "-1"
5827         | RConstString _ | RConstOptString _ ->
5828             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5829         | RString _ -> pr "  char *r;\n"; "NULL"
5830         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5831         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5832         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5833         | RBufferOut _ ->
5834             pr "  size_t size = 1;\n";
5835             pr "  char *r;\n";
5836             "NULL" in
5837
5838       (match snd style with
5839        | [] -> ()
5840        | args ->
5841            pr "  struct guestfs_%s_args args;\n" name;
5842            List.iter (
5843              function
5844              | Device n | Dev_or_Path n
5845              | Pathname n
5846              | String n -> ()
5847              | OptString n -> pr "  char *%s;\n" n
5848              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5849              | Bool n -> pr "  int %s;\n" n
5850              | Int n -> pr "  int %s;\n" n
5851              | Int64 n -> pr "  int64_t %s;\n" n
5852              | FileIn _ | FileOut _ -> ()
5853            ) args
5854       );
5855       pr "\n";
5856
5857       (match snd style with
5858        | [] -> ()
5859        | args ->
5860            pr "  memset (&args, 0, sizeof args);\n";
5861            pr "\n";
5862            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5863            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5864            pr "    return;\n";
5865            pr "  }\n";
5866            let pr_args n =
5867              pr "  char *%s = args.%s;\n" n n
5868            in
5869            let pr_list_handling_code n =
5870              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5871              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5872              pr "  if (%s == NULL) {\n" n;
5873              pr "    reply_with_perror (\"realloc\");\n";
5874              pr "    goto done;\n";
5875              pr "  }\n";
5876              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5877              pr "  args.%s.%s_val = %s;\n" n n n;
5878            in
5879            List.iter (
5880              function
5881              | Pathname n ->
5882                  pr_args n;
5883                  pr "  ABS_PATH (%s, goto done);\n" n;
5884              | Device n ->
5885                  pr_args n;
5886                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5887              | Dev_or_Path n ->
5888                  pr_args n;
5889                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5890              | String n -> pr_args n
5891              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5892              | StringList n ->
5893                  pr_list_handling_code n;
5894              | DeviceList n ->
5895                  pr_list_handling_code n;
5896                  pr "  /* Ensure that each is a device,\n";
5897                  pr "   * and perform device name translation. */\n";
5898                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5899                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5900                  pr "  }\n";
5901              | Bool n -> pr "  %s = args.%s;\n" n n
5902              | Int n -> pr "  %s = args.%s;\n" n n
5903              | Int64 n -> pr "  %s = args.%s;\n" n n
5904              | FileIn _ | FileOut _ -> ()
5905            ) args;
5906            pr "\n"
5907       );
5908
5909
5910       (* this is used at least for do_equal *)
5911       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5912         (* Emit NEED_ROOT just once, even when there are two or
5913            more Pathname args *)
5914         pr "  NEED_ROOT (goto done);\n";
5915       );
5916
5917       (* Don't want to call the impl with any FileIn or FileOut
5918        * parameters, since these go "outside" the RPC protocol.
5919        *)
5920       let args' =
5921         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5922           (snd style) in
5923       pr "  r = do_%s " name;
5924       generate_c_call_args (fst style, args');
5925       pr ";\n";
5926
5927       (match fst style with
5928        | RErr | RInt _ | RInt64 _ | RBool _
5929        | RConstString _ | RConstOptString _
5930        | RString _ | RStringList _ | RHashtable _
5931        | RStruct (_, _) | RStructList (_, _) ->
5932            pr "  if (r == %s)\n" error_code;
5933            pr "    /* do_%s has already called reply_with_error */\n" name;
5934            pr "    goto done;\n";
5935            pr "\n"
5936        | RBufferOut _ ->
5937            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5938            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5939            pr "   */\n";
5940            pr "  if (size == 1 && r == %s)\n" error_code;
5941            pr "    /* do_%s has already called reply_with_error */\n" name;
5942            pr "    goto done;\n";
5943            pr "\n"
5944       );
5945
5946       (* If there are any FileOut parameters, then the impl must
5947        * send its own reply.
5948        *)
5949       let no_reply =
5950         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5951       if no_reply then
5952         pr "  /* do_%s has already sent a reply */\n" name
5953       else (
5954         match fst style with
5955         | RErr -> pr "  reply (NULL, NULL);\n"
5956         | RInt n | RInt64 n | RBool n ->
5957             pr "  struct guestfs_%s_ret ret;\n" name;
5958             pr "  ret.%s = r;\n" n;
5959             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5960               name
5961         | RConstString _ | RConstOptString _ ->
5962             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5963         | RString n ->
5964             pr "  struct guestfs_%s_ret ret;\n" name;
5965             pr "  ret.%s = r;\n" n;
5966             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5967               name;
5968             pr "  free (r);\n"
5969         | RStringList n | RHashtable n ->
5970             pr "  struct guestfs_%s_ret ret;\n" name;
5971             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5972             pr "  ret.%s.%s_val = r;\n" n n;
5973             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5974               name;
5975             pr "  free_strings (r);\n"
5976         | RStruct (n, _) ->
5977             pr "  struct guestfs_%s_ret ret;\n" name;
5978             pr "  ret.%s = *r;\n" n;
5979             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5980               name;
5981             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5982               name
5983         | RStructList (n, _) ->
5984             pr "  struct guestfs_%s_ret ret;\n" name;
5985             pr "  ret.%s = *r;\n" n;
5986             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5987               name;
5988             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5989               name
5990         | RBufferOut n ->
5991             pr "  struct guestfs_%s_ret ret;\n" name;
5992             pr "  ret.%s.%s_val = r;\n" n n;
5993             pr "  ret.%s.%s_len = size;\n" n n;
5994             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5995               name;
5996             pr "  free (r);\n"
5997       );
5998
5999       (* Free the args. *)
6000       (match snd style with
6001        | [] ->
6002            pr "done: ;\n";
6003        | _ ->
6004            pr "done:\n";
6005            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6006              name
6007       );
6008
6009       pr "}\n\n";
6010   ) daemon_functions;
6011
6012   (* Dispatch function. *)
6013   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6014   pr "{\n";
6015   pr "  switch (proc_nr) {\n";
6016
6017   List.iter (
6018     fun (name, style, _, _, _, _, _) ->
6019       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6020       pr "      %s_stub (xdr_in);\n" name;
6021       pr "      break;\n"
6022   ) daemon_functions;
6023
6024   pr "    default:\n";
6025   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";
6026   pr "  }\n";
6027   pr "}\n";
6028   pr "\n";
6029
6030   (* LVM columns and tokenization functions. *)
6031   (* XXX This generates crap code.  We should rethink how we
6032    * do this parsing.
6033    *)
6034   List.iter (
6035     function
6036     | typ, cols ->
6037         pr "static const char *lvm_%s_cols = \"%s\";\n"
6038           typ (String.concat "," (List.map fst cols));
6039         pr "\n";
6040
6041         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6042         pr "{\n";
6043         pr "  char *tok, *p, *next;\n";
6044         pr "  int i, j;\n";
6045         pr "\n";
6046         (*
6047           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6048           pr "\n";
6049         *)
6050         pr "  if (!str) {\n";
6051         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6052         pr "    return -1;\n";
6053         pr "  }\n";
6054         pr "  if (!*str || c_isspace (*str)) {\n";
6055         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6056         pr "    return -1;\n";
6057         pr "  }\n";
6058         pr "  tok = str;\n";
6059         List.iter (
6060           fun (name, coltype) ->
6061             pr "  if (!tok) {\n";
6062             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6063             pr "    return -1;\n";
6064             pr "  }\n";
6065             pr "  p = strchrnul (tok, ',');\n";
6066             pr "  if (*p) next = p+1; else next = NULL;\n";
6067             pr "  *p = '\\0';\n";
6068             (match coltype with
6069              | FString ->
6070                  pr "  r->%s = strdup (tok);\n" name;
6071                  pr "  if (r->%s == NULL) {\n" name;
6072                  pr "    perror (\"strdup\");\n";
6073                  pr "    return -1;\n";
6074                  pr "  }\n"
6075              | FUUID ->
6076                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6077                  pr "    if (tok[j] == '\\0') {\n";
6078                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6079                  pr "      return -1;\n";
6080                  pr "    } else if (tok[j] != '-')\n";
6081                  pr "      r->%s[i++] = tok[j];\n" name;
6082                  pr "  }\n";
6083              | FBytes ->
6084                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6085                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6086                  pr "    return -1;\n";
6087                  pr "  }\n";
6088              | FInt64 ->
6089                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6090                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6091                  pr "    return -1;\n";
6092                  pr "  }\n";
6093              | FOptPercent ->
6094                  pr "  if (tok[0] == '\\0')\n";
6095                  pr "    r->%s = -1;\n" name;
6096                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6097                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6098                  pr "    return -1;\n";
6099                  pr "  }\n";
6100              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6101                  assert false (* can never be an LVM column *)
6102             );
6103             pr "  tok = next;\n";
6104         ) cols;
6105
6106         pr "  if (tok != NULL) {\n";
6107         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6108         pr "    return -1;\n";
6109         pr "  }\n";
6110         pr "  return 0;\n";
6111         pr "}\n";
6112         pr "\n";
6113
6114         pr "guestfs_int_lvm_%s_list *\n" typ;
6115         pr "parse_command_line_%ss (void)\n" typ;
6116         pr "{\n";
6117         pr "  char *out, *err;\n";
6118         pr "  char *p, *pend;\n";
6119         pr "  int r, i;\n";
6120         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6121         pr "  void *newp;\n";
6122         pr "\n";
6123         pr "  ret = malloc (sizeof *ret);\n";
6124         pr "  if (!ret) {\n";
6125         pr "    reply_with_perror (\"malloc\");\n";
6126         pr "    return NULL;\n";
6127         pr "  }\n";
6128         pr "\n";
6129         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6130         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6131         pr "\n";
6132         pr "  r = command (&out, &err,\n";
6133         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
6134         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6135         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6136         pr "  if (r == -1) {\n";
6137         pr "    reply_with_error (\"%%s\", err);\n";
6138         pr "    free (out);\n";
6139         pr "    free (err);\n";
6140         pr "    free (ret);\n";
6141         pr "    return NULL;\n";
6142         pr "  }\n";
6143         pr "\n";
6144         pr "  free (err);\n";
6145         pr "\n";
6146         pr "  /* Tokenize each line of the output. */\n";
6147         pr "  p = out;\n";
6148         pr "  i = 0;\n";
6149         pr "  while (p) {\n";
6150         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6151         pr "    if (pend) {\n";
6152         pr "      *pend = '\\0';\n";
6153         pr "      pend++;\n";
6154         pr "    }\n";
6155         pr "\n";
6156         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6157         pr "      p++;\n";
6158         pr "\n";
6159         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6160         pr "      p = pend;\n";
6161         pr "      continue;\n";
6162         pr "    }\n";
6163         pr "\n";
6164         pr "    /* Allocate some space to store this next entry. */\n";
6165         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6166         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6167         pr "    if (newp == NULL) {\n";
6168         pr "      reply_with_perror (\"realloc\");\n";
6169         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6170         pr "      free (ret);\n";
6171         pr "      free (out);\n";
6172         pr "      return NULL;\n";
6173         pr "    }\n";
6174         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6175         pr "\n";
6176         pr "    /* Tokenize the next entry. */\n";
6177         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6178         pr "    if (r == -1) {\n";
6179         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6180         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6181         pr "      free (ret);\n";
6182         pr "      free (out);\n";
6183         pr "      return NULL;\n";
6184         pr "    }\n";
6185         pr "\n";
6186         pr "    ++i;\n";
6187         pr "    p = pend;\n";
6188         pr "  }\n";
6189         pr "\n";
6190         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6191         pr "\n";
6192         pr "  free (out);\n";
6193         pr "  return ret;\n";
6194         pr "}\n"
6195
6196   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6197
6198 (* Generate a list of function names, for debugging in the daemon.. *)
6199 and generate_daemon_names () =
6200   generate_header CStyle GPLv2plus;
6201
6202   pr "#include <config.h>\n";
6203   pr "\n";
6204   pr "#include \"daemon.h\"\n";
6205   pr "\n";
6206
6207   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6208   pr "const char *function_names[] = {\n";
6209   List.iter (
6210     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6211   ) daemon_functions;
6212   pr "};\n";
6213
6214 (* Generate the optional groups for the daemon to implement
6215  * guestfs_available.
6216  *)
6217 and generate_daemon_optgroups_c () =
6218   generate_header CStyle GPLv2plus;
6219
6220   pr "#include <config.h>\n";
6221   pr "\n";
6222   pr "#include \"daemon.h\"\n";
6223   pr "#include \"optgroups.h\"\n";
6224   pr "\n";
6225
6226   pr "struct optgroup optgroups[] = {\n";
6227   List.iter (
6228     fun (group, _) ->
6229       pr "  { \"%s\", optgroup_%s_available },\n" group group
6230   ) optgroups;
6231   pr "  { NULL, NULL }\n";
6232   pr "};\n"
6233
6234 and generate_daemon_optgroups_h () =
6235   generate_header CStyle GPLv2plus;
6236
6237   List.iter (
6238     fun (group, _) ->
6239       pr "extern int optgroup_%s_available (void);\n" group
6240   ) optgroups
6241
6242 (* Generate the tests. *)
6243 and generate_tests () =
6244   generate_header CStyle GPLv2plus;
6245
6246   pr "\
6247 #include <stdio.h>
6248 #include <stdlib.h>
6249 #include <string.h>
6250 #include <unistd.h>
6251 #include <sys/types.h>
6252 #include <fcntl.h>
6253
6254 #include \"guestfs.h\"
6255 #include \"guestfs-internal.h\"
6256
6257 static guestfs_h *g;
6258 static int suppress_error = 0;
6259
6260 static void print_error (guestfs_h *g, void *data, const char *msg)
6261 {
6262   if (!suppress_error)
6263     fprintf (stderr, \"%%s\\n\", msg);
6264 }
6265
6266 /* FIXME: nearly identical code appears in fish.c */
6267 static void print_strings (char *const *argv)
6268 {
6269   int argc;
6270
6271   for (argc = 0; argv[argc] != NULL; ++argc)
6272     printf (\"\\t%%s\\n\", argv[argc]);
6273 }
6274
6275 /*
6276 static void print_table (char const *const *argv)
6277 {
6278   int i;
6279
6280   for (i = 0; argv[i] != NULL; i += 2)
6281     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6282 }
6283 */
6284
6285 ";
6286
6287   (* Generate a list of commands which are not tested anywhere. *)
6288   pr "static void no_test_warnings (void)\n";
6289   pr "{\n";
6290
6291   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6292   List.iter (
6293     fun (_, _, _, _, tests, _, _) ->
6294       let tests = filter_map (
6295         function
6296         | (_, (Always|If _|Unless _), test) -> Some test
6297         | (_, Disabled, _) -> None
6298       ) tests in
6299       let seq = List.concat (List.map seq_of_test tests) in
6300       let cmds_tested = List.map List.hd seq in
6301       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6302   ) all_functions;
6303
6304   List.iter (
6305     fun (name, _, _, _, _, _, _) ->
6306       if not (Hashtbl.mem hash name) then
6307         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6308   ) all_functions;
6309
6310   pr "}\n";
6311   pr "\n";
6312
6313   (* Generate the actual tests.  Note that we generate the tests
6314    * in reverse order, deliberately, so that (in general) the
6315    * newest tests run first.  This makes it quicker and easier to
6316    * debug them.
6317    *)
6318   let test_names =
6319     List.map (
6320       fun (name, _, _, flags, tests, _, _) ->
6321         mapi (generate_one_test name flags) tests
6322     ) (List.rev all_functions) in
6323   let test_names = List.concat test_names in
6324   let nr_tests = List.length test_names in
6325
6326   pr "\
6327 int main (int argc, char *argv[])
6328 {
6329   char c = 0;
6330   unsigned long int n_failed = 0;
6331   const char *filename;
6332   int fd;
6333   int nr_tests, test_num = 0;
6334
6335   setbuf (stdout, NULL);
6336
6337   no_test_warnings ();
6338
6339   g = guestfs_create ();
6340   if (g == NULL) {
6341     printf (\"guestfs_create FAILED\\n\");
6342     exit (EXIT_FAILURE);
6343   }
6344
6345   guestfs_set_error_handler (g, print_error, NULL);
6346
6347   guestfs_set_path (g, \"../appliance\");
6348
6349   filename = \"test1.img\";
6350   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6351   if (fd == -1) {
6352     perror (filename);
6353     exit (EXIT_FAILURE);
6354   }
6355   if (lseek (fd, %d, SEEK_SET) == -1) {
6356     perror (\"lseek\");
6357     close (fd);
6358     unlink (filename);
6359     exit (EXIT_FAILURE);
6360   }
6361   if (write (fd, &c, 1) == -1) {
6362     perror (\"write\");
6363     close (fd);
6364     unlink (filename);
6365     exit (EXIT_FAILURE);
6366   }
6367   if (close (fd) == -1) {
6368     perror (filename);
6369     unlink (filename);
6370     exit (EXIT_FAILURE);
6371   }
6372   if (guestfs_add_drive (g, filename) == -1) {
6373     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6374     exit (EXIT_FAILURE);
6375   }
6376
6377   filename = \"test2.img\";
6378   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6379   if (fd == -1) {
6380     perror (filename);
6381     exit (EXIT_FAILURE);
6382   }
6383   if (lseek (fd, %d, SEEK_SET) == -1) {
6384     perror (\"lseek\");
6385     close (fd);
6386     unlink (filename);
6387     exit (EXIT_FAILURE);
6388   }
6389   if (write (fd, &c, 1) == -1) {
6390     perror (\"write\");
6391     close (fd);
6392     unlink (filename);
6393     exit (EXIT_FAILURE);
6394   }
6395   if (close (fd) == -1) {
6396     perror (filename);
6397     unlink (filename);
6398     exit (EXIT_FAILURE);
6399   }
6400   if (guestfs_add_drive (g, filename) == -1) {
6401     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6402     exit (EXIT_FAILURE);
6403   }
6404
6405   filename = \"test3.img\";
6406   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6407   if (fd == -1) {
6408     perror (filename);
6409     exit (EXIT_FAILURE);
6410   }
6411   if (lseek (fd, %d, SEEK_SET) == -1) {
6412     perror (\"lseek\");
6413     close (fd);
6414     unlink (filename);
6415     exit (EXIT_FAILURE);
6416   }
6417   if (write (fd, &c, 1) == -1) {
6418     perror (\"write\");
6419     close (fd);
6420     unlink (filename);
6421     exit (EXIT_FAILURE);
6422   }
6423   if (close (fd) == -1) {
6424     perror (filename);
6425     unlink (filename);
6426     exit (EXIT_FAILURE);
6427   }
6428   if (guestfs_add_drive (g, filename) == -1) {
6429     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6430     exit (EXIT_FAILURE);
6431   }
6432
6433   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6434     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6435     exit (EXIT_FAILURE);
6436   }
6437
6438   if (guestfs_launch (g) == -1) {
6439     printf (\"guestfs_launch FAILED\\n\");
6440     exit (EXIT_FAILURE);
6441   }
6442
6443   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6444   alarm (600);
6445
6446   /* Cancel previous alarm. */
6447   alarm (0);
6448
6449   nr_tests = %d;
6450
6451 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6452
6453   iteri (
6454     fun i test_name ->
6455       pr "  test_num++;\n";
6456       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6457       pr "  if (%s () == -1) {\n" test_name;
6458       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6459       pr "    n_failed++;\n";
6460       pr "  }\n";
6461   ) test_names;
6462   pr "\n";
6463
6464   pr "  guestfs_close (g);\n";
6465   pr "  unlink (\"test1.img\");\n";
6466   pr "  unlink (\"test2.img\");\n";
6467   pr "  unlink (\"test3.img\");\n";
6468   pr "\n";
6469
6470   pr "  if (n_failed > 0) {\n";
6471   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6472   pr "    exit (EXIT_FAILURE);\n";
6473   pr "  }\n";
6474   pr "\n";
6475
6476   pr "  exit (EXIT_SUCCESS);\n";
6477   pr "}\n"
6478
6479 and generate_one_test name flags i (init, prereq, test) =
6480   let test_name = sprintf "test_%s_%d" name i in
6481
6482   pr "\
6483 static int %s_skip (void)
6484 {
6485   const char *str;
6486
6487   str = getenv (\"TEST_ONLY\");
6488   if (str)
6489     return strstr (str, \"%s\") == NULL;
6490   str = getenv (\"SKIP_%s\");
6491   if (str && STREQ (str, \"1\")) return 1;
6492   str = getenv (\"SKIP_TEST_%s\");
6493   if (str && STREQ (str, \"1\")) return 1;
6494   return 0;
6495 }
6496
6497 " test_name name (String.uppercase test_name) (String.uppercase name);
6498
6499   (match prereq with
6500    | Disabled | Always -> ()
6501    | If code | Unless code ->
6502        pr "static int %s_prereq (void)\n" test_name;
6503        pr "{\n";
6504        pr "  %s\n" code;
6505        pr "}\n";
6506        pr "\n";
6507   );
6508
6509   pr "\
6510 static int %s (void)
6511 {
6512   if (%s_skip ()) {
6513     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6514     return 0;
6515   }
6516
6517 " test_name test_name test_name;
6518
6519   (* Optional functions should only be tested if the relevant
6520    * support is available in the daemon.
6521    *)
6522   List.iter (
6523     function
6524     | Optional group ->
6525         pr "  {\n";
6526         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6527         pr "    int r;\n";
6528         pr "    suppress_error = 1;\n";
6529         pr "    r = guestfs_available (g, (char **) groups);\n";
6530         pr "    suppress_error = 0;\n";
6531         pr "    if (r == -1) {\n";
6532         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6533         pr "      return 0;\n";
6534         pr "    }\n";
6535         pr "  }\n";
6536     | _ -> ()
6537   ) flags;
6538
6539   (match prereq with
6540    | Disabled ->
6541        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6542    | If _ ->
6543        pr "  if (! %s_prereq ()) {\n" test_name;
6544        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6545        pr "    return 0;\n";
6546        pr "  }\n";
6547        pr "\n";
6548        generate_one_test_body name i test_name init test;
6549    | Unless _ ->
6550        pr "  if (%s_prereq ()) {\n" test_name;
6551        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6552        pr "    return 0;\n";
6553        pr "  }\n";
6554        pr "\n";
6555        generate_one_test_body name i test_name init test;
6556    | Always ->
6557        generate_one_test_body name i test_name init test
6558   );
6559
6560   pr "  return 0;\n";
6561   pr "}\n";
6562   pr "\n";
6563   test_name
6564
6565 and generate_one_test_body name i test_name init test =
6566   (match init with
6567    | InitNone (* XXX at some point, InitNone and InitEmpty became
6568                * folded together as the same thing.  Really we should
6569                * make InitNone do nothing at all, but the tests may
6570                * need to be checked to make sure this is OK.
6571                *)
6572    | InitEmpty ->
6573        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6574        List.iter (generate_test_command_call test_name)
6575          [["blockdev_setrw"; "/dev/sda"];
6576           ["umount_all"];
6577           ["lvm_remove_all"]]
6578    | InitPartition ->
6579        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6580        List.iter (generate_test_command_call test_name)
6581          [["blockdev_setrw"; "/dev/sda"];
6582           ["umount_all"];
6583           ["lvm_remove_all"];
6584           ["part_disk"; "/dev/sda"; "mbr"]]
6585    | InitBasicFS ->
6586        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6587        List.iter (generate_test_command_call test_name)
6588          [["blockdev_setrw"; "/dev/sda"];
6589           ["umount_all"];
6590           ["lvm_remove_all"];
6591           ["part_disk"; "/dev/sda"; "mbr"];
6592           ["mkfs"; "ext2"; "/dev/sda1"];
6593           ["mount_options"; ""; "/dev/sda1"; "/"]]
6594    | InitBasicFSonLVM ->
6595        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6596          test_name;
6597        List.iter (generate_test_command_call test_name)
6598          [["blockdev_setrw"; "/dev/sda"];
6599           ["umount_all"];
6600           ["lvm_remove_all"];
6601           ["part_disk"; "/dev/sda"; "mbr"];
6602           ["pvcreate"; "/dev/sda1"];
6603           ["vgcreate"; "VG"; "/dev/sda1"];
6604           ["lvcreate"; "LV"; "VG"; "8"];
6605           ["mkfs"; "ext2"; "/dev/VG/LV"];
6606           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6607    | InitISOFS ->
6608        pr "  /* InitISOFS for %s */\n" test_name;
6609        List.iter (generate_test_command_call test_name)
6610          [["blockdev_setrw"; "/dev/sda"];
6611           ["umount_all"];
6612           ["lvm_remove_all"];
6613           ["mount_ro"; "/dev/sdd"; "/"]]
6614   );
6615
6616   let get_seq_last = function
6617     | [] ->
6618         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6619           test_name
6620     | seq ->
6621         let seq = List.rev seq in
6622         List.rev (List.tl seq), List.hd seq
6623   in
6624
6625   match test with
6626   | TestRun seq ->
6627       pr "  /* TestRun for %s (%d) */\n" name i;
6628       List.iter (generate_test_command_call test_name) seq
6629   | TestOutput (seq, expected) ->
6630       pr "  /* TestOutput for %s (%d) */\n" name i;
6631       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6632       let seq, last = get_seq_last seq in
6633       let test () =
6634         pr "    if (STRNEQ (r, expected)) {\n";
6635         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6636         pr "      return -1;\n";
6637         pr "    }\n"
6638       in
6639       List.iter (generate_test_command_call test_name) seq;
6640       generate_test_command_call ~test test_name last
6641   | TestOutputList (seq, expected) ->
6642       pr "  /* TestOutputList for %s (%d) */\n" name i;
6643       let seq, last = get_seq_last seq in
6644       let test () =
6645         iteri (
6646           fun i str ->
6647             pr "    if (!r[%d]) {\n" i;
6648             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6649             pr "      print_strings (r);\n";
6650             pr "      return -1;\n";
6651             pr "    }\n";
6652             pr "    {\n";
6653             pr "      const char *expected = \"%s\";\n" (c_quote str);
6654             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6655             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6656             pr "        return -1;\n";
6657             pr "      }\n";
6658             pr "    }\n"
6659         ) expected;
6660         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6661         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6662           test_name;
6663         pr "      print_strings (r);\n";
6664         pr "      return -1;\n";
6665         pr "    }\n"
6666       in
6667       List.iter (generate_test_command_call test_name) seq;
6668       generate_test_command_call ~test test_name last
6669   | TestOutputListOfDevices (seq, expected) ->
6670       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6671       let seq, last = get_seq_last seq in
6672       let test () =
6673         iteri (
6674           fun i str ->
6675             pr "    if (!r[%d]) {\n" i;
6676             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6677             pr "      print_strings (r);\n";
6678             pr "      return -1;\n";
6679             pr "    }\n";
6680             pr "    {\n";
6681             pr "      const char *expected = \"%s\";\n" (c_quote str);
6682             pr "      r[%d][5] = 's';\n" i;
6683             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6684             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6685             pr "        return -1;\n";
6686             pr "      }\n";
6687             pr "    }\n"
6688         ) expected;
6689         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6690         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6691           test_name;
6692         pr "      print_strings (r);\n";
6693         pr "      return -1;\n";
6694         pr "    }\n"
6695       in
6696       List.iter (generate_test_command_call test_name) seq;
6697       generate_test_command_call ~test test_name last
6698   | TestOutputInt (seq, expected) ->
6699       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6700       let seq, last = get_seq_last seq in
6701       let test () =
6702         pr "    if (r != %d) {\n" expected;
6703         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6704           test_name expected;
6705         pr "               (int) r);\n";
6706         pr "      return -1;\n";
6707         pr "    }\n"
6708       in
6709       List.iter (generate_test_command_call test_name) seq;
6710       generate_test_command_call ~test test_name last
6711   | TestOutputIntOp (seq, op, expected) ->
6712       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6713       let seq, last = get_seq_last seq in
6714       let test () =
6715         pr "    if (! (r %s %d)) {\n" op expected;
6716         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6717           test_name op expected;
6718         pr "               (int) r);\n";
6719         pr "      return -1;\n";
6720         pr "    }\n"
6721       in
6722       List.iter (generate_test_command_call test_name) seq;
6723       generate_test_command_call ~test test_name last
6724   | TestOutputTrue seq ->
6725       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6726       let seq, last = get_seq_last seq in
6727       let test () =
6728         pr "    if (!r) {\n";
6729         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6730           test_name;
6731         pr "      return -1;\n";
6732         pr "    }\n"
6733       in
6734       List.iter (generate_test_command_call test_name) seq;
6735       generate_test_command_call ~test test_name last
6736   | TestOutputFalse seq ->
6737       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6738       let seq, last = get_seq_last seq in
6739       let test () =
6740         pr "    if (r) {\n";
6741         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6742           test_name;
6743         pr "      return -1;\n";
6744         pr "    }\n"
6745       in
6746       List.iter (generate_test_command_call test_name) seq;
6747       generate_test_command_call ~test test_name last
6748   | TestOutputLength (seq, expected) ->
6749       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6750       let seq, last = get_seq_last seq in
6751       let test () =
6752         pr "    int j;\n";
6753         pr "    for (j = 0; j < %d; ++j)\n" expected;
6754         pr "      if (r[j] == NULL) {\n";
6755         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6756           test_name;
6757         pr "        print_strings (r);\n";
6758         pr "        return -1;\n";
6759         pr "      }\n";
6760         pr "    if (r[j] != NULL) {\n";
6761         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6762           test_name;
6763         pr "      print_strings (r);\n";
6764         pr "      return -1;\n";
6765         pr "    }\n"
6766       in
6767       List.iter (generate_test_command_call test_name) seq;
6768       generate_test_command_call ~test test_name last
6769   | TestOutputBuffer (seq, expected) ->
6770       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6771       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6772       let seq, last = get_seq_last seq in
6773       let len = String.length expected in
6774       let test () =
6775         pr "    if (size != %d) {\n" len;
6776         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6777         pr "      return -1;\n";
6778         pr "    }\n";
6779         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6780         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6781         pr "      return -1;\n";
6782         pr "    }\n"
6783       in
6784       List.iter (generate_test_command_call test_name) seq;
6785       generate_test_command_call ~test test_name last
6786   | TestOutputStruct (seq, checks) ->
6787       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6788       let seq, last = get_seq_last seq in
6789       let test () =
6790         List.iter (
6791           function
6792           | CompareWithInt (field, expected) ->
6793               pr "    if (r->%s != %d) {\n" field expected;
6794               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6795                 test_name field expected;
6796               pr "               (int) r->%s);\n" field;
6797               pr "      return -1;\n";
6798               pr "    }\n"
6799           | CompareWithIntOp (field, op, expected) ->
6800               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6801               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6802                 test_name field op expected;
6803               pr "               (int) r->%s);\n" field;
6804               pr "      return -1;\n";
6805               pr "    }\n"
6806           | CompareWithString (field, expected) ->
6807               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6808               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6809                 test_name field expected;
6810               pr "               r->%s);\n" field;
6811               pr "      return -1;\n";
6812               pr "    }\n"
6813           | CompareFieldsIntEq (field1, field2) ->
6814               pr "    if (r->%s != r->%s) {\n" field1 field2;
6815               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6816                 test_name field1 field2;
6817               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6818               pr "      return -1;\n";
6819               pr "    }\n"
6820           | CompareFieldsStrEq (field1, field2) ->
6821               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6822               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6823                 test_name field1 field2;
6824               pr "               r->%s, r->%s);\n" field1 field2;
6825               pr "      return -1;\n";
6826               pr "    }\n"
6827         ) checks
6828       in
6829       List.iter (generate_test_command_call test_name) seq;
6830       generate_test_command_call ~test test_name last
6831   | TestLastFail seq ->
6832       pr "  /* TestLastFail for %s (%d) */\n" name i;
6833       let seq, last = get_seq_last seq in
6834       List.iter (generate_test_command_call test_name) seq;
6835       generate_test_command_call test_name ~expect_error:true last
6836
6837 (* Generate the code to run a command, leaving the result in 'r'.
6838  * If you expect to get an error then you should set expect_error:true.
6839  *)
6840 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6841   match cmd with
6842   | [] -> assert false
6843   | name :: args ->
6844       (* Look up the command to find out what args/ret it has. *)
6845       let style =
6846         try
6847           let _, style, _, _, _, _, _ =
6848             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6849           style
6850         with Not_found ->
6851           failwithf "%s: in test, command %s was not found" test_name name in
6852
6853       if List.length (snd style) <> List.length args then
6854         failwithf "%s: in test, wrong number of args given to %s"
6855           test_name name;
6856
6857       pr "  {\n";
6858
6859       List.iter (
6860         function
6861         | OptString n, "NULL" -> ()
6862         | Pathname n, arg
6863         | Device n, arg
6864         | Dev_or_Path n, arg
6865         | String n, arg
6866         | OptString n, arg ->
6867             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6868         | Int _, _
6869         | Int64 _, _
6870         | Bool _, _
6871         | FileIn _, _ | FileOut _, _ -> ()
6872         | StringList n, "" | DeviceList n, "" ->
6873             pr "    const char *const %s[1] = { NULL };\n" n
6874         | StringList n, arg | DeviceList n, arg ->
6875             let strs = string_split " " arg in
6876             iteri (
6877               fun i str ->
6878                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6879             ) strs;
6880             pr "    const char *const %s[] = {\n" n;
6881             iteri (
6882               fun i _ -> pr "      %s_%d,\n" n i
6883             ) strs;
6884             pr "      NULL\n";
6885             pr "    };\n";
6886       ) (List.combine (snd style) args);
6887
6888       let error_code =
6889         match fst style with
6890         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6891         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6892         | RConstString _ | RConstOptString _ ->
6893             pr "    const char *r;\n"; "NULL"
6894         | RString _ -> pr "    char *r;\n"; "NULL"
6895         | RStringList _ | RHashtable _ ->
6896             pr "    char **r;\n";
6897             pr "    int i;\n";
6898             "NULL"
6899         | RStruct (_, typ) ->
6900             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6901         | RStructList (_, typ) ->
6902             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6903         | RBufferOut _ ->
6904             pr "    char *r;\n";
6905             pr "    size_t size;\n";
6906             "NULL" in
6907
6908       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6909       pr "    r = guestfs_%s (g" name;
6910
6911       (* Generate the parameters. *)
6912       List.iter (
6913         function
6914         | OptString _, "NULL" -> pr ", NULL"
6915         | Pathname n, _
6916         | Device n, _ | Dev_or_Path n, _
6917         | String n, _
6918         | OptString n, _ ->
6919             pr ", %s" n
6920         | FileIn _, arg | FileOut _, arg ->
6921             pr ", \"%s\"" (c_quote arg)
6922         | StringList n, _ | DeviceList n, _ ->
6923             pr ", (char **) %s" n
6924         | Int _, arg ->
6925             let i =
6926               try int_of_string arg
6927               with Failure "int_of_string" ->
6928                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6929             pr ", %d" i
6930         | Int64 _, arg ->
6931             let i =
6932               try Int64.of_string arg
6933               with Failure "int_of_string" ->
6934                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6935             pr ", %Ld" i
6936         | Bool _, arg ->
6937             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6938       ) (List.combine (snd style) args);
6939
6940       (match fst style with
6941        | RBufferOut _ -> pr ", &size"
6942        | _ -> ()
6943       );
6944
6945       pr ");\n";
6946
6947       if not expect_error then
6948         pr "    if (r == %s)\n" error_code
6949       else
6950         pr "    if (r != %s)\n" error_code;
6951       pr "      return -1;\n";
6952
6953       (* Insert the test code. *)
6954       (match test with
6955        | None -> ()
6956        | Some f -> f ()
6957       );
6958
6959       (match fst style with
6960        | RErr | RInt _ | RInt64 _ | RBool _
6961        | RConstString _ | RConstOptString _ -> ()
6962        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6963        | RStringList _ | RHashtable _ ->
6964            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6965            pr "      free (r[i]);\n";
6966            pr "    free (r);\n"
6967        | RStruct (_, typ) ->
6968            pr "    guestfs_free_%s (r);\n" typ
6969        | RStructList (_, typ) ->
6970            pr "    guestfs_free_%s_list (r);\n" typ
6971       );
6972
6973       pr "  }\n"
6974
6975 and c_quote str =
6976   let str = replace_str str "\r" "\\r" in
6977   let str = replace_str str "\n" "\\n" in
6978   let str = replace_str str "\t" "\\t" in
6979   let str = replace_str str "\000" "\\0" in
6980   str
6981
6982 (* Generate a lot of different functions for guestfish. *)
6983 and generate_fish_cmds () =
6984   generate_header CStyle GPLv2plus;
6985
6986   let all_functions =
6987     List.filter (
6988       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6989     ) all_functions in
6990   let all_functions_sorted =
6991     List.filter (
6992       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6993     ) all_functions_sorted in
6994
6995   pr "#include <config.h>\n";
6996   pr "\n";
6997   pr "#include <stdio.h>\n";
6998   pr "#include <stdlib.h>\n";
6999   pr "#include <string.h>\n";
7000   pr "#include <inttypes.h>\n";
7001   pr "\n";
7002   pr "#include <guestfs.h>\n";
7003   pr "#include \"c-ctype.h\"\n";
7004   pr "#include \"full-write.h\"\n";
7005   pr "#include \"xstrtol.h\"\n";
7006   pr "#include \"fish.h\"\n";
7007   pr "\n";
7008
7009   (* list_commands function, which implements guestfish -h *)
7010   pr "void list_commands (void)\n";
7011   pr "{\n";
7012   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7013   pr "  list_builtin_commands ();\n";
7014   List.iter (
7015     fun (name, _, _, flags, _, shortdesc, _) ->
7016       let name = replace_char name '_' '-' in
7017       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7018         name shortdesc
7019   ) all_functions_sorted;
7020   pr "  printf (\"    %%s\\n\",";
7021   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7022   pr "}\n";
7023   pr "\n";
7024
7025   (* display_command function, which implements guestfish -h cmd *)
7026   pr "void display_command (const char *cmd)\n";
7027   pr "{\n";
7028   List.iter (
7029     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7030       let name2 = replace_char name '_' '-' in
7031       let alias =
7032         try find_map (function FishAlias n -> Some n | _ -> None) flags
7033         with Not_found -> name in
7034       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7035       let synopsis =
7036         match snd style with
7037         | [] -> name2
7038         | args ->
7039             sprintf "%s %s"
7040               name2 (String.concat " " (List.map name_of_argt args)) in
7041
7042       let warnings =
7043         if List.mem ProtocolLimitWarning flags then
7044           ("\n\n" ^ protocol_limit_warning)
7045         else "" in
7046
7047       (* For DangerWillRobinson commands, we should probably have
7048        * guestfish prompt before allowing you to use them (especially
7049        * in interactive mode). XXX
7050        *)
7051       let warnings =
7052         warnings ^
7053           if List.mem DangerWillRobinson flags then
7054             ("\n\n" ^ danger_will_robinson)
7055           else "" in
7056
7057       let warnings =
7058         warnings ^
7059           match deprecation_notice flags with
7060           | None -> ""
7061           | Some txt -> "\n\n" ^ txt in
7062
7063       let describe_alias =
7064         if name <> alias then
7065           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7066         else "" in
7067
7068       pr "  if (";
7069       pr "STRCASEEQ (cmd, \"%s\")" name;
7070       if name <> name2 then
7071         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7072       if name <> alias then
7073         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7074       pr ")\n";
7075       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7076         name2 shortdesc
7077         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7078          "=head1 DESCRIPTION\n\n" ^
7079          longdesc ^ warnings ^ describe_alias);
7080       pr "  else\n"
7081   ) all_functions;
7082   pr "    display_builtin_command (cmd);\n";
7083   pr "}\n";
7084   pr "\n";
7085
7086   let emit_print_list_function typ =
7087     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7088       typ typ typ;
7089     pr "{\n";
7090     pr "  unsigned int i;\n";
7091     pr "\n";
7092     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7093     pr "    printf (\"[%%d] = {\\n\", i);\n";
7094     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7095     pr "    printf (\"}\\n\");\n";
7096     pr "  }\n";
7097     pr "}\n";
7098     pr "\n";
7099   in
7100
7101   (* print_* functions *)
7102   List.iter (
7103     fun (typ, cols) ->
7104       let needs_i =
7105         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7106
7107       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7108       pr "{\n";
7109       if needs_i then (
7110         pr "  unsigned int i;\n";
7111         pr "\n"
7112       );
7113       List.iter (
7114         function
7115         | name, FString ->
7116             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7117         | name, FUUID ->
7118             pr "  printf (\"%%s%s: \", indent);\n" name;
7119             pr "  for (i = 0; i < 32; ++i)\n";
7120             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7121             pr "  printf (\"\\n\");\n"
7122         | name, FBuffer ->
7123             pr "  printf (\"%%s%s: \", indent);\n" name;
7124             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7125             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7126             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7127             pr "    else\n";
7128             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7129             pr "  printf (\"\\n\");\n"
7130         | name, (FUInt64|FBytes) ->
7131             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7132               name typ name
7133         | name, FInt64 ->
7134             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7135               name typ name
7136         | name, FUInt32 ->
7137             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7138               name typ name
7139         | name, FInt32 ->
7140             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7141               name typ name
7142         | name, FChar ->
7143             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7144               name typ name
7145         | name, FOptPercent ->
7146             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7147               typ name name typ name;
7148             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7149       ) cols;
7150       pr "}\n";
7151       pr "\n";
7152   ) structs;
7153
7154   (* Emit a print_TYPE_list function definition only if that function is used. *)
7155   List.iter (
7156     function
7157     | typ, (RStructListOnly | RStructAndList) ->
7158         (* generate the function for typ *)
7159         emit_print_list_function typ
7160     | typ, _ -> () (* empty *)
7161   ) (rstructs_used_by all_functions);
7162
7163   (* Emit a print_TYPE function definition only if that function is used. *)
7164   List.iter (
7165     function
7166     | typ, (RStructOnly | RStructAndList) ->
7167         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7168         pr "{\n";
7169         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7170         pr "}\n";
7171         pr "\n";
7172     | typ, _ -> () (* empty *)
7173   ) (rstructs_used_by all_functions);
7174
7175   (* run_<action> actions *)
7176   List.iter (
7177     fun (name, style, _, flags, _, _, _) ->
7178       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7179       pr "{\n";
7180       (match fst style with
7181        | RErr
7182        | RInt _
7183        | RBool _ -> pr "  int r;\n"
7184        | RInt64 _ -> pr "  int64_t r;\n"
7185        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7186        | RString _ -> pr "  char *r;\n"
7187        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7188        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7189        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7190        | RBufferOut _ ->
7191            pr "  char *r;\n";
7192            pr "  size_t size;\n";
7193       );
7194       List.iter (
7195         function
7196         | Device n
7197         | String n
7198         | OptString n
7199         | FileIn n
7200         | FileOut n -> pr "  const char *%s;\n" n
7201         | Pathname n
7202         | Dev_or_Path n -> pr "  char *%s;\n" n
7203         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7204         | Bool n -> pr "  int %s;\n" n
7205         | Int n -> pr "  int %s;\n" n
7206         | Int64 n -> pr "  int64_t %s;\n" n
7207       ) (snd style);
7208
7209       (* Check and convert parameters. *)
7210       let argc_expected = List.length (snd style) in
7211       pr "  if (argc != %d) {\n" argc_expected;
7212       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7213         argc_expected;
7214       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7215       pr "    return -1;\n";
7216       pr "  }\n";
7217
7218       let parse_integer fn fntyp rtyp range name i =
7219         pr "  {\n";
7220         pr "    strtol_error xerr;\n";
7221         pr "    %s r;\n" fntyp;
7222         pr "\n";
7223         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7224         pr "    if (xerr != LONGINT_OK) {\n";
7225         pr "      fprintf (stderr,\n";
7226         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7227         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7228         pr "      return -1;\n";
7229         pr "    }\n";
7230         (match range with
7231          | None -> ()
7232          | Some (min, max, comment) ->
7233              pr "    /* %s */\n" comment;
7234              pr "    if (r < %s || r > %s) {\n" min max;
7235              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7236                name;
7237              pr "      return -1;\n";
7238              pr "    }\n";
7239              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7240         );
7241         pr "    %s = r;\n" name;
7242         pr "  }\n";
7243       in
7244
7245       iteri (
7246         fun i ->
7247           function
7248           | Device name
7249           | String name ->
7250               pr "  %s = argv[%d];\n" name i
7251           | Pathname name
7252           | Dev_or_Path name ->
7253               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7254               pr "  if (%s == NULL) return -1;\n" name
7255           | OptString name ->
7256               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7257                 name i i
7258           | FileIn name ->
7259               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7260                 name i i
7261           | FileOut name ->
7262               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7263                 name i i
7264           | StringList name | DeviceList name ->
7265               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7266               pr "  if (%s == NULL) return -1;\n" name;
7267           | Bool name ->
7268               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7269           | Int name ->
7270               let range =
7271                 let min = "(-(2LL<<30))"
7272                 and max = "((2LL<<30)-1)"
7273                 and comment =
7274                   "The Int type in the generator is a signed 31 bit int." in
7275                 Some (min, max, comment) in
7276               parse_integer "xstrtoll" "long long" "int" range name i
7277           | Int64 name ->
7278               parse_integer "xstrtoll" "long long" "int64_t" None name i
7279       ) (snd style);
7280
7281       (* Call C API function. *)
7282       let fn =
7283         try find_map (function FishAction n -> Some n | _ -> None) flags
7284         with Not_found -> sprintf "guestfs_%s" name in
7285       pr "  r = %s " fn;
7286       generate_c_call_args ~handle:"g" style;
7287       pr ";\n";
7288
7289       List.iter (
7290         function
7291         | Device name | String name
7292         | OptString name | FileIn name | FileOut name | Bool name
7293         | Int name | Int64 name -> ()
7294         | Pathname name | Dev_or_Path name ->
7295             pr "  free (%s);\n" name
7296         | StringList name | DeviceList name ->
7297             pr "  free_strings (%s);\n" name
7298       ) (snd style);
7299
7300       (* Check return value for errors and display command results. *)
7301       (match fst style with
7302        | RErr -> pr "  return r;\n"
7303        | RInt _ ->
7304            pr "  if (r == -1) return -1;\n";
7305            pr "  printf (\"%%d\\n\", r);\n";
7306            pr "  return 0;\n"
7307        | RInt64 _ ->
7308            pr "  if (r == -1) return -1;\n";
7309            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7310            pr "  return 0;\n"
7311        | RBool _ ->
7312            pr "  if (r == -1) return -1;\n";
7313            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7314            pr "  return 0;\n"
7315        | RConstString _ ->
7316            pr "  if (r == NULL) return -1;\n";
7317            pr "  printf (\"%%s\\n\", r);\n";
7318            pr "  return 0;\n"
7319        | RConstOptString _ ->
7320            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7321            pr "  return 0;\n"
7322        | RString _ ->
7323            pr "  if (r == NULL) return -1;\n";
7324            pr "  printf (\"%%s\\n\", r);\n";
7325            pr "  free (r);\n";
7326            pr "  return 0;\n"
7327        | RStringList _ ->
7328            pr "  if (r == NULL) return -1;\n";
7329            pr "  print_strings (r);\n";
7330            pr "  free_strings (r);\n";
7331            pr "  return 0;\n"
7332        | RStruct (_, typ) ->
7333            pr "  if (r == NULL) return -1;\n";
7334            pr "  print_%s (r);\n" typ;
7335            pr "  guestfs_free_%s (r);\n" typ;
7336            pr "  return 0;\n"
7337        | RStructList (_, typ) ->
7338            pr "  if (r == NULL) return -1;\n";
7339            pr "  print_%s_list (r);\n" typ;
7340            pr "  guestfs_free_%s_list (r);\n" typ;
7341            pr "  return 0;\n"
7342        | RHashtable _ ->
7343            pr "  if (r == NULL) return -1;\n";
7344            pr "  print_table (r);\n";
7345            pr "  free_strings (r);\n";
7346            pr "  return 0;\n"
7347        | RBufferOut _ ->
7348            pr "  if (r == NULL) return -1;\n";
7349            pr "  if (full_write (1, r, size) != size) {\n";
7350            pr "    perror (\"write\");\n";
7351            pr "    free (r);\n";
7352            pr "    return -1;\n";
7353            pr "  }\n";
7354            pr "  free (r);\n";
7355            pr "  return 0;\n"
7356       );
7357       pr "}\n";
7358       pr "\n"
7359   ) all_functions;
7360
7361   (* run_action function *)
7362   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7363   pr "{\n";
7364   List.iter (
7365     fun (name, _, _, flags, _, _, _) ->
7366       let name2 = replace_char name '_' '-' in
7367       let alias =
7368         try find_map (function FishAlias n -> Some n | _ -> None) flags
7369         with Not_found -> name in
7370       pr "  if (";
7371       pr "STRCASEEQ (cmd, \"%s\")" name;
7372       if name <> name2 then
7373         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7374       if name <> alias then
7375         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7376       pr ")\n";
7377       pr "    return run_%s (cmd, argc, argv);\n" name;
7378       pr "  else\n";
7379   ) all_functions;
7380   pr "    {\n";
7381   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7382   pr "      return -1;\n";
7383   pr "    }\n";
7384   pr "  return 0;\n";
7385   pr "}\n";
7386   pr "\n"
7387
7388 (* Readline completion for guestfish. *)
7389 and generate_fish_completion () =
7390   generate_header CStyle GPLv2plus;
7391
7392   let all_functions =
7393     List.filter (
7394       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7395     ) all_functions in
7396
7397   pr "\
7398 #include <config.h>
7399
7400 #include <stdio.h>
7401 #include <stdlib.h>
7402 #include <string.h>
7403
7404 #ifdef HAVE_LIBREADLINE
7405 #include <readline/readline.h>
7406 #endif
7407
7408 #include \"fish.h\"
7409
7410 #ifdef HAVE_LIBREADLINE
7411
7412 static const char *const commands[] = {
7413   BUILTIN_COMMANDS_FOR_COMPLETION,
7414 ";
7415
7416   (* Get the commands, including the aliases.  They don't need to be
7417    * sorted - the generator() function just does a dumb linear search.
7418    *)
7419   let commands =
7420     List.map (
7421       fun (name, _, _, flags, _, _, _) ->
7422         let name2 = replace_char name '_' '-' in
7423         let alias =
7424           try find_map (function FishAlias n -> Some n | _ -> None) flags
7425           with Not_found -> name in
7426
7427         if name <> alias then [name2; alias] else [name2]
7428     ) all_functions in
7429   let commands = List.flatten commands in
7430
7431   List.iter (pr "  \"%s\",\n") commands;
7432
7433   pr "  NULL
7434 };
7435
7436 static char *
7437 generator (const char *text, int state)
7438 {
7439   static int index, len;
7440   const char *name;
7441
7442   if (!state) {
7443     index = 0;
7444     len = strlen (text);
7445   }
7446
7447   rl_attempted_completion_over = 1;
7448
7449   while ((name = commands[index]) != NULL) {
7450     index++;
7451     if (STRCASEEQLEN (name, text, len))
7452       return strdup (name);
7453   }
7454
7455   return NULL;
7456 }
7457
7458 #endif /* HAVE_LIBREADLINE */
7459
7460 char **do_completion (const char *text, int start, int end)
7461 {
7462   char **matches = NULL;
7463
7464 #ifdef HAVE_LIBREADLINE
7465   rl_completion_append_character = ' ';
7466
7467   if (start == 0)
7468     matches = rl_completion_matches (text, generator);
7469   else if (complete_dest_paths)
7470     matches = rl_completion_matches (text, complete_dest_paths_generator);
7471 #endif
7472
7473   return matches;
7474 }
7475 ";
7476
7477 (* Generate the POD documentation for guestfish. *)
7478 and generate_fish_actions_pod () =
7479   let all_functions_sorted =
7480     List.filter (
7481       fun (_, _, _, flags, _, _, _) ->
7482         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7483     ) all_functions_sorted in
7484
7485   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7486
7487   List.iter (
7488     fun (name, style, _, flags, _, _, longdesc) ->
7489       let longdesc =
7490         Str.global_substitute rex (
7491           fun s ->
7492             let sub =
7493               try Str.matched_group 1 s
7494               with Not_found ->
7495                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7496             "C<" ^ replace_char sub '_' '-' ^ ">"
7497         ) longdesc in
7498       let name = replace_char name '_' '-' in
7499       let alias =
7500         try find_map (function FishAlias n -> Some n | _ -> None) flags
7501         with Not_found -> name in
7502
7503       pr "=head2 %s" name;
7504       if name <> alias then
7505         pr " | %s" alias;
7506       pr "\n";
7507       pr "\n";
7508       pr " %s" name;
7509       List.iter (
7510         function
7511         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7512         | OptString n -> pr " %s" n
7513         | StringList n | DeviceList n -> pr " '%s ...'" n
7514         | Bool _ -> pr " true|false"
7515         | Int n -> pr " %s" n
7516         | Int64 n -> pr " %s" n
7517         | FileIn n | FileOut n -> pr " (%s|-)" n
7518       ) (snd style);
7519       pr "\n";
7520       pr "\n";
7521       pr "%s\n\n" longdesc;
7522
7523       if List.exists (function FileIn _ | FileOut _ -> true
7524                       | _ -> false) (snd style) then
7525         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7526
7527       if List.mem ProtocolLimitWarning flags then
7528         pr "%s\n\n" protocol_limit_warning;
7529
7530       if List.mem DangerWillRobinson flags then
7531         pr "%s\n\n" danger_will_robinson;
7532
7533       match deprecation_notice flags with
7534       | None -> ()
7535       | Some txt -> pr "%s\n\n" txt
7536   ) all_functions_sorted
7537
7538 (* Generate a C function prototype. *)
7539 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7540     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7541     ?(prefix = "")
7542     ?handle name style =
7543   if extern then pr "extern ";
7544   if static then pr "static ";
7545   (match fst style with
7546    | RErr -> pr "int "
7547    | RInt _ -> pr "int "
7548    | RInt64 _ -> pr "int64_t "
7549    | RBool _ -> pr "int "
7550    | RConstString _ | RConstOptString _ -> pr "const char *"
7551    | RString _ | RBufferOut _ -> pr "char *"
7552    | RStringList _ | RHashtable _ -> pr "char **"
7553    | RStruct (_, typ) ->
7554        if not in_daemon then pr "struct guestfs_%s *" typ
7555        else pr "guestfs_int_%s *" typ
7556    | RStructList (_, typ) ->
7557        if not in_daemon then pr "struct guestfs_%s_list *" typ
7558        else pr "guestfs_int_%s_list *" typ
7559   );
7560   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7561   pr "%s%s (" prefix name;
7562   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7563     pr "void"
7564   else (
7565     let comma = ref false in
7566     (match handle with
7567      | None -> ()
7568      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7569     );
7570     let next () =
7571       if !comma then (
7572         if single_line then pr ", " else pr ",\n\t\t"
7573       );
7574       comma := true
7575     in
7576     List.iter (
7577       function
7578       | Pathname n
7579       | Device n | Dev_or_Path n
7580       | String n
7581       | OptString n ->
7582           next ();
7583           pr "const char *%s" n
7584       | StringList n | DeviceList n ->
7585           next ();
7586           pr "char *const *%s" n
7587       | Bool n -> next (); pr "int %s" n
7588       | Int n -> next (); pr "int %s" n
7589       | Int64 n -> next (); pr "int64_t %s" n
7590       | FileIn n
7591       | FileOut n ->
7592           if not in_daemon then (next (); pr "const char *%s" n)
7593     ) (snd style);
7594     if is_RBufferOut then (next (); pr "size_t *size_r");
7595   );
7596   pr ")";
7597   if semicolon then pr ";";
7598   if newline then pr "\n"
7599
7600 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7601 and generate_c_call_args ?handle ?(decl = false) style =
7602   pr "(";
7603   let comma = ref false in
7604   let next () =
7605     if !comma then pr ", ";
7606     comma := true
7607   in
7608   (match handle with
7609    | None -> ()
7610    | Some handle -> pr "%s" handle; comma := true
7611   );
7612   List.iter (
7613     fun arg ->
7614       next ();
7615       pr "%s" (name_of_argt arg)
7616   ) (snd style);
7617   (* For RBufferOut calls, add implicit &size parameter. *)
7618   if not decl then (
7619     match fst style with
7620     | RBufferOut _ ->
7621         next ();
7622         pr "&size"
7623     | _ -> ()
7624   );
7625   pr ")"
7626
7627 (* Generate the OCaml bindings interface. *)
7628 and generate_ocaml_mli () =
7629   generate_header OCamlStyle LGPLv2plus;
7630
7631   pr "\
7632 (** For API documentation you should refer to the C API
7633     in the guestfs(3) manual page.  The OCaml API uses almost
7634     exactly the same calls. *)
7635
7636 type t
7637 (** A [guestfs_h] handle. *)
7638
7639 exception Error of string
7640 (** This exception is raised when there is an error. *)
7641
7642 exception Handle_closed of string
7643 (** This exception is raised if you use a {!Guestfs.t} handle
7644     after calling {!close} on it.  The string is the name of
7645     the function. *)
7646
7647 val create : unit -> t
7648 (** Create a {!Guestfs.t} handle. *)
7649
7650 val close : t -> unit
7651 (** Close the {!Guestfs.t} handle and free up all resources used
7652     by it immediately.
7653
7654     Handles are closed by the garbage collector when they become
7655     unreferenced, but callers can call this in order to provide
7656     predictable cleanup. *)
7657
7658 ";
7659   generate_ocaml_structure_decls ();
7660
7661   (* The actions. *)
7662   List.iter (
7663     fun (name, style, _, _, _, shortdesc, _) ->
7664       generate_ocaml_prototype name style;
7665       pr "(** %s *)\n" shortdesc;
7666       pr "\n"
7667   ) all_functions_sorted
7668
7669 (* Generate the OCaml bindings implementation. *)
7670 and generate_ocaml_ml () =
7671   generate_header OCamlStyle LGPLv2plus;
7672
7673   pr "\
7674 type t
7675
7676 exception Error of string
7677 exception Handle_closed of string
7678
7679 external create : unit -> t = \"ocaml_guestfs_create\"
7680 external close : t -> unit = \"ocaml_guestfs_close\"
7681
7682 (* Give the exceptions names, so they can be raised from the C code. *)
7683 let () =
7684   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7685   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7686
7687 ";
7688
7689   generate_ocaml_structure_decls ();
7690
7691   (* The actions. *)
7692   List.iter (
7693     fun (name, style, _, _, _, shortdesc, _) ->
7694       generate_ocaml_prototype ~is_external:true name style;
7695   ) all_functions_sorted
7696
7697 (* Generate the OCaml bindings C implementation. *)
7698 and generate_ocaml_c () =
7699   generate_header CStyle LGPLv2plus;
7700
7701   pr "\
7702 #include <stdio.h>
7703 #include <stdlib.h>
7704 #include <string.h>
7705
7706 #include <caml/config.h>
7707 #include <caml/alloc.h>
7708 #include <caml/callback.h>
7709 #include <caml/fail.h>
7710 #include <caml/memory.h>
7711 #include <caml/mlvalues.h>
7712 #include <caml/signals.h>
7713
7714 #include <guestfs.h>
7715
7716 #include \"guestfs_c.h\"
7717
7718 /* Copy a hashtable of string pairs into an assoc-list.  We return
7719  * the list in reverse order, but hashtables aren't supposed to be
7720  * ordered anyway.
7721  */
7722 static CAMLprim value
7723 copy_table (char * const * argv)
7724 {
7725   CAMLparam0 ();
7726   CAMLlocal5 (rv, pairv, kv, vv, cons);
7727   int i;
7728
7729   rv = Val_int (0);
7730   for (i = 0; argv[i] != NULL; i += 2) {
7731     kv = caml_copy_string (argv[i]);
7732     vv = caml_copy_string (argv[i+1]);
7733     pairv = caml_alloc (2, 0);
7734     Store_field (pairv, 0, kv);
7735     Store_field (pairv, 1, vv);
7736     cons = caml_alloc (2, 0);
7737     Store_field (cons, 1, rv);
7738     rv = cons;
7739     Store_field (cons, 0, pairv);
7740   }
7741
7742   CAMLreturn (rv);
7743 }
7744
7745 ";
7746
7747   (* Struct copy functions. *)
7748
7749   let emit_ocaml_copy_list_function typ =
7750     pr "static CAMLprim value\n";
7751     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7752     pr "{\n";
7753     pr "  CAMLparam0 ();\n";
7754     pr "  CAMLlocal2 (rv, v);\n";
7755     pr "  unsigned int i;\n";
7756     pr "\n";
7757     pr "  if (%ss->len == 0)\n" typ;
7758     pr "    CAMLreturn (Atom (0));\n";
7759     pr "  else {\n";
7760     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7761     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7762     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7763     pr "      caml_modify (&Field (rv, i), v);\n";
7764     pr "    }\n";
7765     pr "    CAMLreturn (rv);\n";
7766     pr "  }\n";
7767     pr "}\n";
7768     pr "\n";
7769   in
7770
7771   List.iter (
7772     fun (typ, cols) ->
7773       let has_optpercent_col =
7774         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7775
7776       pr "static CAMLprim value\n";
7777       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7778       pr "{\n";
7779       pr "  CAMLparam0 ();\n";
7780       if has_optpercent_col then
7781         pr "  CAMLlocal3 (rv, v, v2);\n"
7782       else
7783         pr "  CAMLlocal2 (rv, v);\n";
7784       pr "\n";
7785       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7786       iteri (
7787         fun i col ->
7788           (match col with
7789            | name, FString ->
7790                pr "  v = caml_copy_string (%s->%s);\n" typ name
7791            | name, FBuffer ->
7792                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7793                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7794                  typ name typ name
7795            | name, FUUID ->
7796                pr "  v = caml_alloc_string (32);\n";
7797                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7798            | name, (FBytes|FInt64|FUInt64) ->
7799                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7800            | name, (FInt32|FUInt32) ->
7801                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7802            | name, FOptPercent ->
7803                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7804                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7805                pr "    v = caml_alloc (1, 0);\n";
7806                pr "    Store_field (v, 0, v2);\n";
7807                pr "  } else /* None */\n";
7808                pr "    v = Val_int (0);\n";
7809            | name, FChar ->
7810                pr "  v = Val_int (%s->%s);\n" typ name
7811           );
7812           pr "  Store_field (rv, %d, v);\n" i
7813       ) cols;
7814       pr "  CAMLreturn (rv);\n";
7815       pr "}\n";
7816       pr "\n";
7817   ) structs;
7818
7819   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7820   List.iter (
7821     function
7822     | typ, (RStructListOnly | RStructAndList) ->
7823         (* generate the function for typ *)
7824         emit_ocaml_copy_list_function typ
7825     | typ, _ -> () (* empty *)
7826   ) (rstructs_used_by all_functions);
7827
7828   (* The wrappers. *)
7829   List.iter (
7830     fun (name, style, _, _, _, _, _) ->
7831       pr "/* Automatically generated wrapper for function\n";
7832       pr " * ";
7833       generate_ocaml_prototype name style;
7834       pr " */\n";
7835       pr "\n";
7836
7837       let params =
7838         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7839
7840       let needs_extra_vs =
7841         match fst style with RConstOptString _ -> true | _ -> false in
7842
7843       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7844       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7845       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7846       pr "\n";
7847
7848       pr "CAMLprim value\n";
7849       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7850       List.iter (pr ", value %s") (List.tl params);
7851       pr ")\n";
7852       pr "{\n";
7853
7854       (match params with
7855        | [p1; p2; p3; p4; p5] ->
7856            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7857        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7858            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7859            pr "  CAMLxparam%d (%s);\n"
7860              (List.length rest) (String.concat ", " rest)
7861        | ps ->
7862            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7863       );
7864       if not needs_extra_vs then
7865         pr "  CAMLlocal1 (rv);\n"
7866       else
7867         pr "  CAMLlocal3 (rv, v, v2);\n";
7868       pr "\n";
7869
7870       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7871       pr "  if (g == NULL)\n";
7872       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7873       pr "\n";
7874
7875       List.iter (
7876         function
7877         | Pathname n
7878         | Device n | Dev_or_Path n
7879         | String n
7880         | FileIn n
7881         | FileOut n ->
7882             pr "  const char *%s = String_val (%sv);\n" n n
7883         | OptString n ->
7884             pr "  const char *%s =\n" n;
7885             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7886               n n
7887         | StringList n | DeviceList n ->
7888             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7889         | Bool n ->
7890             pr "  int %s = Bool_val (%sv);\n" n n
7891         | Int n ->
7892             pr "  int %s = Int_val (%sv);\n" n n
7893         | Int64 n ->
7894             pr "  int64_t %s = Int64_val (%sv);\n" n n
7895       ) (snd style);
7896       let error_code =
7897         match fst style with
7898         | RErr -> pr "  int r;\n"; "-1"
7899         | RInt _ -> pr "  int r;\n"; "-1"
7900         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7901         | RBool _ -> pr "  int r;\n"; "-1"
7902         | RConstString _ | RConstOptString _ ->
7903             pr "  const char *r;\n"; "NULL"
7904         | RString _ -> pr "  char *r;\n"; "NULL"
7905         | RStringList _ ->
7906             pr "  int i;\n";
7907             pr "  char **r;\n";
7908             "NULL"
7909         | RStruct (_, typ) ->
7910             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7911         | RStructList (_, typ) ->
7912             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7913         | RHashtable _ ->
7914             pr "  int i;\n";
7915             pr "  char **r;\n";
7916             "NULL"
7917         | RBufferOut _ ->
7918             pr "  char *r;\n";
7919             pr "  size_t size;\n";
7920             "NULL" in
7921       pr "\n";
7922
7923       pr "  caml_enter_blocking_section ();\n";
7924       pr "  r = guestfs_%s " name;
7925       generate_c_call_args ~handle:"g" style;
7926       pr ";\n";
7927       pr "  caml_leave_blocking_section ();\n";
7928
7929       List.iter (
7930         function
7931         | StringList n | DeviceList n ->
7932             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7933         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7934         | Bool _ | Int _ | Int64 _
7935         | FileIn _ | FileOut _ -> ()
7936       ) (snd style);
7937
7938       pr "  if (r == %s)\n" error_code;
7939       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7940       pr "\n";
7941
7942       (match fst style with
7943        | RErr -> pr "  rv = Val_unit;\n"
7944        | RInt _ -> pr "  rv = Val_int (r);\n"
7945        | RInt64 _ ->
7946            pr "  rv = caml_copy_int64 (r);\n"
7947        | RBool _ -> pr "  rv = Val_bool (r);\n"
7948        | RConstString _ ->
7949            pr "  rv = caml_copy_string (r);\n"
7950        | RConstOptString _ ->
7951            pr "  if (r) { /* Some string */\n";
7952            pr "    v = caml_alloc (1, 0);\n";
7953            pr "    v2 = caml_copy_string (r);\n";
7954            pr "    Store_field (v, 0, v2);\n";
7955            pr "  } else /* None */\n";
7956            pr "    v = Val_int (0);\n";
7957        | RString _ ->
7958            pr "  rv = caml_copy_string (r);\n";
7959            pr "  free (r);\n"
7960        | RStringList _ ->
7961            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7962            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7963            pr "  free (r);\n"
7964        | RStruct (_, typ) ->
7965            pr "  rv = copy_%s (r);\n" typ;
7966            pr "  guestfs_free_%s (r);\n" typ;
7967        | RStructList (_, typ) ->
7968            pr "  rv = copy_%s_list (r);\n" typ;
7969            pr "  guestfs_free_%s_list (r);\n" typ;
7970        | RHashtable _ ->
7971            pr "  rv = copy_table (r);\n";
7972            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7973            pr "  free (r);\n";
7974        | RBufferOut _ ->
7975            pr "  rv = caml_alloc_string (size);\n";
7976            pr "  memcpy (String_val (rv), r, size);\n";
7977       );
7978
7979       pr "  CAMLreturn (rv);\n";
7980       pr "}\n";
7981       pr "\n";
7982
7983       if List.length params > 5 then (
7984         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7985         pr "CAMLprim value ";
7986         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7987         pr "CAMLprim value\n";
7988         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7989         pr "{\n";
7990         pr "  return ocaml_guestfs_%s (argv[0]" name;
7991         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7992         pr ");\n";
7993         pr "}\n";
7994         pr "\n"
7995       )
7996   ) all_functions_sorted
7997
7998 and generate_ocaml_structure_decls () =
7999   List.iter (
8000     fun (typ, cols) ->
8001       pr "type %s = {\n" typ;
8002       List.iter (
8003         function
8004         | name, FString -> pr "  %s : string;\n" name
8005         | name, FBuffer -> pr "  %s : string;\n" name
8006         | name, FUUID -> pr "  %s : string;\n" name
8007         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8008         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8009         | name, FChar -> pr "  %s : char;\n" name
8010         | name, FOptPercent -> pr "  %s : float option;\n" name
8011       ) cols;
8012       pr "}\n";
8013       pr "\n"
8014   ) structs
8015
8016 and generate_ocaml_prototype ?(is_external = false) name style =
8017   if is_external then pr "external " else pr "val ";
8018   pr "%s : t -> " name;
8019   List.iter (
8020     function
8021     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8022     | OptString _ -> pr "string option -> "
8023     | StringList _ | DeviceList _ -> pr "string array -> "
8024     | Bool _ -> pr "bool -> "
8025     | Int _ -> pr "int -> "
8026     | Int64 _ -> pr "int64 -> "
8027   ) (snd style);
8028   (match fst style with
8029    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8030    | RInt _ -> pr "int"
8031    | RInt64 _ -> pr "int64"
8032    | RBool _ -> pr "bool"
8033    | RConstString _ -> pr "string"
8034    | RConstOptString _ -> pr "string option"
8035    | RString _ | RBufferOut _ -> pr "string"
8036    | RStringList _ -> pr "string array"
8037    | RStruct (_, typ) -> pr "%s" typ
8038    | RStructList (_, typ) -> pr "%s array" typ
8039    | RHashtable _ -> pr "(string * string) list"
8040   );
8041   if is_external then (
8042     pr " = ";
8043     if List.length (snd style) + 1 > 5 then
8044       pr "\"ocaml_guestfs_%s_byte\" " name;
8045     pr "\"ocaml_guestfs_%s\"" name
8046   );
8047   pr "\n"
8048
8049 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8050 and generate_perl_xs () =
8051   generate_header CStyle LGPLv2plus;
8052
8053   pr "\
8054 #include \"EXTERN.h\"
8055 #include \"perl.h\"
8056 #include \"XSUB.h\"
8057
8058 #include <guestfs.h>
8059
8060 #ifndef PRId64
8061 #define PRId64 \"lld\"
8062 #endif
8063
8064 static SV *
8065 my_newSVll(long long val) {
8066 #ifdef USE_64_BIT_ALL
8067   return newSViv(val);
8068 #else
8069   char buf[100];
8070   int len;
8071   len = snprintf(buf, 100, \"%%\" PRId64, val);
8072   return newSVpv(buf, len);
8073 #endif
8074 }
8075
8076 #ifndef PRIu64
8077 #define PRIu64 \"llu\"
8078 #endif
8079
8080 static SV *
8081 my_newSVull(unsigned long long val) {
8082 #ifdef USE_64_BIT_ALL
8083   return newSVuv(val);
8084 #else
8085   char buf[100];
8086   int len;
8087   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8088   return newSVpv(buf, len);
8089 #endif
8090 }
8091
8092 /* http://www.perlmonks.org/?node_id=680842 */
8093 static char **
8094 XS_unpack_charPtrPtr (SV *arg) {
8095   char **ret;
8096   AV *av;
8097   I32 i;
8098
8099   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8100     croak (\"array reference expected\");
8101
8102   av = (AV *)SvRV (arg);
8103   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8104   if (!ret)
8105     croak (\"malloc failed\");
8106
8107   for (i = 0; i <= av_len (av); i++) {
8108     SV **elem = av_fetch (av, i, 0);
8109
8110     if (!elem || !*elem)
8111       croak (\"missing element in list\");
8112
8113     ret[i] = SvPV_nolen (*elem);
8114   }
8115
8116   ret[i] = NULL;
8117
8118   return ret;
8119 }
8120
8121 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8122
8123 PROTOTYPES: ENABLE
8124
8125 guestfs_h *
8126 _create ()
8127    CODE:
8128       RETVAL = guestfs_create ();
8129       if (!RETVAL)
8130         croak (\"could not create guestfs handle\");
8131       guestfs_set_error_handler (RETVAL, NULL, NULL);
8132  OUTPUT:
8133       RETVAL
8134
8135 void
8136 DESTROY (g)
8137       guestfs_h *g;
8138  PPCODE:
8139       guestfs_close (g);
8140
8141 ";
8142
8143   List.iter (
8144     fun (name, style, _, _, _, _, _) ->
8145       (match fst style with
8146        | RErr -> pr "void\n"
8147        | RInt _ -> pr "SV *\n"
8148        | RInt64 _ -> pr "SV *\n"
8149        | RBool _ -> pr "SV *\n"
8150        | RConstString _ -> pr "SV *\n"
8151        | RConstOptString _ -> pr "SV *\n"
8152        | RString _ -> pr "SV *\n"
8153        | RBufferOut _ -> pr "SV *\n"
8154        | RStringList _
8155        | RStruct _ | RStructList _
8156        | RHashtable _ ->
8157            pr "void\n" (* all lists returned implictly on the stack *)
8158       );
8159       (* Call and arguments. *)
8160       pr "%s " name;
8161       generate_c_call_args ~handle:"g" ~decl:true style;
8162       pr "\n";
8163       pr "      guestfs_h *g;\n";
8164       iteri (
8165         fun i ->
8166           function
8167           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8168               pr "      char *%s;\n" n
8169           | OptString n ->
8170               (* http://www.perlmonks.org/?node_id=554277
8171                * Note that the implicit handle argument means we have
8172                * to add 1 to the ST(x) operator.
8173                *)
8174               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8175           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8176           | Bool n -> pr "      int %s;\n" n
8177           | Int n -> pr "      int %s;\n" n
8178           | Int64 n -> pr "      int64_t %s;\n" n
8179       ) (snd style);
8180
8181       let do_cleanups () =
8182         List.iter (
8183           function
8184           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8185           | Bool _ | Int _ | Int64 _
8186           | FileIn _ | FileOut _ -> ()
8187           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8188         ) (snd style)
8189       in
8190
8191       (* Code. *)
8192       (match fst style with
8193        | RErr ->
8194            pr "PREINIT:\n";
8195            pr "      int r;\n";
8196            pr " PPCODE:\n";
8197            pr "      r = guestfs_%s " name;
8198            generate_c_call_args ~handle:"g" style;
8199            pr ";\n";
8200            do_cleanups ();
8201            pr "      if (r == -1)\n";
8202            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8203        | RInt n
8204        | RBool n ->
8205            pr "PREINIT:\n";
8206            pr "      int %s;\n" n;
8207            pr "   CODE:\n";
8208            pr "      %s = guestfs_%s " n name;
8209            generate_c_call_args ~handle:"g" style;
8210            pr ";\n";
8211            do_cleanups ();
8212            pr "      if (%s == -1)\n" n;
8213            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8214            pr "      RETVAL = newSViv (%s);\n" n;
8215            pr " OUTPUT:\n";
8216            pr "      RETVAL\n"
8217        | RInt64 n ->
8218            pr "PREINIT:\n";
8219            pr "      int64_t %s;\n" n;
8220            pr "   CODE:\n";
8221            pr "      %s = guestfs_%s " n name;
8222            generate_c_call_args ~handle:"g" style;
8223            pr ";\n";
8224            do_cleanups ();
8225            pr "      if (%s == -1)\n" n;
8226            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8227            pr "      RETVAL = my_newSVll (%s);\n" n;
8228            pr " OUTPUT:\n";
8229            pr "      RETVAL\n"
8230        | RConstString n ->
8231            pr "PREINIT:\n";
8232            pr "      const char *%s;\n" n;
8233            pr "   CODE:\n";
8234            pr "      %s = guestfs_%s " n name;
8235            generate_c_call_args ~handle:"g" style;
8236            pr ";\n";
8237            do_cleanups ();
8238            pr "      if (%s == NULL)\n" n;
8239            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8240            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8241            pr " OUTPUT:\n";
8242            pr "      RETVAL\n"
8243        | RConstOptString n ->
8244            pr "PREINIT:\n";
8245            pr "      const char *%s;\n" n;
8246            pr "   CODE:\n";
8247            pr "      %s = guestfs_%s " n name;
8248            generate_c_call_args ~handle:"g" style;
8249            pr ";\n";
8250            do_cleanups ();
8251            pr "      if (%s == NULL)\n" n;
8252            pr "        RETVAL = &PL_sv_undef;\n";
8253            pr "      else\n";
8254            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8255            pr " OUTPUT:\n";
8256            pr "      RETVAL\n"
8257        | RString n ->
8258            pr "PREINIT:\n";
8259            pr "      char *%s;\n" n;
8260            pr "   CODE:\n";
8261            pr "      %s = guestfs_%s " n name;
8262            generate_c_call_args ~handle:"g" style;
8263            pr ";\n";
8264            do_cleanups ();
8265            pr "      if (%s == NULL)\n" n;
8266            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8267            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8268            pr "      free (%s);\n" n;
8269            pr " OUTPUT:\n";
8270            pr "      RETVAL\n"
8271        | RStringList n | RHashtable n ->
8272            pr "PREINIT:\n";
8273            pr "      char **%s;\n" n;
8274            pr "      int i, n;\n";
8275            pr " PPCODE:\n";
8276            pr "      %s = guestfs_%s " n name;
8277            generate_c_call_args ~handle:"g" style;
8278            pr ";\n";
8279            do_cleanups ();
8280            pr "      if (%s == NULL)\n" n;
8281            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8282            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8283            pr "      EXTEND (SP, n);\n";
8284            pr "      for (i = 0; i < n; ++i) {\n";
8285            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8286            pr "        free (%s[i]);\n" n;
8287            pr "      }\n";
8288            pr "      free (%s);\n" n;
8289        | RStruct (n, typ) ->
8290            let cols = cols_of_struct typ in
8291            generate_perl_struct_code typ cols name style n do_cleanups
8292        | RStructList (n, typ) ->
8293            let cols = cols_of_struct typ in
8294            generate_perl_struct_list_code typ cols name style n do_cleanups
8295        | RBufferOut n ->
8296            pr "PREINIT:\n";
8297            pr "      char *%s;\n" n;
8298            pr "      size_t size;\n";
8299            pr "   CODE:\n";
8300            pr "      %s = guestfs_%s " n name;
8301            generate_c_call_args ~handle:"g" style;
8302            pr ";\n";
8303            do_cleanups ();
8304            pr "      if (%s == NULL)\n" n;
8305            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8306            pr "      RETVAL = newSVpv (%s, size);\n" n;
8307            pr "      free (%s);\n" n;
8308            pr " OUTPUT:\n";
8309            pr "      RETVAL\n"
8310       );
8311
8312       pr "\n"
8313   ) all_functions
8314
8315 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8316   pr "PREINIT:\n";
8317   pr "      struct guestfs_%s_list *%s;\n" typ n;
8318   pr "      int i;\n";
8319   pr "      HV *hv;\n";
8320   pr " PPCODE:\n";
8321   pr "      %s = guestfs_%s " n name;
8322   generate_c_call_args ~handle:"g" style;
8323   pr ";\n";
8324   do_cleanups ();
8325   pr "      if (%s == NULL)\n" n;
8326   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8327   pr "      EXTEND (SP, %s->len);\n" n;
8328   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8329   pr "        hv = newHV ();\n";
8330   List.iter (
8331     function
8332     | name, FString ->
8333         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8334           name (String.length name) n name
8335     | name, FUUID ->
8336         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8337           name (String.length name) n name
8338     | name, FBuffer ->
8339         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8340           name (String.length name) n name n name
8341     | name, (FBytes|FUInt64) ->
8342         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8343           name (String.length name) n name
8344     | name, FInt64 ->
8345         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8346           name (String.length name) n name
8347     | name, (FInt32|FUInt32) ->
8348         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8349           name (String.length name) n name
8350     | name, FChar ->
8351         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8352           name (String.length name) n name
8353     | name, FOptPercent ->
8354         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8355           name (String.length name) n name
8356   ) cols;
8357   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8358   pr "      }\n";
8359   pr "      guestfs_free_%s_list (%s);\n" typ n
8360
8361 and generate_perl_struct_code typ cols name style n do_cleanups =
8362   pr "PREINIT:\n";
8363   pr "      struct guestfs_%s *%s;\n" typ n;
8364   pr " PPCODE:\n";
8365   pr "      %s = guestfs_%s " n name;
8366   generate_c_call_args ~handle:"g" style;
8367   pr ";\n";
8368   do_cleanups ();
8369   pr "      if (%s == NULL)\n" n;
8370   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8371   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8372   List.iter (
8373     fun ((name, _) as col) ->
8374       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8375
8376       match col with
8377       | name, FString ->
8378           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8379             n name
8380       | name, FBuffer ->
8381           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8382             n name n name
8383       | name, FUUID ->
8384           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8385             n name
8386       | name, (FBytes|FUInt64) ->
8387           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8388             n name
8389       | name, FInt64 ->
8390           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8391             n name
8392       | name, (FInt32|FUInt32) ->
8393           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8394             n name
8395       | name, FChar ->
8396           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8397             n name
8398       | name, FOptPercent ->
8399           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8400             n name
8401   ) cols;
8402   pr "      free (%s);\n" n
8403
8404 (* Generate Sys/Guestfs.pm. *)
8405 and generate_perl_pm () =
8406   generate_header HashStyle LGPLv2plus;
8407
8408   pr "\
8409 =pod
8410
8411 =head1 NAME
8412
8413 Sys::Guestfs - Perl bindings for libguestfs
8414
8415 =head1 SYNOPSIS
8416
8417  use Sys::Guestfs;
8418
8419  my $h = Sys::Guestfs->new ();
8420  $h->add_drive ('guest.img');
8421  $h->launch ();
8422  $h->mount ('/dev/sda1', '/');
8423  $h->touch ('/hello');
8424  $h->sync ();
8425
8426 =head1 DESCRIPTION
8427
8428 The C<Sys::Guestfs> module provides a Perl XS binding to the
8429 libguestfs API for examining and modifying virtual machine
8430 disk images.
8431
8432 Amongst the things this is good for: making batch configuration
8433 changes to guests, getting disk used/free statistics (see also:
8434 virt-df), migrating between virtualization systems (see also:
8435 virt-p2v), performing partial backups, performing partial guest
8436 clones, cloning guests and changing registry/UUID/hostname info, and
8437 much else besides.
8438
8439 Libguestfs uses Linux kernel and qemu code, and can access any type of
8440 guest filesystem that Linux and qemu can, including but not limited
8441 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8442 schemes, qcow, qcow2, vmdk.
8443
8444 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8445 LVs, what filesystem is in each LV, etc.).  It can also run commands
8446 in the context of the guest.  Also you can access filesystems over
8447 FUSE.
8448
8449 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8450 functions for using libguestfs from Perl, including integration
8451 with libvirt.
8452
8453 =head1 ERRORS
8454
8455 All errors turn into calls to C<croak> (see L<Carp(3)>).
8456
8457 =head1 METHODS
8458
8459 =over 4
8460
8461 =cut
8462
8463 package Sys::Guestfs;
8464
8465 use strict;
8466 use warnings;
8467
8468 require XSLoader;
8469 XSLoader::load ('Sys::Guestfs');
8470
8471 =item $h = Sys::Guestfs->new ();
8472
8473 Create a new guestfs handle.
8474
8475 =cut
8476
8477 sub new {
8478   my $proto = shift;
8479   my $class = ref ($proto) || $proto;
8480
8481   my $self = Sys::Guestfs::_create ();
8482   bless $self, $class;
8483   return $self;
8484 }
8485
8486 ";
8487
8488   (* Actions.  We only need to print documentation for these as
8489    * they are pulled in from the XS code automatically.
8490    *)
8491   List.iter (
8492     fun (name, style, _, flags, _, _, longdesc) ->
8493       if not (List.mem NotInDocs flags) then (
8494         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8495         pr "=item ";
8496         generate_perl_prototype name style;
8497         pr "\n\n";
8498         pr "%s\n\n" longdesc;
8499         if List.mem ProtocolLimitWarning flags then
8500           pr "%s\n\n" protocol_limit_warning;
8501         if List.mem DangerWillRobinson flags then
8502           pr "%s\n\n" danger_will_robinson;
8503         match deprecation_notice flags with
8504         | None -> ()
8505         | Some txt -> pr "%s\n\n" txt
8506       )
8507   ) all_functions_sorted;
8508
8509   (* End of file. *)
8510   pr "\
8511 =cut
8512
8513 1;
8514
8515 =back
8516
8517 =head1 COPYRIGHT
8518
8519 Copyright (C) %s Red Hat Inc.
8520
8521 =head1 LICENSE
8522
8523 Please see the file COPYING.LIB for the full license.
8524
8525 =head1 SEE ALSO
8526
8527 L<guestfs(3)>,
8528 L<guestfish(1)>,
8529 L<http://libguestfs.org>,
8530 L<Sys::Guestfs::Lib(3)>.
8531
8532 =cut
8533 " copyright_years
8534
8535 and generate_perl_prototype name style =
8536   (match fst style with
8537    | RErr -> ()
8538    | RBool n
8539    | RInt n
8540    | RInt64 n
8541    | RConstString n
8542    | RConstOptString n
8543    | RString n
8544    | RBufferOut n -> pr "$%s = " n
8545    | RStruct (n,_)
8546    | RHashtable n -> pr "%%%s = " n
8547    | RStringList n
8548    | RStructList (n,_) -> pr "@%s = " n
8549   );
8550   pr "$h->%s (" name;
8551   let comma = ref false in
8552   List.iter (
8553     fun arg ->
8554       if !comma then pr ", ";
8555       comma := true;
8556       match arg with
8557       | Pathname n | Device n | Dev_or_Path n | String n
8558       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8559           pr "$%s" n
8560       | StringList n | DeviceList n ->
8561           pr "\\@%s" n
8562   ) (snd style);
8563   pr ");"
8564
8565 (* Generate Python C module. *)
8566 and generate_python_c () =
8567   generate_header CStyle LGPLv2plus;
8568
8569   pr "\
8570 #include <Python.h>
8571
8572 #include <stdio.h>
8573 #include <stdlib.h>
8574 #include <assert.h>
8575
8576 #include \"guestfs.h\"
8577
8578 typedef struct {
8579   PyObject_HEAD
8580   guestfs_h *g;
8581 } Pyguestfs_Object;
8582
8583 static guestfs_h *
8584 get_handle (PyObject *obj)
8585 {
8586   assert (obj);
8587   assert (obj != Py_None);
8588   return ((Pyguestfs_Object *) obj)->g;
8589 }
8590
8591 static PyObject *
8592 put_handle (guestfs_h *g)
8593 {
8594   assert (g);
8595   return
8596     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8597 }
8598
8599 /* This list should be freed (but not the strings) after use. */
8600 static char **
8601 get_string_list (PyObject *obj)
8602 {
8603   int i, len;
8604   char **r;
8605
8606   assert (obj);
8607
8608   if (!PyList_Check (obj)) {
8609     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8610     return NULL;
8611   }
8612
8613   len = PyList_Size (obj);
8614   r = malloc (sizeof (char *) * (len+1));
8615   if (r == NULL) {
8616     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8617     return NULL;
8618   }
8619
8620   for (i = 0; i < len; ++i)
8621     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8622   r[len] = NULL;
8623
8624   return r;
8625 }
8626
8627 static PyObject *
8628 put_string_list (char * const * const argv)
8629 {
8630   PyObject *list;
8631   int argc, i;
8632
8633   for (argc = 0; argv[argc] != NULL; ++argc)
8634     ;
8635
8636   list = PyList_New (argc);
8637   for (i = 0; i < argc; ++i)
8638     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8639
8640   return list;
8641 }
8642
8643 static PyObject *
8644 put_table (char * const * const argv)
8645 {
8646   PyObject *list, *item;
8647   int argc, i;
8648
8649   for (argc = 0; argv[argc] != NULL; ++argc)
8650     ;
8651
8652   list = PyList_New (argc >> 1);
8653   for (i = 0; i < argc; i += 2) {
8654     item = PyTuple_New (2);
8655     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8656     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8657     PyList_SetItem (list, i >> 1, item);
8658   }
8659
8660   return list;
8661 }
8662
8663 static void
8664 free_strings (char **argv)
8665 {
8666   int argc;
8667
8668   for (argc = 0; argv[argc] != NULL; ++argc)
8669     free (argv[argc]);
8670   free (argv);
8671 }
8672
8673 static PyObject *
8674 py_guestfs_create (PyObject *self, PyObject *args)
8675 {
8676   guestfs_h *g;
8677
8678   g = guestfs_create ();
8679   if (g == NULL) {
8680     PyErr_SetString (PyExc_RuntimeError,
8681                      \"guestfs.create: failed to allocate handle\");
8682     return NULL;
8683   }
8684   guestfs_set_error_handler (g, NULL, NULL);
8685   return put_handle (g);
8686 }
8687
8688 static PyObject *
8689 py_guestfs_close (PyObject *self, PyObject *args)
8690 {
8691   PyObject *py_g;
8692   guestfs_h *g;
8693
8694   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8695     return NULL;
8696   g = get_handle (py_g);
8697
8698   guestfs_close (g);
8699
8700   Py_INCREF (Py_None);
8701   return Py_None;
8702 }
8703
8704 ";
8705
8706   let emit_put_list_function typ =
8707     pr "static PyObject *\n";
8708     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8709     pr "{\n";
8710     pr "  PyObject *list;\n";
8711     pr "  int i;\n";
8712     pr "\n";
8713     pr "  list = PyList_New (%ss->len);\n" typ;
8714     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8715     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8716     pr "  return list;\n";
8717     pr "};\n";
8718     pr "\n"
8719   in
8720
8721   (* Structures, turned into Python dictionaries. *)
8722   List.iter (
8723     fun (typ, cols) ->
8724       pr "static PyObject *\n";
8725       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8726       pr "{\n";
8727       pr "  PyObject *dict;\n";
8728       pr "\n";
8729       pr "  dict = PyDict_New ();\n";
8730       List.iter (
8731         function
8732         | name, FString ->
8733             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8734             pr "                        PyString_FromString (%s->%s));\n"
8735               typ name
8736         | name, FBuffer ->
8737             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8738             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8739               typ name typ name
8740         | name, FUUID ->
8741             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8742             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8743               typ name
8744         | name, (FBytes|FUInt64) ->
8745             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8746             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8747               typ name
8748         | name, FInt64 ->
8749             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8750             pr "                        PyLong_FromLongLong (%s->%s));\n"
8751               typ name
8752         | name, FUInt32 ->
8753             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8754             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8755               typ name
8756         | name, FInt32 ->
8757             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8758             pr "                        PyLong_FromLong (%s->%s));\n"
8759               typ name
8760         | name, FOptPercent ->
8761             pr "  if (%s->%s >= 0)\n" typ name;
8762             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8763             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8764               typ name;
8765             pr "  else {\n";
8766             pr "    Py_INCREF (Py_None);\n";
8767             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8768             pr "  }\n"
8769         | name, FChar ->
8770             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8771             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8772       ) cols;
8773       pr "  return dict;\n";
8774       pr "};\n";
8775       pr "\n";
8776
8777   ) structs;
8778
8779   (* Emit a put_TYPE_list function definition only if that function is used. *)
8780   List.iter (
8781     function
8782     | typ, (RStructListOnly | RStructAndList) ->
8783         (* generate the function for typ *)
8784         emit_put_list_function typ
8785     | typ, _ -> () (* empty *)
8786   ) (rstructs_used_by all_functions);
8787
8788   (* Python wrapper functions. *)
8789   List.iter (
8790     fun (name, style, _, _, _, _, _) ->
8791       pr "static PyObject *\n";
8792       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8793       pr "{\n";
8794
8795       pr "  PyObject *py_g;\n";
8796       pr "  guestfs_h *g;\n";
8797       pr "  PyObject *py_r;\n";
8798
8799       let error_code =
8800         match fst style with
8801         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8802         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8803         | RConstString _ | RConstOptString _ ->
8804             pr "  const char *r;\n"; "NULL"
8805         | RString _ -> pr "  char *r;\n"; "NULL"
8806         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8807         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8808         | RStructList (_, typ) ->
8809             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8810         | RBufferOut _ ->
8811             pr "  char *r;\n";
8812             pr "  size_t size;\n";
8813             "NULL" in
8814
8815       List.iter (
8816         function
8817         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8818             pr "  const char *%s;\n" n
8819         | OptString n -> pr "  const char *%s;\n" n
8820         | StringList n | DeviceList n ->
8821             pr "  PyObject *py_%s;\n" n;
8822             pr "  char **%s;\n" n
8823         | Bool n -> pr "  int %s;\n" n
8824         | Int n -> pr "  int %s;\n" n
8825         | Int64 n -> pr "  long long %s;\n" n
8826       ) (snd style);
8827
8828       pr "\n";
8829
8830       (* Convert the parameters. *)
8831       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8832       List.iter (
8833         function
8834         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8835         | OptString _ -> pr "z"
8836         | StringList _ | DeviceList _ -> pr "O"
8837         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8838         | Int _ -> pr "i"
8839         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8840                              * emulate C's int/long/long long in Python?
8841                              *)
8842       ) (snd style);
8843       pr ":guestfs_%s\",\n" name;
8844       pr "                         &py_g";
8845       List.iter (
8846         function
8847         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8848         | OptString n -> pr ", &%s" n
8849         | StringList n | DeviceList n -> pr ", &py_%s" n
8850         | Bool n -> pr ", &%s" n
8851         | Int n -> pr ", &%s" n
8852         | Int64 n -> pr ", &%s" n
8853       ) (snd style);
8854
8855       pr "))\n";
8856       pr "    return NULL;\n";
8857
8858       pr "  g = get_handle (py_g);\n";
8859       List.iter (
8860         function
8861         | Pathname _ | Device _ | Dev_or_Path _ | String _
8862         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8863         | StringList n | DeviceList n ->
8864             pr "  %s = get_string_list (py_%s);\n" n n;
8865             pr "  if (!%s) return NULL;\n" n
8866       ) (snd style);
8867
8868       pr "\n";
8869
8870       pr "  r = guestfs_%s " name;
8871       generate_c_call_args ~handle:"g" style;
8872       pr ";\n";
8873
8874       List.iter (
8875         function
8876         | Pathname _ | Device _ | Dev_or_Path _ | String _
8877         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8878         | StringList n | DeviceList n ->
8879             pr "  free (%s);\n" n
8880       ) (snd style);
8881
8882       pr "  if (r == %s) {\n" error_code;
8883       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8884       pr "    return NULL;\n";
8885       pr "  }\n";
8886       pr "\n";
8887
8888       (match fst style with
8889        | RErr ->
8890            pr "  Py_INCREF (Py_None);\n";
8891            pr "  py_r = Py_None;\n"
8892        | RInt _
8893        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8894        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8895        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8896        | RConstOptString _ ->
8897            pr "  if (r)\n";
8898            pr "    py_r = PyString_FromString (r);\n";
8899            pr "  else {\n";
8900            pr "    Py_INCREF (Py_None);\n";
8901            pr "    py_r = Py_None;\n";
8902            pr "  }\n"
8903        | RString _ ->
8904            pr "  py_r = PyString_FromString (r);\n";
8905            pr "  free (r);\n"
8906        | RStringList _ ->
8907            pr "  py_r = put_string_list (r);\n";
8908            pr "  free_strings (r);\n"
8909        | RStruct (_, typ) ->
8910            pr "  py_r = put_%s (r);\n" typ;
8911            pr "  guestfs_free_%s (r);\n" typ
8912        | RStructList (_, typ) ->
8913            pr "  py_r = put_%s_list (r);\n" typ;
8914            pr "  guestfs_free_%s_list (r);\n" typ
8915        | RHashtable n ->
8916            pr "  py_r = put_table (r);\n";
8917            pr "  free_strings (r);\n"
8918        | RBufferOut _ ->
8919            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8920            pr "  free (r);\n"
8921       );
8922
8923       pr "  return py_r;\n";
8924       pr "}\n";
8925       pr "\n"
8926   ) all_functions;
8927
8928   (* Table of functions. *)
8929   pr "static PyMethodDef methods[] = {\n";
8930   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8931   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8932   List.iter (
8933     fun (name, _, _, _, _, _, _) ->
8934       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8935         name name
8936   ) all_functions;
8937   pr "  { NULL, NULL, 0, NULL }\n";
8938   pr "};\n";
8939   pr "\n";
8940
8941   (* Init function. *)
8942   pr "\
8943 void
8944 initlibguestfsmod (void)
8945 {
8946   static int initialized = 0;
8947
8948   if (initialized) return;
8949   Py_InitModule ((char *) \"libguestfsmod\", methods);
8950   initialized = 1;
8951 }
8952 "
8953
8954 (* Generate Python module. *)
8955 and generate_python_py () =
8956   generate_header HashStyle LGPLv2plus;
8957
8958   pr "\
8959 u\"\"\"Python bindings for libguestfs
8960
8961 import guestfs
8962 g = guestfs.GuestFS ()
8963 g.add_drive (\"guest.img\")
8964 g.launch ()
8965 parts = g.list_partitions ()
8966
8967 The guestfs module provides a Python binding to the libguestfs API
8968 for examining and modifying virtual machine disk images.
8969
8970 Amongst the things this is good for: making batch configuration
8971 changes to guests, getting disk used/free statistics (see also:
8972 virt-df), migrating between virtualization systems (see also:
8973 virt-p2v), performing partial backups, performing partial guest
8974 clones, cloning guests and changing registry/UUID/hostname info, and
8975 much else besides.
8976
8977 Libguestfs uses Linux kernel and qemu code, and can access any type of
8978 guest filesystem that Linux and qemu can, including but not limited
8979 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8980 schemes, qcow, qcow2, vmdk.
8981
8982 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8983 LVs, what filesystem is in each LV, etc.).  It can also run commands
8984 in the context of the guest.  Also you can access filesystems over
8985 FUSE.
8986
8987 Errors which happen while using the API are turned into Python
8988 RuntimeError exceptions.
8989
8990 To create a guestfs handle you usually have to perform the following
8991 sequence of calls:
8992
8993 # Create the handle, call add_drive at least once, and possibly
8994 # several times if the guest has multiple block devices:
8995 g = guestfs.GuestFS ()
8996 g.add_drive (\"guest.img\")
8997
8998 # Launch the qemu subprocess and wait for it to become ready:
8999 g.launch ()
9000
9001 # Now you can issue commands, for example:
9002 logvols = g.lvs ()
9003
9004 \"\"\"
9005
9006 import libguestfsmod
9007
9008 class GuestFS:
9009     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9010
9011     def __init__ (self):
9012         \"\"\"Create a new libguestfs handle.\"\"\"
9013         self._o = libguestfsmod.create ()
9014
9015     def __del__ (self):
9016         libguestfsmod.close (self._o)
9017
9018 ";
9019
9020   List.iter (
9021     fun (name, style, _, flags, _, _, longdesc) ->
9022       pr "    def %s " name;
9023       generate_py_call_args ~handle:"self" (snd style);
9024       pr ":\n";
9025
9026       if not (List.mem NotInDocs flags) then (
9027         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9028         let doc =
9029           match fst style with
9030           | RErr | RInt _ | RInt64 _ | RBool _
9031           | RConstOptString _ | RConstString _
9032           | RString _ | RBufferOut _ -> doc
9033           | RStringList _ ->
9034               doc ^ "\n\nThis function returns a list of strings."
9035           | RStruct (_, typ) ->
9036               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9037           | RStructList (_, typ) ->
9038               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9039           | RHashtable _ ->
9040               doc ^ "\n\nThis function returns a dictionary." in
9041         let doc =
9042           if List.mem ProtocolLimitWarning flags then
9043             doc ^ "\n\n" ^ protocol_limit_warning
9044           else doc in
9045         let doc =
9046           if List.mem DangerWillRobinson flags then
9047             doc ^ "\n\n" ^ danger_will_robinson
9048           else doc in
9049         let doc =
9050           match deprecation_notice flags with
9051           | None -> doc
9052           | Some txt -> doc ^ "\n\n" ^ txt in
9053         let doc = pod2text ~width:60 name doc in
9054         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9055         let doc = String.concat "\n        " doc in
9056         pr "        u\"\"\"%s\"\"\"\n" doc;
9057       );
9058       pr "        return libguestfsmod.%s " name;
9059       generate_py_call_args ~handle:"self._o" (snd style);
9060       pr "\n";
9061       pr "\n";
9062   ) all_functions
9063
9064 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9065 and generate_py_call_args ~handle args =
9066   pr "(%s" handle;
9067   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9068   pr ")"
9069
9070 (* Useful if you need the longdesc POD text as plain text.  Returns a
9071  * list of lines.
9072  *
9073  * Because this is very slow (the slowest part of autogeneration),
9074  * we memoize the results.
9075  *)
9076 and pod2text ~width name longdesc =
9077   let key = width, name, longdesc in
9078   try Hashtbl.find pod2text_memo key
9079   with Not_found ->
9080     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9081     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9082     close_out chan;
9083     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9084     let chan = open_process_in cmd in
9085     let lines = ref [] in
9086     let rec loop i =
9087       let line = input_line chan in
9088       if i = 1 then             (* discard the first line of output *)
9089         loop (i+1)
9090       else (
9091         let line = triml line in
9092         lines := line :: !lines;
9093         loop (i+1)
9094       ) in
9095     let lines = try loop 1 with End_of_file -> List.rev !lines in
9096     unlink filename;
9097     (match close_process_in chan with
9098      | WEXITED 0 -> ()
9099      | WEXITED i ->
9100          failwithf "pod2text: process exited with non-zero status (%d)" i
9101      | WSIGNALED i | WSTOPPED i ->
9102          failwithf "pod2text: process signalled or stopped by signal %d" i
9103     );
9104     Hashtbl.add pod2text_memo key lines;
9105     pod2text_memo_updated ();
9106     lines
9107
9108 (* Generate ruby bindings. *)
9109 and generate_ruby_c () =
9110   generate_header CStyle LGPLv2plus;
9111
9112   pr "\
9113 #include <stdio.h>
9114 #include <stdlib.h>
9115
9116 #include <ruby.h>
9117
9118 #include \"guestfs.h\"
9119
9120 #include \"extconf.h\"
9121
9122 /* For Ruby < 1.9 */
9123 #ifndef RARRAY_LEN
9124 #define RARRAY_LEN(r) (RARRAY((r))->len)
9125 #endif
9126
9127 static VALUE m_guestfs;                 /* guestfs module */
9128 static VALUE c_guestfs;                 /* guestfs_h handle */
9129 static VALUE e_Error;                   /* used for all errors */
9130
9131 static void ruby_guestfs_free (void *p)
9132 {
9133   if (!p) return;
9134   guestfs_close ((guestfs_h *) p);
9135 }
9136
9137 static VALUE ruby_guestfs_create (VALUE m)
9138 {
9139   guestfs_h *g;
9140
9141   g = guestfs_create ();
9142   if (!g)
9143     rb_raise (e_Error, \"failed to create guestfs handle\");
9144
9145   /* Don't print error messages to stderr by default. */
9146   guestfs_set_error_handler (g, NULL, NULL);
9147
9148   /* Wrap it, and make sure the close function is called when the
9149    * handle goes away.
9150    */
9151   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9152 }
9153
9154 static VALUE ruby_guestfs_close (VALUE gv)
9155 {
9156   guestfs_h *g;
9157   Data_Get_Struct (gv, guestfs_h, g);
9158
9159   ruby_guestfs_free (g);
9160   DATA_PTR (gv) = NULL;
9161
9162   return Qnil;
9163 }
9164
9165 ";
9166
9167   List.iter (
9168     fun (name, style, _, _, _, _, _) ->
9169       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9170       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9171       pr ")\n";
9172       pr "{\n";
9173       pr "  guestfs_h *g;\n";
9174       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9175       pr "  if (!g)\n";
9176       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9177         name;
9178       pr "\n";
9179
9180       List.iter (
9181         function
9182         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9183             pr "  Check_Type (%sv, T_STRING);\n" n;
9184             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9185             pr "  if (!%s)\n" n;
9186             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9187             pr "              \"%s\", \"%s\");\n" n name
9188         | OptString n ->
9189             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9190         | StringList n | DeviceList n ->
9191             pr "  char **%s;\n" n;
9192             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9193             pr "  {\n";
9194             pr "    int i, len;\n";
9195             pr "    len = RARRAY_LEN (%sv);\n" n;
9196             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9197               n;
9198             pr "    for (i = 0; i < len; ++i) {\n";
9199             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9200             pr "      %s[i] = StringValueCStr (v);\n" n;
9201             pr "    }\n";
9202             pr "    %s[len] = NULL;\n" n;
9203             pr "  }\n";
9204         | Bool n ->
9205             pr "  int %s = RTEST (%sv);\n" n n
9206         | Int n ->
9207             pr "  int %s = NUM2INT (%sv);\n" n n
9208         | Int64 n ->
9209             pr "  long long %s = NUM2LL (%sv);\n" n n
9210       ) (snd style);
9211       pr "\n";
9212
9213       let error_code =
9214         match fst style with
9215         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9216         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9217         | RConstString _ | RConstOptString _ ->
9218             pr "  const char *r;\n"; "NULL"
9219         | RString _ -> pr "  char *r;\n"; "NULL"
9220         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9221         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9222         | RStructList (_, typ) ->
9223             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9224         | RBufferOut _ ->
9225             pr "  char *r;\n";
9226             pr "  size_t size;\n";
9227             "NULL" in
9228       pr "\n";
9229
9230       pr "  r = guestfs_%s " name;
9231       generate_c_call_args ~handle:"g" style;
9232       pr ";\n";
9233
9234       List.iter (
9235         function
9236         | Pathname _ | Device _ | Dev_or_Path _ | String _
9237         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9238         | StringList n | DeviceList n ->
9239             pr "  free (%s);\n" n
9240       ) (snd style);
9241
9242       pr "  if (r == %s)\n" error_code;
9243       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9244       pr "\n";
9245
9246       (match fst style with
9247        | RErr ->
9248            pr "  return Qnil;\n"
9249        | RInt _ | RBool _ ->
9250            pr "  return INT2NUM (r);\n"
9251        | RInt64 _ ->
9252            pr "  return ULL2NUM (r);\n"
9253        | RConstString _ ->
9254            pr "  return rb_str_new2 (r);\n";
9255        | RConstOptString _ ->
9256            pr "  if (r)\n";
9257            pr "    return rb_str_new2 (r);\n";
9258            pr "  else\n";
9259            pr "    return Qnil;\n";
9260        | RString _ ->
9261            pr "  VALUE rv = rb_str_new2 (r);\n";
9262            pr "  free (r);\n";
9263            pr "  return rv;\n";
9264        | RStringList _ ->
9265            pr "  int i, len = 0;\n";
9266            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9267            pr "  VALUE rv = rb_ary_new2 (len);\n";
9268            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9269            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9270            pr "    free (r[i]);\n";
9271            pr "  }\n";
9272            pr "  free (r);\n";
9273            pr "  return rv;\n"
9274        | RStruct (_, typ) ->
9275            let cols = cols_of_struct typ in
9276            generate_ruby_struct_code typ cols
9277        | RStructList (_, typ) ->
9278            let cols = cols_of_struct typ in
9279            generate_ruby_struct_list_code typ cols
9280        | RHashtable _ ->
9281            pr "  VALUE rv = rb_hash_new ();\n";
9282            pr "  int i;\n";
9283            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9284            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9285            pr "    free (r[i]);\n";
9286            pr "    free (r[i+1]);\n";
9287            pr "  }\n";
9288            pr "  free (r);\n";
9289            pr "  return rv;\n"
9290        | RBufferOut _ ->
9291            pr "  VALUE rv = rb_str_new (r, size);\n";
9292            pr "  free (r);\n";
9293            pr "  return rv;\n";
9294       );
9295
9296       pr "}\n";
9297       pr "\n"
9298   ) all_functions;
9299
9300   pr "\
9301 /* Initialize the module. */
9302 void Init__guestfs ()
9303 {
9304   m_guestfs = rb_define_module (\"Guestfs\");
9305   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9306   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9307
9308   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9309   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9310
9311 ";
9312   (* Define the rest of the methods. *)
9313   List.iter (
9314     fun (name, style, _, _, _, _, _) ->
9315       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9316       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9317   ) all_functions;
9318
9319   pr "}\n"
9320
9321 (* Ruby code to return a struct. *)
9322 and generate_ruby_struct_code typ cols =
9323   pr "  VALUE rv = rb_hash_new ();\n";
9324   List.iter (
9325     function
9326     | name, FString ->
9327         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9328     | name, FBuffer ->
9329         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9330     | name, FUUID ->
9331         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9332     | name, (FBytes|FUInt64) ->
9333         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9334     | name, FInt64 ->
9335         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9336     | name, FUInt32 ->
9337         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9338     | name, FInt32 ->
9339         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9340     | name, FOptPercent ->
9341         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9342     | name, FChar -> (* XXX wrong? *)
9343         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9344   ) cols;
9345   pr "  guestfs_free_%s (r);\n" typ;
9346   pr "  return rv;\n"
9347
9348 (* Ruby code to return a struct list. *)
9349 and generate_ruby_struct_list_code typ cols =
9350   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9351   pr "  int i;\n";
9352   pr "  for (i = 0; i < r->len; ++i) {\n";
9353   pr "    VALUE hv = rb_hash_new ();\n";
9354   List.iter (
9355     function
9356     | name, FString ->
9357         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9358     | name, FBuffer ->
9359         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
9360     | name, FUUID ->
9361         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9362     | name, (FBytes|FUInt64) ->
9363         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9364     | name, FInt64 ->
9365         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9366     | name, FUInt32 ->
9367         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9368     | name, FInt32 ->
9369         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9370     | name, FOptPercent ->
9371         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9372     | name, FChar -> (* XXX wrong? *)
9373         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9374   ) cols;
9375   pr "    rb_ary_push (rv, hv);\n";
9376   pr "  }\n";
9377   pr "  guestfs_free_%s_list (r);\n" typ;
9378   pr "  return rv;\n"
9379
9380 (* Generate Java bindings GuestFS.java file. *)
9381 and generate_java_java () =
9382   generate_header CStyle LGPLv2plus;
9383
9384   pr "\
9385 package com.redhat.et.libguestfs;
9386
9387 import java.util.HashMap;
9388 import com.redhat.et.libguestfs.LibGuestFSException;
9389 import com.redhat.et.libguestfs.PV;
9390 import com.redhat.et.libguestfs.VG;
9391 import com.redhat.et.libguestfs.LV;
9392 import com.redhat.et.libguestfs.Stat;
9393 import com.redhat.et.libguestfs.StatVFS;
9394 import com.redhat.et.libguestfs.IntBool;
9395 import com.redhat.et.libguestfs.Dirent;
9396
9397 /**
9398  * The GuestFS object is a libguestfs handle.
9399  *
9400  * @author rjones
9401  */
9402 public class GuestFS {
9403   // Load the native code.
9404   static {
9405     System.loadLibrary (\"guestfs_jni\");
9406   }
9407
9408   /**
9409    * The native guestfs_h pointer.
9410    */
9411   long g;
9412
9413   /**
9414    * Create a libguestfs handle.
9415    *
9416    * @throws LibGuestFSException
9417    */
9418   public GuestFS () throws LibGuestFSException
9419   {
9420     g = _create ();
9421   }
9422   private native long _create () throws LibGuestFSException;
9423
9424   /**
9425    * Close a libguestfs handle.
9426    *
9427    * You can also leave handles to be collected by the garbage
9428    * collector, but this method ensures that the resources used
9429    * by the handle are freed up immediately.  If you call any
9430    * other methods after closing the handle, you will get an
9431    * exception.
9432    *
9433    * @throws LibGuestFSException
9434    */
9435   public void close () throws LibGuestFSException
9436   {
9437     if (g != 0)
9438       _close (g);
9439     g = 0;
9440   }
9441   private native void _close (long g) throws LibGuestFSException;
9442
9443   public void finalize () throws LibGuestFSException
9444   {
9445     close ();
9446   }
9447
9448 ";
9449
9450   List.iter (
9451     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9452       if not (List.mem NotInDocs flags); then (
9453         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9454         let doc =
9455           if List.mem ProtocolLimitWarning flags then
9456             doc ^ "\n\n" ^ protocol_limit_warning
9457           else doc in
9458         let doc =
9459           if List.mem DangerWillRobinson flags then
9460             doc ^ "\n\n" ^ danger_will_robinson
9461           else doc in
9462         let doc =
9463           match deprecation_notice flags with
9464           | None -> doc
9465           | Some txt -> doc ^ "\n\n" ^ txt in
9466         let doc = pod2text ~width:60 name doc in
9467         let doc = List.map (            (* RHBZ#501883 *)
9468           function
9469           | "" -> "<p>"
9470           | nonempty -> nonempty
9471         ) doc in
9472         let doc = String.concat "\n   * " doc in
9473
9474         pr "  /**\n";
9475         pr "   * %s\n" shortdesc;
9476         pr "   * <p>\n";
9477         pr "   * %s\n" doc;
9478         pr "   * @throws LibGuestFSException\n";
9479         pr "   */\n";
9480         pr "  ";
9481       );
9482       generate_java_prototype ~public:true ~semicolon:false name style;
9483       pr "\n";
9484       pr "  {\n";
9485       pr "    if (g == 0)\n";
9486       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9487         name;
9488       pr "    ";
9489       if fst style <> RErr then pr "return ";
9490       pr "_%s " name;
9491       generate_java_call_args ~handle:"g" (snd style);
9492       pr ";\n";
9493       pr "  }\n";
9494       pr "  ";
9495       generate_java_prototype ~privat:true ~native:true name style;
9496       pr "\n";
9497       pr "\n";
9498   ) all_functions;
9499
9500   pr "}\n"
9501
9502 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9503 and generate_java_call_args ~handle args =
9504   pr "(%s" handle;
9505   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9506   pr ")"
9507
9508 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9509     ?(semicolon=true) name style =
9510   if privat then pr "private ";
9511   if public then pr "public ";
9512   if native then pr "native ";
9513
9514   (* return type *)
9515   (match fst style with
9516    | RErr -> pr "void ";
9517    | RInt _ -> pr "int ";
9518    | RInt64 _ -> pr "long ";
9519    | RBool _ -> pr "boolean ";
9520    | RConstString _ | RConstOptString _ | RString _
9521    | RBufferOut _ -> pr "String ";
9522    | RStringList _ -> pr "String[] ";
9523    | RStruct (_, typ) ->
9524        let name = java_name_of_struct typ in
9525        pr "%s " name;
9526    | RStructList (_, typ) ->
9527        let name = java_name_of_struct typ in
9528        pr "%s[] " name;
9529    | RHashtable _ -> pr "HashMap<String,String> ";
9530   );
9531
9532   if native then pr "_%s " name else pr "%s " name;
9533   pr "(";
9534   let needs_comma = ref false in
9535   if native then (
9536     pr "long g";
9537     needs_comma := true
9538   );
9539
9540   (* args *)
9541   List.iter (
9542     fun arg ->
9543       if !needs_comma then pr ", ";
9544       needs_comma := true;
9545
9546       match arg with
9547       | Pathname n
9548       | Device n | Dev_or_Path n
9549       | String n
9550       | OptString n
9551       | FileIn n
9552       | FileOut n ->
9553           pr "String %s" n
9554       | StringList n | DeviceList n ->
9555           pr "String[] %s" n
9556       | Bool n ->
9557           pr "boolean %s" n
9558       | Int n ->
9559           pr "int %s" n
9560       | Int64 n ->
9561           pr "long %s" n
9562   ) (snd style);
9563
9564   pr ")\n";
9565   pr "    throws LibGuestFSException";
9566   if semicolon then pr ";"
9567
9568 and generate_java_struct jtyp cols () =
9569   generate_header CStyle LGPLv2plus;
9570
9571   pr "\
9572 package com.redhat.et.libguestfs;
9573
9574 /**
9575  * Libguestfs %s structure.
9576  *
9577  * @author rjones
9578  * @see GuestFS
9579  */
9580 public class %s {
9581 " jtyp jtyp;
9582
9583   List.iter (
9584     function
9585     | name, FString
9586     | name, FUUID
9587     | name, FBuffer -> pr "  public String %s;\n" name
9588     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9589     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9590     | name, FChar -> pr "  public char %s;\n" name
9591     | name, FOptPercent ->
9592         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9593         pr "  public float %s;\n" name
9594   ) cols;
9595
9596   pr "}\n"
9597
9598 and generate_java_c () =
9599   generate_header CStyle LGPLv2plus;
9600
9601   pr "\
9602 #include <stdio.h>
9603 #include <stdlib.h>
9604 #include <string.h>
9605
9606 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9607 #include \"guestfs.h\"
9608
9609 /* Note that this function returns.  The exception is not thrown
9610  * until after the wrapper function returns.
9611  */
9612 static void
9613 throw_exception (JNIEnv *env, const char *msg)
9614 {
9615   jclass cl;
9616   cl = (*env)->FindClass (env,
9617                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9618   (*env)->ThrowNew (env, cl, msg);
9619 }
9620
9621 JNIEXPORT jlong JNICALL
9622 Java_com_redhat_et_libguestfs_GuestFS__1create
9623   (JNIEnv *env, jobject obj)
9624 {
9625   guestfs_h *g;
9626
9627   g = guestfs_create ();
9628   if (g == NULL) {
9629     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9630     return 0;
9631   }
9632   guestfs_set_error_handler (g, NULL, NULL);
9633   return (jlong) (long) g;
9634 }
9635
9636 JNIEXPORT void JNICALL
9637 Java_com_redhat_et_libguestfs_GuestFS__1close
9638   (JNIEnv *env, jobject obj, jlong jg)
9639 {
9640   guestfs_h *g = (guestfs_h *) (long) jg;
9641   guestfs_close (g);
9642 }
9643
9644 ";
9645
9646   List.iter (
9647     fun (name, style, _, _, _, _, _) ->
9648       pr "JNIEXPORT ";
9649       (match fst style with
9650        | RErr -> pr "void ";
9651        | RInt _ -> pr "jint ";
9652        | RInt64 _ -> pr "jlong ";
9653        | RBool _ -> pr "jboolean ";
9654        | RConstString _ | RConstOptString _ | RString _
9655        | RBufferOut _ -> pr "jstring ";
9656        | RStruct _ | RHashtable _ ->
9657            pr "jobject ";
9658        | RStringList _ | RStructList _ ->
9659            pr "jobjectArray ";
9660       );
9661       pr "JNICALL\n";
9662       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9663       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9664       pr "\n";
9665       pr "  (JNIEnv *env, jobject obj, jlong jg";
9666       List.iter (
9667         function
9668         | Pathname n
9669         | Device n | Dev_or_Path n
9670         | String n
9671         | OptString n
9672         | FileIn n
9673         | FileOut n ->
9674             pr ", jstring j%s" n
9675         | StringList n | DeviceList n ->
9676             pr ", jobjectArray j%s" n
9677         | Bool n ->
9678             pr ", jboolean j%s" n
9679         | Int n ->
9680             pr ", jint j%s" n
9681         | Int64 n ->
9682             pr ", jlong j%s" n
9683       ) (snd style);
9684       pr ")\n";
9685       pr "{\n";
9686       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9687       let error_code, no_ret =
9688         match fst style with
9689         | RErr -> pr "  int r;\n"; "-1", ""
9690         | RBool _
9691         | RInt _ -> pr "  int r;\n"; "-1", "0"
9692         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9693         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9694         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9695         | RString _ ->
9696             pr "  jstring jr;\n";
9697             pr "  char *r;\n"; "NULL", "NULL"
9698         | RStringList _ ->
9699             pr "  jobjectArray jr;\n";
9700             pr "  int r_len;\n";
9701             pr "  jclass cl;\n";
9702             pr "  jstring jstr;\n";
9703             pr "  char **r;\n"; "NULL", "NULL"
9704         | RStruct (_, typ) ->
9705             pr "  jobject jr;\n";
9706             pr "  jclass cl;\n";
9707             pr "  jfieldID fl;\n";
9708             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9709         | RStructList (_, typ) ->
9710             pr "  jobjectArray jr;\n";
9711             pr "  jclass cl;\n";
9712             pr "  jfieldID fl;\n";
9713             pr "  jobject jfl;\n";
9714             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9715         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9716         | RBufferOut _ ->
9717             pr "  jstring jr;\n";
9718             pr "  char *r;\n";
9719             pr "  size_t size;\n";
9720             "NULL", "NULL" in
9721       List.iter (
9722         function
9723         | Pathname n
9724         | Device n | Dev_or_Path n
9725         | String n
9726         | OptString n
9727         | FileIn n
9728         | FileOut n ->
9729             pr "  const char *%s;\n" n
9730         | StringList n | DeviceList n ->
9731             pr "  int %s_len;\n" n;
9732             pr "  const char **%s;\n" n
9733         | Bool n
9734         | Int n ->
9735             pr "  int %s;\n" n
9736         | Int64 n ->
9737             pr "  int64_t %s;\n" n
9738       ) (snd style);
9739
9740       let needs_i =
9741         (match fst style with
9742          | RStringList _ | RStructList _ -> true
9743          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9744          | RConstOptString _
9745          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9746           List.exists (function
9747                        | StringList _ -> true
9748                        | DeviceList _ -> true
9749                        | _ -> false) (snd style) in
9750       if needs_i then
9751         pr "  int i;\n";
9752
9753       pr "\n";
9754
9755       (* Get the parameters. *)
9756       List.iter (
9757         function
9758         | Pathname n
9759         | Device n | Dev_or_Path n
9760         | String n
9761         | FileIn n
9762         | FileOut n ->
9763             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9764         | OptString n ->
9765             (* This is completely undocumented, but Java null becomes
9766              * a NULL parameter.
9767              *)
9768             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9769         | StringList n | DeviceList n ->
9770             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9771             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9772             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9773             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9774               n;
9775             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9776             pr "  }\n";
9777             pr "  %s[%s_len] = NULL;\n" n n;
9778         | Bool n
9779         | Int n
9780         | Int64 n ->
9781             pr "  %s = j%s;\n" n n
9782       ) (snd style);
9783
9784       (* Make the call. *)
9785       pr "  r = guestfs_%s " name;
9786       generate_c_call_args ~handle:"g" style;
9787       pr ";\n";
9788
9789       (* Release the parameters. *)
9790       List.iter (
9791         function
9792         | Pathname n
9793         | Device n | Dev_or_Path n
9794         | String n
9795         | FileIn n
9796         | FileOut n ->
9797             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9798         | OptString n ->
9799             pr "  if (j%s)\n" n;
9800             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9801         | StringList n | DeviceList n ->
9802             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9803             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9804               n;
9805             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9806             pr "  }\n";
9807             pr "  free (%s);\n" n
9808         | Bool n
9809         | Int n
9810         | Int64 n -> ()
9811       ) (snd style);
9812
9813       (* Check for errors. *)
9814       pr "  if (r == %s) {\n" error_code;
9815       pr "    throw_exception (env, guestfs_last_error (g));\n";
9816       pr "    return %s;\n" no_ret;
9817       pr "  }\n";
9818
9819       (* Return value. *)
9820       (match fst style with
9821        | RErr -> ()
9822        | RInt _ -> pr "  return (jint) r;\n"
9823        | RBool _ -> pr "  return (jboolean) r;\n"
9824        | RInt64 _ -> pr "  return (jlong) r;\n"
9825        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9826        | RConstOptString _ ->
9827            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9828        | RString _ ->
9829            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9830            pr "  free (r);\n";
9831            pr "  return jr;\n"
9832        | RStringList _ ->
9833            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9834            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9835            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9836            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9837            pr "  for (i = 0; i < r_len; ++i) {\n";
9838            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9839            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9840            pr "    free (r[i]);\n";
9841            pr "  }\n";
9842            pr "  free (r);\n";
9843            pr "  return jr;\n"
9844        | RStruct (_, typ) ->
9845            let jtyp = java_name_of_struct typ in
9846            let cols = cols_of_struct typ in
9847            generate_java_struct_return typ jtyp cols
9848        | RStructList (_, typ) ->
9849            let jtyp = java_name_of_struct typ in
9850            let cols = cols_of_struct typ in
9851            generate_java_struct_list_return typ jtyp cols
9852        | RHashtable _ ->
9853            (* XXX *)
9854            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9855            pr "  return NULL;\n"
9856        | RBufferOut _ ->
9857            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9858            pr "  free (r);\n";
9859            pr "  return jr;\n"
9860       );
9861
9862       pr "}\n";
9863       pr "\n"
9864   ) all_functions
9865
9866 and generate_java_struct_return typ jtyp cols =
9867   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9868   pr "  jr = (*env)->AllocObject (env, cl);\n";
9869   List.iter (
9870     function
9871     | name, FString ->
9872         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9873         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9874     | name, FUUID ->
9875         pr "  {\n";
9876         pr "    char s[33];\n";
9877         pr "    memcpy (s, r->%s, 32);\n" name;
9878         pr "    s[32] = 0;\n";
9879         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9880         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9881         pr "  }\n";
9882     | name, FBuffer ->
9883         pr "  {\n";
9884         pr "    int len = r->%s_len;\n" name;
9885         pr "    char s[len+1];\n";
9886         pr "    memcpy (s, r->%s, len);\n" name;
9887         pr "    s[len] = 0;\n";
9888         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9889         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9890         pr "  }\n";
9891     | name, (FBytes|FUInt64|FInt64) ->
9892         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9893         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9894     | name, (FUInt32|FInt32) ->
9895         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9896         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9897     | name, FOptPercent ->
9898         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9899         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9900     | name, FChar ->
9901         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9902         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9903   ) cols;
9904   pr "  free (r);\n";
9905   pr "  return jr;\n"
9906
9907 and generate_java_struct_list_return typ jtyp cols =
9908   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9909   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9910   pr "  for (i = 0; i < r->len; ++i) {\n";
9911   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9912   List.iter (
9913     function
9914     | name, FString ->
9915         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9916         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9917     | name, FUUID ->
9918         pr "    {\n";
9919         pr "      char s[33];\n";
9920         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9921         pr "      s[32] = 0;\n";
9922         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9923         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9924         pr "    }\n";
9925     | name, FBuffer ->
9926         pr "    {\n";
9927         pr "      int len = r->val[i].%s_len;\n" name;
9928         pr "      char s[len+1];\n";
9929         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9930         pr "      s[len] = 0;\n";
9931         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9932         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9933         pr "    }\n";
9934     | name, (FBytes|FUInt64|FInt64) ->
9935         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9936         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9937     | name, (FUInt32|FInt32) ->
9938         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9939         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9940     | name, FOptPercent ->
9941         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9942         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9943     | name, FChar ->
9944         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9945         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9946   ) cols;
9947   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9948   pr "  }\n";
9949   pr "  guestfs_free_%s_list (r);\n" typ;
9950   pr "  return jr;\n"
9951
9952 and generate_java_makefile_inc () =
9953   generate_header HashStyle GPLv2plus;
9954
9955   pr "java_built_sources = \\\n";
9956   List.iter (
9957     fun (typ, jtyp) ->
9958         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9959   ) java_structs;
9960   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9961
9962 and generate_haskell_hs () =
9963   generate_header HaskellStyle LGPLv2plus;
9964
9965   (* XXX We only know how to generate partial FFI for Haskell
9966    * at the moment.  Please help out!
9967    *)
9968   let can_generate style =
9969     match style with
9970     | RErr, _
9971     | RInt _, _
9972     | RInt64 _, _ -> true
9973     | RBool _, _
9974     | RConstString _, _
9975     | RConstOptString _, _
9976     | RString _, _
9977     | RStringList _, _
9978     | RStruct _, _
9979     | RStructList _, _
9980     | RHashtable _, _
9981     | RBufferOut _, _ -> false in
9982
9983   pr "\
9984 {-# INCLUDE <guestfs.h> #-}
9985 {-# LANGUAGE ForeignFunctionInterface #-}
9986
9987 module Guestfs (
9988   create";
9989
9990   (* List out the names of the actions we want to export. *)
9991   List.iter (
9992     fun (name, style, _, _, _, _, _) ->
9993       if can_generate style then pr ",\n  %s" name
9994   ) all_functions;
9995
9996   pr "
9997   ) where
9998
9999 -- Unfortunately some symbols duplicate ones already present
10000 -- in Prelude.  We don't know which, so we hard-code a list
10001 -- here.
10002 import Prelude hiding (truncate)
10003
10004 import Foreign
10005 import Foreign.C
10006 import Foreign.C.Types
10007 import IO
10008 import Control.Exception
10009 import Data.Typeable
10010
10011 data GuestfsS = GuestfsS            -- represents the opaque C struct
10012 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10013 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10014
10015 -- XXX define properly later XXX
10016 data PV = PV
10017 data VG = VG
10018 data LV = LV
10019 data IntBool = IntBool
10020 data Stat = Stat
10021 data StatVFS = StatVFS
10022 data Hashtable = Hashtable
10023
10024 foreign import ccall unsafe \"guestfs_create\" c_create
10025   :: IO GuestfsP
10026 foreign import ccall unsafe \"&guestfs_close\" c_close
10027   :: FunPtr (GuestfsP -> IO ())
10028 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10029   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10030
10031 create :: IO GuestfsH
10032 create = do
10033   p <- c_create
10034   c_set_error_handler p nullPtr nullPtr
10035   h <- newForeignPtr c_close p
10036   return h
10037
10038 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10039   :: GuestfsP -> IO CString
10040
10041 -- last_error :: GuestfsH -> IO (Maybe String)
10042 -- last_error h = do
10043 --   str <- withForeignPtr h (\\p -> c_last_error p)
10044 --   maybePeek peekCString str
10045
10046 last_error :: GuestfsH -> IO (String)
10047 last_error h = do
10048   str <- withForeignPtr h (\\p -> c_last_error p)
10049   if (str == nullPtr)
10050     then return \"no error\"
10051     else peekCString str
10052
10053 ";
10054
10055   (* Generate wrappers for each foreign function. *)
10056   List.iter (
10057     fun (name, style, _, _, _, _, _) ->
10058       if can_generate style then (
10059         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10060         pr "  :: ";
10061         generate_haskell_prototype ~handle:"GuestfsP" style;
10062         pr "\n";
10063         pr "\n";
10064         pr "%s :: " name;
10065         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10066         pr "\n";
10067         pr "%s %s = do\n" name
10068           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10069         pr "  r <- ";
10070         (* Convert pointer arguments using with* functions. *)
10071         List.iter (
10072           function
10073           | FileIn n
10074           | FileOut n
10075           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10076           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10077           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10078           | Bool _ | Int _ | Int64 _ -> ()
10079         ) (snd style);
10080         (* Convert integer arguments. *)
10081         let args =
10082           List.map (
10083             function
10084             | Bool n -> sprintf "(fromBool %s)" n
10085             | Int n -> sprintf "(fromIntegral %s)" n
10086             | Int64 n -> sprintf "(fromIntegral %s)" n
10087             | FileIn n | FileOut n
10088             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10089           ) (snd style) in
10090         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10091           (String.concat " " ("p" :: args));
10092         (match fst style with
10093          | RErr | RInt _ | RInt64 _ | RBool _ ->
10094              pr "  if (r == -1)\n";
10095              pr "    then do\n";
10096              pr "      err <- last_error h\n";
10097              pr "      fail err\n";
10098          | RConstString _ | RConstOptString _ | RString _
10099          | RStringList _ | RStruct _
10100          | RStructList _ | RHashtable _ | RBufferOut _ ->
10101              pr "  if (r == nullPtr)\n";
10102              pr "    then do\n";
10103              pr "      err <- last_error h\n";
10104              pr "      fail err\n";
10105         );
10106         (match fst style with
10107          | RErr ->
10108              pr "    else return ()\n"
10109          | RInt _ ->
10110              pr "    else return (fromIntegral r)\n"
10111          | RInt64 _ ->
10112              pr "    else return (fromIntegral r)\n"
10113          | RBool _ ->
10114              pr "    else return (toBool r)\n"
10115          | RConstString _
10116          | RConstOptString _
10117          | RString _
10118          | RStringList _
10119          | RStruct _
10120          | RStructList _
10121          | RHashtable _
10122          | RBufferOut _ ->
10123              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10124         );
10125         pr "\n";
10126       )
10127   ) all_functions
10128
10129 and generate_haskell_prototype ~handle ?(hs = false) style =
10130   pr "%s -> " handle;
10131   let string = if hs then "String" else "CString" in
10132   let int = if hs then "Int" else "CInt" in
10133   let bool = if hs then "Bool" else "CInt" in
10134   let int64 = if hs then "Integer" else "Int64" in
10135   List.iter (
10136     fun arg ->
10137       (match arg with
10138        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10139        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10140        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10141        | Bool _ -> pr "%s" bool
10142        | Int _ -> pr "%s" int
10143        | Int64 _ -> pr "%s" int
10144        | FileIn _ -> pr "%s" string
10145        | FileOut _ -> pr "%s" string
10146       );
10147       pr " -> ";
10148   ) (snd style);
10149   pr "IO (";
10150   (match fst style with
10151    | RErr -> if not hs then pr "CInt"
10152    | RInt _ -> pr "%s" int
10153    | RInt64 _ -> pr "%s" int64
10154    | RBool _ -> pr "%s" bool
10155    | RConstString _ -> pr "%s" string
10156    | RConstOptString _ -> pr "Maybe %s" string
10157    | RString _ -> pr "%s" string
10158    | RStringList _ -> pr "[%s]" string
10159    | RStruct (_, typ) ->
10160        let name = java_name_of_struct typ in
10161        pr "%s" name
10162    | RStructList (_, typ) ->
10163        let name = java_name_of_struct typ in
10164        pr "[%s]" name
10165    | RHashtable _ -> pr "Hashtable"
10166    | RBufferOut _ -> pr "%s" string
10167   );
10168   pr ")"
10169
10170 and generate_csharp () =
10171   generate_header CPlusPlusStyle LGPLv2plus;
10172
10173   (* XXX Make this configurable by the C# assembly users. *)
10174   let library = "libguestfs.so.0" in
10175
10176   pr "\
10177 // These C# bindings are highly experimental at present.
10178 //
10179 // Firstly they only work on Linux (ie. Mono).  In order to get them
10180 // to work on Windows (ie. .Net) you would need to port the library
10181 // itself to Windows first.
10182 //
10183 // The second issue is that some calls are known to be incorrect and
10184 // can cause Mono to segfault.  Particularly: calls which pass or
10185 // return string[], or return any structure value.  This is because
10186 // we haven't worked out the correct way to do this from C#.
10187 //
10188 // The third issue is that when compiling you get a lot of warnings.
10189 // We are not sure whether the warnings are important or not.
10190 //
10191 // Fourthly we do not routinely build or test these bindings as part
10192 // of the make && make check cycle, which means that regressions might
10193 // go unnoticed.
10194 //
10195 // Suggestions and patches are welcome.
10196
10197 // To compile:
10198 //
10199 // gmcs Libguestfs.cs
10200 // mono Libguestfs.exe
10201 //
10202 // (You'll probably want to add a Test class / static main function
10203 // otherwise this won't do anything useful).
10204
10205 using System;
10206 using System.IO;
10207 using System.Runtime.InteropServices;
10208 using System.Runtime.Serialization;
10209 using System.Collections;
10210
10211 namespace Guestfs
10212 {
10213   class Error : System.ApplicationException
10214   {
10215     public Error (string message) : base (message) {}
10216     protected Error (SerializationInfo info, StreamingContext context) {}
10217   }
10218
10219   class Guestfs
10220   {
10221     IntPtr _handle;
10222
10223     [DllImport (\"%s\")]
10224     static extern IntPtr guestfs_create ();
10225
10226     public Guestfs ()
10227     {
10228       _handle = guestfs_create ();
10229       if (_handle == IntPtr.Zero)
10230         throw new Error (\"could not create guestfs handle\");
10231     }
10232
10233     [DllImport (\"%s\")]
10234     static extern void guestfs_close (IntPtr h);
10235
10236     ~Guestfs ()
10237     {
10238       guestfs_close (_handle);
10239     }
10240
10241     [DllImport (\"%s\")]
10242     static extern string guestfs_last_error (IntPtr h);
10243
10244 " library library library;
10245
10246   (* Generate C# structure bindings.  We prefix struct names with
10247    * underscore because C# cannot have conflicting struct names and
10248    * method names (eg. "class stat" and "stat").
10249    *)
10250   List.iter (
10251     fun (typ, cols) ->
10252       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10253       pr "    public class _%s {\n" typ;
10254       List.iter (
10255         function
10256         | name, FChar -> pr "      char %s;\n" name
10257         | name, FString -> pr "      string %s;\n" name
10258         | name, FBuffer ->
10259             pr "      uint %s_len;\n" name;
10260             pr "      string %s;\n" name
10261         | name, FUUID ->
10262             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10263             pr "      string %s;\n" name
10264         | name, FUInt32 -> pr "      uint %s;\n" name
10265         | name, FInt32 -> pr "      int %s;\n" name
10266         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10267         | name, FInt64 -> pr "      long %s;\n" name
10268         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10269       ) cols;
10270       pr "    }\n";
10271       pr "\n"
10272   ) structs;
10273
10274   (* Generate C# function bindings. *)
10275   List.iter (
10276     fun (name, style, _, _, _, shortdesc, _) ->
10277       let rec csharp_return_type () =
10278         match fst style with
10279         | RErr -> "void"
10280         | RBool n -> "bool"
10281         | RInt n -> "int"
10282         | RInt64 n -> "long"
10283         | RConstString n
10284         | RConstOptString n
10285         | RString n
10286         | RBufferOut n -> "string"
10287         | RStruct (_,n) -> "_" ^ n
10288         | RHashtable n -> "Hashtable"
10289         | RStringList n -> "string[]"
10290         | RStructList (_,n) -> sprintf "_%s[]" n
10291
10292       and c_return_type () =
10293         match fst style with
10294         | RErr
10295         | RBool _
10296         | RInt _ -> "int"
10297         | RInt64 _ -> "long"
10298         | RConstString _
10299         | RConstOptString _
10300         | RString _
10301         | RBufferOut _ -> "string"
10302         | RStruct (_,n) -> "_" ^ n
10303         | RHashtable _
10304         | RStringList _ -> "string[]"
10305         | RStructList (_,n) -> sprintf "_%s[]" n
10306
10307       and c_error_comparison () =
10308         match fst style with
10309         | RErr
10310         | RBool _
10311         | RInt _
10312         | RInt64 _ -> "== -1"
10313         | RConstString _
10314         | RConstOptString _
10315         | RString _
10316         | RBufferOut _
10317         | RStruct (_,_)
10318         | RHashtable _
10319         | RStringList _
10320         | RStructList (_,_) -> "== null"
10321
10322       and generate_extern_prototype () =
10323         pr "    static extern %s guestfs_%s (IntPtr h"
10324           (c_return_type ()) name;
10325         List.iter (
10326           function
10327           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10328           | FileIn n | FileOut n ->
10329               pr ", [In] string %s" n
10330           | StringList n | DeviceList n ->
10331               pr ", [In] string[] %s" n
10332           | Bool n ->
10333               pr ", bool %s" n
10334           | Int n ->
10335               pr ", int %s" n
10336           | Int64 n ->
10337               pr ", long %s" n
10338         ) (snd style);
10339         pr ");\n"
10340
10341       and generate_public_prototype () =
10342         pr "    public %s %s (" (csharp_return_type ()) name;
10343         let comma = ref false in
10344         let next () =
10345           if !comma then pr ", ";
10346           comma := true
10347         in
10348         List.iter (
10349           function
10350           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10351           | FileIn n | FileOut n ->
10352               next (); pr "string %s" n
10353           | StringList n | DeviceList n ->
10354               next (); pr "string[] %s" n
10355           | Bool n ->
10356               next (); pr "bool %s" n
10357           | Int n ->
10358               next (); pr "int %s" n
10359           | Int64 n ->
10360               next (); pr "long %s" n
10361         ) (snd style);
10362         pr ")\n"
10363
10364       and generate_call () =
10365         pr "guestfs_%s (_handle" name;
10366         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10367         pr ");\n";
10368       in
10369
10370       pr "    [DllImport (\"%s\")]\n" library;
10371       generate_extern_prototype ();
10372       pr "\n";
10373       pr "    /// <summary>\n";
10374       pr "    /// %s\n" shortdesc;
10375       pr "    /// </summary>\n";
10376       generate_public_prototype ();
10377       pr "    {\n";
10378       pr "      %s r;\n" (c_return_type ());
10379       pr "      r = ";
10380       generate_call ();
10381       pr "      if (r %s)\n" (c_error_comparison ());
10382       pr "        throw new Error (guestfs_last_error (_handle));\n";
10383       (match fst style with
10384        | RErr -> ()
10385        | RBool _ ->
10386            pr "      return r != 0 ? true : false;\n"
10387        | RHashtable _ ->
10388            pr "      Hashtable rr = new Hashtable ();\n";
10389            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10390            pr "        rr.Add (r[i], r[i+1]);\n";
10391            pr "      return rr;\n"
10392        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10393        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10394        | RStructList _ ->
10395            pr "      return r;\n"
10396       );
10397       pr "    }\n";
10398       pr "\n";
10399   ) all_functions_sorted;
10400
10401   pr "  }
10402 }
10403 "
10404
10405 and generate_bindtests () =
10406   generate_header CStyle LGPLv2plus;
10407
10408   pr "\
10409 #include <stdio.h>
10410 #include <stdlib.h>
10411 #include <inttypes.h>
10412 #include <string.h>
10413
10414 #include \"guestfs.h\"
10415 #include \"guestfs-internal.h\"
10416 #include \"guestfs-internal-actions.h\"
10417 #include \"guestfs_protocol.h\"
10418
10419 #define error guestfs_error
10420 #define safe_calloc guestfs_safe_calloc
10421 #define safe_malloc guestfs_safe_malloc
10422
10423 static void
10424 print_strings (char *const *argv)
10425 {
10426   int argc;
10427
10428   printf (\"[\");
10429   for (argc = 0; argv[argc] != NULL; ++argc) {
10430     if (argc > 0) printf (\", \");
10431     printf (\"\\\"%%s\\\"\", argv[argc]);
10432   }
10433   printf (\"]\\n\");
10434 }
10435
10436 /* The test0 function prints its parameters to stdout. */
10437 ";
10438
10439   let test0, tests =
10440     match test_functions with
10441     | [] -> assert false
10442     | test0 :: tests -> test0, tests in
10443
10444   let () =
10445     let (name, style, _, _, _, _, _) = test0 in
10446     generate_prototype ~extern:false ~semicolon:false ~newline:true
10447       ~handle:"g" ~prefix:"guestfs__" name style;
10448     pr "{\n";
10449     List.iter (
10450       function
10451       | Pathname n
10452       | Device n | Dev_or_Path n
10453       | String n
10454       | FileIn n
10455       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10456       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10457       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10458       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10459       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10460       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10461     ) (snd style);
10462     pr "  /* Java changes stdout line buffering so we need this: */\n";
10463     pr "  fflush (stdout);\n";
10464     pr "  return 0;\n";
10465     pr "}\n";
10466     pr "\n" in
10467
10468   List.iter (
10469     fun (name, style, _, _, _, _, _) ->
10470       if String.sub name (String.length name - 3) 3 <> "err" then (
10471         pr "/* Test normal return. */\n";
10472         generate_prototype ~extern:false ~semicolon:false ~newline:true
10473           ~handle:"g" ~prefix:"guestfs__" name style;
10474         pr "{\n";
10475         (match fst style with
10476          | RErr ->
10477              pr "  return 0;\n"
10478          | RInt _ ->
10479              pr "  int r;\n";
10480              pr "  sscanf (val, \"%%d\", &r);\n";
10481              pr "  return r;\n"
10482          | RInt64 _ ->
10483              pr "  int64_t r;\n";
10484              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10485              pr "  return r;\n"
10486          | RBool _ ->
10487              pr "  return STREQ (val, \"true\");\n"
10488          | RConstString _
10489          | RConstOptString _ ->
10490              (* Can't return the input string here.  Return a static
10491               * string so we ensure we get a segfault if the caller
10492               * tries to free it.
10493               *)
10494              pr "  return \"static string\";\n"
10495          | RString _ ->
10496              pr "  return strdup (val);\n"
10497          | RStringList _ ->
10498              pr "  char **strs;\n";
10499              pr "  int n, i;\n";
10500              pr "  sscanf (val, \"%%d\", &n);\n";
10501              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10502              pr "  for (i = 0; i < n; ++i) {\n";
10503              pr "    strs[i] = safe_malloc (g, 16);\n";
10504              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10505              pr "  }\n";
10506              pr "  strs[n] = NULL;\n";
10507              pr "  return strs;\n"
10508          | RStruct (_, typ) ->
10509              pr "  struct guestfs_%s *r;\n" typ;
10510              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10511              pr "  return r;\n"
10512          | RStructList (_, typ) ->
10513              pr "  struct guestfs_%s_list *r;\n" typ;
10514              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10515              pr "  sscanf (val, \"%%d\", &r->len);\n";
10516              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10517              pr "  return r;\n"
10518          | RHashtable _ ->
10519              pr "  char **strs;\n";
10520              pr "  int n, i;\n";
10521              pr "  sscanf (val, \"%%d\", &n);\n";
10522              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10523              pr "  for (i = 0; i < n; ++i) {\n";
10524              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10525              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10526              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10527              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10528              pr "  }\n";
10529              pr "  strs[n*2] = NULL;\n";
10530              pr "  return strs;\n"
10531          | RBufferOut _ ->
10532              pr "  return strdup (val);\n"
10533         );
10534         pr "}\n";
10535         pr "\n"
10536       ) else (
10537         pr "/* Test error return. */\n";
10538         generate_prototype ~extern:false ~semicolon:false ~newline:true
10539           ~handle:"g" ~prefix:"guestfs__" name style;
10540         pr "{\n";
10541         pr "  error (g, \"error\");\n";
10542         (match fst style with
10543          | RErr | RInt _ | RInt64 _ | RBool _ ->
10544              pr "  return -1;\n"
10545          | RConstString _ | RConstOptString _
10546          | RString _ | RStringList _ | RStruct _
10547          | RStructList _
10548          | RHashtable _
10549          | RBufferOut _ ->
10550              pr "  return NULL;\n"
10551         );
10552         pr "}\n";
10553         pr "\n"
10554       )
10555   ) tests
10556
10557 and generate_ocaml_bindtests () =
10558   generate_header OCamlStyle GPLv2plus;
10559
10560   pr "\
10561 let () =
10562   let g = Guestfs.create () in
10563 ";
10564
10565   let mkargs args =
10566     String.concat " " (
10567       List.map (
10568         function
10569         | CallString s -> "\"" ^ s ^ "\""
10570         | CallOptString None -> "None"
10571         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10572         | CallStringList xs ->
10573             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10574         | CallInt i when i >= 0 -> string_of_int i
10575         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10576         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10577         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10578         | CallBool b -> string_of_bool b
10579       ) args
10580     )
10581   in
10582
10583   generate_lang_bindtests (
10584     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10585   );
10586
10587   pr "print_endline \"EOF\"\n"
10588
10589 and generate_perl_bindtests () =
10590   pr "#!/usr/bin/perl -w\n";
10591   generate_header HashStyle GPLv2plus;
10592
10593   pr "\
10594 use strict;
10595
10596 use Sys::Guestfs;
10597
10598 my $g = Sys::Guestfs->new ();
10599 ";
10600
10601   let mkargs args =
10602     String.concat ", " (
10603       List.map (
10604         function
10605         | CallString s -> "\"" ^ s ^ "\""
10606         | CallOptString None -> "undef"
10607         | CallOptString (Some s) -> sprintf "\"%s\"" s
10608         | CallStringList xs ->
10609             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10610         | CallInt i -> string_of_int i
10611         | CallInt64 i -> Int64.to_string i
10612         | CallBool b -> if b then "1" else "0"
10613       ) args
10614     )
10615   in
10616
10617   generate_lang_bindtests (
10618     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10619   );
10620
10621   pr "print \"EOF\\n\"\n"
10622
10623 and generate_python_bindtests () =
10624   generate_header HashStyle GPLv2plus;
10625
10626   pr "\
10627 import guestfs
10628
10629 g = guestfs.GuestFS ()
10630 ";
10631
10632   let mkargs args =
10633     String.concat ", " (
10634       List.map (
10635         function
10636         | CallString s -> "\"" ^ s ^ "\""
10637         | CallOptString None -> "None"
10638         | CallOptString (Some s) -> sprintf "\"%s\"" s
10639         | CallStringList xs ->
10640             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10641         | CallInt i -> string_of_int i
10642         | CallInt64 i -> Int64.to_string i
10643         | CallBool b -> if b then "1" else "0"
10644       ) args
10645     )
10646   in
10647
10648   generate_lang_bindtests (
10649     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10650   );
10651
10652   pr "print \"EOF\"\n"
10653
10654 and generate_ruby_bindtests () =
10655   generate_header HashStyle GPLv2plus;
10656
10657   pr "\
10658 require 'guestfs'
10659
10660 g = Guestfs::create()
10661 ";
10662
10663   let mkargs args =
10664     String.concat ", " (
10665       List.map (
10666         function
10667         | CallString s -> "\"" ^ s ^ "\""
10668         | CallOptString None -> "nil"
10669         | CallOptString (Some s) -> sprintf "\"%s\"" s
10670         | CallStringList xs ->
10671             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10672         | CallInt i -> string_of_int i
10673         | CallInt64 i -> Int64.to_string i
10674         | CallBool b -> string_of_bool b
10675       ) args
10676     )
10677   in
10678
10679   generate_lang_bindtests (
10680     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10681   );
10682
10683   pr "print \"EOF\\n\"\n"
10684
10685 and generate_java_bindtests () =
10686   generate_header CStyle GPLv2plus;
10687
10688   pr "\
10689 import com.redhat.et.libguestfs.*;
10690
10691 public class Bindtests {
10692     public static void main (String[] argv)
10693     {
10694         try {
10695             GuestFS g = new GuestFS ();
10696 ";
10697
10698   let mkargs args =
10699     String.concat ", " (
10700       List.map (
10701         function
10702         | CallString s -> "\"" ^ s ^ "\""
10703         | CallOptString None -> "null"
10704         | CallOptString (Some s) -> sprintf "\"%s\"" s
10705         | CallStringList xs ->
10706             "new String[]{" ^
10707               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10708         | CallInt i -> string_of_int i
10709         | CallInt64 i -> Int64.to_string i
10710         | CallBool b -> string_of_bool b
10711       ) args
10712     )
10713   in
10714
10715   generate_lang_bindtests (
10716     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10717   );
10718
10719   pr "
10720             System.out.println (\"EOF\");
10721         }
10722         catch (Exception exn) {
10723             System.err.println (exn);
10724             System.exit (1);
10725         }
10726     }
10727 }
10728 "
10729
10730 and generate_haskell_bindtests () =
10731   generate_header HaskellStyle GPLv2plus;
10732
10733   pr "\
10734 module Bindtests where
10735 import qualified Guestfs
10736
10737 main = do
10738   g <- Guestfs.create
10739 ";
10740
10741   let mkargs args =
10742     String.concat " " (
10743       List.map (
10744         function
10745         | CallString s -> "\"" ^ s ^ "\""
10746         | CallOptString None -> "Nothing"
10747         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10748         | CallStringList xs ->
10749             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10750         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10751         | CallInt i -> string_of_int i
10752         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10753         | CallInt64 i -> Int64.to_string i
10754         | CallBool true -> "True"
10755         | CallBool false -> "False"
10756       ) args
10757     )
10758   in
10759
10760   generate_lang_bindtests (
10761     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10762   );
10763
10764   pr "  putStrLn \"EOF\"\n"
10765
10766 (* Language-independent bindings tests - we do it this way to
10767  * ensure there is parity in testing bindings across all languages.
10768  *)
10769 and generate_lang_bindtests call =
10770   call "test0" [CallString "abc"; CallOptString (Some "def");
10771                 CallStringList []; CallBool false;
10772                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10773   call "test0" [CallString "abc"; CallOptString None;
10774                 CallStringList []; CallBool false;
10775                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10776   call "test0" [CallString ""; CallOptString (Some "def");
10777                 CallStringList []; CallBool false;
10778                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10779   call "test0" [CallString ""; CallOptString (Some "");
10780                 CallStringList []; CallBool false;
10781                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10782   call "test0" [CallString "abc"; CallOptString (Some "def");
10783                 CallStringList ["1"]; CallBool false;
10784                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10785   call "test0" [CallString "abc"; CallOptString (Some "def");
10786                 CallStringList ["1"; "2"]; CallBool false;
10787                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10788   call "test0" [CallString "abc"; CallOptString (Some "def");
10789                 CallStringList ["1"]; CallBool true;
10790                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10791   call "test0" [CallString "abc"; CallOptString (Some "def");
10792                 CallStringList ["1"]; CallBool false;
10793                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10794   call "test0" [CallString "abc"; CallOptString (Some "def");
10795                 CallStringList ["1"]; CallBool false;
10796                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10797   call "test0" [CallString "abc"; CallOptString (Some "def");
10798                 CallStringList ["1"]; CallBool false;
10799                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10800   call "test0" [CallString "abc"; CallOptString (Some "def");
10801                 CallStringList ["1"]; CallBool false;
10802                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10803   call "test0" [CallString "abc"; CallOptString (Some "def");
10804                 CallStringList ["1"]; CallBool false;
10805                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10806   call "test0" [CallString "abc"; CallOptString (Some "def");
10807                 CallStringList ["1"]; CallBool false;
10808                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10809
10810 (* XXX Add here tests of the return and error functions. *)
10811
10812 (* Code to generator bindings for virt-inspector.  Currently only
10813  * implemented for OCaml code (for virt-p2v 2.0).
10814  *)
10815 let rng_input = "inspector/virt-inspector.rng"
10816
10817 (* Read the input file and parse it into internal structures.  This is
10818  * by no means a complete RELAX NG parser, but is just enough to be
10819  * able to parse the specific input file.
10820  *)
10821 type rng =
10822   | Element of string * rng list        (* <element name=name/> *)
10823   | Attribute of string * rng list        (* <attribute name=name/> *)
10824   | Interleave of rng list                (* <interleave/> *)
10825   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10826   | OneOrMore of rng                        (* <oneOrMore/> *)
10827   | Optional of rng                        (* <optional/> *)
10828   | Choice of string list                (* <choice><value/>*</choice> *)
10829   | Value of string                        (* <value>str</value> *)
10830   | Text                                (* <text/> *)
10831
10832 let rec string_of_rng = function
10833   | Element (name, xs) ->
10834       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10835   | Attribute (name, xs) ->
10836       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10837   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10838   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10839   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10840   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10841   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10842   | Value value -> "Value \"" ^ value ^ "\""
10843   | Text -> "Text"
10844
10845 and string_of_rng_list xs =
10846   String.concat ", " (List.map string_of_rng xs)
10847
10848 let rec parse_rng ?defines context = function
10849   | [] -> []
10850   | Xml.Element ("element", ["name", name], children) :: rest ->
10851       Element (name, parse_rng ?defines context children)
10852       :: parse_rng ?defines context rest
10853   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10854       Attribute (name, parse_rng ?defines context children)
10855       :: parse_rng ?defines context rest
10856   | Xml.Element ("interleave", [], children) :: rest ->
10857       Interleave (parse_rng ?defines context children)
10858       :: parse_rng ?defines context rest
10859   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10860       let rng = parse_rng ?defines context [child] in
10861       (match rng with
10862        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10863        | _ ->
10864            failwithf "%s: <zeroOrMore> contains more than one child element"
10865              context
10866       )
10867   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10868       let rng = parse_rng ?defines context [child] in
10869       (match rng with
10870        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10871        | _ ->
10872            failwithf "%s: <oneOrMore> contains more than one child element"
10873              context
10874       )
10875   | Xml.Element ("optional", [], [child]) :: rest ->
10876       let rng = parse_rng ?defines context [child] in
10877       (match rng with
10878        | [child] -> Optional child :: parse_rng ?defines context rest
10879        | _ ->
10880            failwithf "%s: <optional> contains more than one child element"
10881              context
10882       )
10883   | Xml.Element ("choice", [], children) :: rest ->
10884       let values = List.map (
10885         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10886         | _ ->
10887             failwithf "%s: can't handle anything except <value> in <choice>"
10888               context
10889       ) children in
10890       Choice values
10891       :: parse_rng ?defines context rest
10892   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10893       Value value :: parse_rng ?defines context rest
10894   | Xml.Element ("text", [], []) :: rest ->
10895       Text :: parse_rng ?defines context rest
10896   | Xml.Element ("ref", ["name", name], []) :: rest ->
10897       (* Look up the reference.  Because of limitations in this parser,
10898        * we can't handle arbitrarily nested <ref> yet.  You can only
10899        * use <ref> from inside <start>.
10900        *)
10901       (match defines with
10902        | None ->
10903            failwithf "%s: contains <ref>, but no refs are defined yet" context
10904        | Some map ->
10905            let rng = StringMap.find name map in
10906            rng @ parse_rng ?defines context rest
10907       )
10908   | x :: _ ->
10909       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10910
10911 let grammar =
10912   let xml = Xml.parse_file rng_input in
10913   match xml with
10914   | Xml.Element ("grammar", _,
10915                  Xml.Element ("start", _, gram) :: defines) ->
10916       (* The <define/> elements are referenced in the <start> section,
10917        * so build a map of those first.
10918        *)
10919       let defines = List.fold_left (
10920         fun map ->
10921           function Xml.Element ("define", ["name", name], defn) ->
10922             StringMap.add name defn map
10923           | _ ->
10924               failwithf "%s: expected <define name=name/>" rng_input
10925       ) StringMap.empty defines in
10926       let defines = StringMap.mapi parse_rng defines in
10927
10928       (* Parse the <start> clause, passing the defines. *)
10929       parse_rng ~defines "<start>" gram
10930   | _ ->
10931       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10932         rng_input
10933
10934 let name_of_field = function
10935   | Element (name, _) | Attribute (name, _)
10936   | ZeroOrMore (Element (name, _))
10937   | OneOrMore (Element (name, _))
10938   | Optional (Element (name, _)) -> name
10939   | Optional (Attribute (name, _)) -> name
10940   | Text -> (* an unnamed field in an element *)
10941       "data"
10942   | rng ->
10943       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10944
10945 (* At the moment this function only generates OCaml types.  However we
10946  * should parameterize it later so it can generate types/structs in a
10947  * variety of languages.
10948  *)
10949 let generate_types xs =
10950   (* A simple type is one that can be printed out directly, eg.
10951    * "string option".  A complex type is one which has a name and has
10952    * to be defined via another toplevel definition, eg. a struct.
10953    *
10954    * generate_type generates code for either simple or complex types.
10955    * In the simple case, it returns the string ("string option").  In
10956    * the complex case, it returns the name ("mountpoint").  In the
10957    * complex case it has to print out the definition before returning,
10958    * so it should only be called when we are at the beginning of a
10959    * new line (BOL context).
10960    *)
10961   let rec generate_type = function
10962     | Text ->                                (* string *)
10963         "string", true
10964     | Choice values ->                        (* [`val1|`val2|...] *)
10965         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10966     | ZeroOrMore rng ->                        (* <rng> list *)
10967         let t, is_simple = generate_type rng in
10968         t ^ " list (* 0 or more *)", is_simple
10969     | OneOrMore rng ->                        (* <rng> list *)
10970         let t, is_simple = generate_type rng in
10971         t ^ " list (* 1 or more *)", is_simple
10972                                         (* virt-inspector hack: bool *)
10973     | Optional (Attribute (name, [Value "1"])) ->
10974         "bool", true
10975     | Optional rng ->                        (* <rng> list *)
10976         let t, is_simple = generate_type rng in
10977         t ^ " option", is_simple
10978                                         (* type name = { fields ... } *)
10979     | Element (name, fields) when is_attrs_interleave fields ->
10980         generate_type_struct name (get_attrs_interleave fields)
10981     | Element (name, [field])                (* type name = field *)
10982     | Attribute (name, [field]) ->
10983         let t, is_simple = generate_type field in
10984         if is_simple then (t, true)
10985         else (
10986           pr "type %s = %s\n" name t;
10987           name, false
10988         )
10989     | Element (name, fields) ->              (* type name = { fields ... } *)
10990         generate_type_struct name fields
10991     | rng ->
10992         failwithf "generate_type failed at: %s" (string_of_rng rng)
10993
10994   and is_attrs_interleave = function
10995     | [Interleave _] -> true
10996     | Attribute _ :: fields -> is_attrs_interleave fields
10997     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
10998     | _ -> false
10999
11000   and get_attrs_interleave = function
11001     | [Interleave fields] -> fields
11002     | ((Attribute _) as field) :: fields
11003     | ((Optional (Attribute _)) as field) :: fields ->
11004         field :: get_attrs_interleave fields
11005     | _ -> assert false
11006
11007   and generate_types xs =
11008     List.iter (fun x -> ignore (generate_type x)) xs
11009
11010   and generate_type_struct name fields =
11011     (* Calculate the types of the fields first.  We have to do this
11012      * before printing anything so we are still in BOL context.
11013      *)
11014     let types = List.map fst (List.map generate_type fields) in
11015
11016     (* Special case of a struct containing just a string and another
11017      * field.  Turn it into an assoc list.
11018      *)
11019     match types with
11020     | ["string"; other] ->
11021         let fname1, fname2 =
11022           match fields with
11023           | [f1; f2] -> name_of_field f1, name_of_field f2
11024           | _ -> assert false in
11025         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11026         name, false
11027
11028     | types ->
11029         pr "type %s = {\n" name;
11030         List.iter (
11031           fun (field, ftype) ->
11032             let fname = name_of_field field in
11033             pr "  %s_%s : %s;\n" name fname ftype
11034         ) (List.combine fields types);
11035         pr "}\n";
11036         (* Return the name of this type, and
11037          * false because it's not a simple type.
11038          *)
11039         name, false
11040   in
11041
11042   generate_types xs
11043
11044 let generate_parsers xs =
11045   (* As for generate_type above, generate_parser makes a parser for
11046    * some type, and returns the name of the parser it has generated.
11047    * Because it (may) need to print something, it should always be
11048    * called in BOL context.
11049    *)
11050   let rec generate_parser = function
11051     | Text ->                                (* string *)
11052         "string_child_or_empty"
11053     | Choice values ->                        (* [`val1|`val2|...] *)
11054         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11055           (String.concat "|"
11056              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11057     | ZeroOrMore rng ->                        (* <rng> list *)
11058         let pa = generate_parser rng in
11059         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11060     | OneOrMore rng ->                        (* <rng> list *)
11061         let pa = generate_parser rng in
11062         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11063                                         (* virt-inspector hack: bool *)
11064     | Optional (Attribute (name, [Value "1"])) ->
11065         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11066     | Optional rng ->                        (* <rng> list *)
11067         let pa = generate_parser rng in
11068         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11069                                         (* type name = { fields ... } *)
11070     | Element (name, fields) when is_attrs_interleave fields ->
11071         generate_parser_struct name (get_attrs_interleave fields)
11072     | Element (name, [field]) ->        (* type name = field *)
11073         let pa = generate_parser field in
11074         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11075         pr "let %s =\n" parser_name;
11076         pr "  %s\n" pa;
11077         pr "let parse_%s = %s\n" name parser_name;
11078         parser_name
11079     | Attribute (name, [field]) ->
11080         let pa = generate_parser field in
11081         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11082         pr "let %s =\n" parser_name;
11083         pr "  %s\n" pa;
11084         pr "let parse_%s = %s\n" name parser_name;
11085         parser_name
11086     | Element (name, fields) ->              (* type name = { fields ... } *)
11087         generate_parser_struct name ([], fields)
11088     | rng ->
11089         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11090
11091   and is_attrs_interleave = function
11092     | [Interleave _] -> true
11093     | Attribute _ :: fields -> is_attrs_interleave fields
11094     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11095     | _ -> false
11096
11097   and get_attrs_interleave = function
11098     | [Interleave fields] -> [], fields
11099     | ((Attribute _) as field) :: fields
11100     | ((Optional (Attribute _)) as field) :: fields ->
11101         let attrs, interleaves = get_attrs_interleave fields in
11102         (field :: attrs), interleaves
11103     | _ -> assert false
11104
11105   and generate_parsers xs =
11106     List.iter (fun x -> ignore (generate_parser x)) xs
11107
11108   and generate_parser_struct name (attrs, interleaves) =
11109     (* Generate parsers for the fields first.  We have to do this
11110      * before printing anything so we are still in BOL context.
11111      *)
11112     let fields = attrs @ interleaves in
11113     let pas = List.map generate_parser fields in
11114
11115     (* Generate an intermediate tuple from all the fields first.
11116      * If the type is just a string + another field, then we will
11117      * return this directly, otherwise it is turned into a record.
11118      *
11119      * RELAX NG note: This code treats <interleave> and plain lists of
11120      * fields the same.  In other words, it doesn't bother enforcing
11121      * any ordering of fields in the XML.
11122      *)
11123     pr "let parse_%s x =\n" name;
11124     pr "  let t = (\n    ";
11125     let comma = ref false in
11126     List.iter (
11127       fun x ->
11128         if !comma then pr ",\n    ";
11129         comma := true;
11130         match x with
11131         | Optional (Attribute (fname, [field])), pa ->
11132             pr "%s x" pa
11133         | Optional (Element (fname, [field])), pa ->
11134             pr "%s (optional_child %S x)" pa fname
11135         | Attribute (fname, [Text]), _ ->
11136             pr "attribute %S x" fname
11137         | (ZeroOrMore _ | OneOrMore _), pa ->
11138             pr "%s x" pa
11139         | Text, pa ->
11140             pr "%s x" pa
11141         | (field, pa) ->
11142             let fname = name_of_field field in
11143             pr "%s (child %S x)" pa fname
11144     ) (List.combine fields pas);
11145     pr "\n  ) in\n";
11146
11147     (match fields with
11148      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11149          pr "  t\n"
11150
11151      | _ ->
11152          pr "  (Obj.magic t : %s)\n" name
11153 (*
11154          List.iter (
11155            function
11156            | (Optional (Attribute (fname, [field])), pa) ->
11157                pr "  %s_%s =\n" name fname;
11158                pr "    %s x;\n" pa
11159            | (Optional (Element (fname, [field])), pa) ->
11160                pr "  %s_%s =\n" name fname;
11161                pr "    (let x = optional_child %S x in\n" fname;
11162                pr "     %s x);\n" pa
11163            | (field, pa) ->
11164                let fname = name_of_field field in
11165                pr "  %s_%s =\n" name fname;
11166                pr "    (let x = child %S x in\n" fname;
11167                pr "     %s x);\n" pa
11168          ) (List.combine fields pas);
11169          pr "}\n"
11170 *)
11171     );
11172     sprintf "parse_%s" name
11173   in
11174
11175   generate_parsers xs
11176
11177 (* Generate ocaml/guestfs_inspector.mli. *)
11178 let generate_ocaml_inspector_mli () =
11179   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11180
11181   pr "\
11182 (** This is an OCaml language binding to the external [virt-inspector]
11183     program.
11184
11185     For more information, please read the man page [virt-inspector(1)].
11186 *)
11187
11188 ";
11189
11190   generate_types grammar;
11191   pr "(** The nested information returned from the {!inspect} function. *)\n";
11192   pr "\n";
11193
11194   pr "\
11195 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11196 (** To inspect a libvirt domain called [name], pass a singleton
11197     list: [inspect [name]].  When using libvirt only, you may
11198     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11199
11200     To inspect a disk image or images, pass a list of the filenames
11201     of the disk images: [inspect filenames]
11202
11203     This function inspects the given guest or disk images and
11204     returns a list of operating system(s) found and a large amount
11205     of information about them.  In the vast majority of cases,
11206     a virtual machine only contains a single operating system.
11207
11208     If the optional [~xml] parameter is given, then this function
11209     skips running the external virt-inspector program and just
11210     parses the given XML directly (which is expected to be XML
11211     produced from a previous run of virt-inspector).  The list of
11212     names and connect URI are ignored in this case.
11213
11214     This function can throw a wide variety of exceptions, for example
11215     if the external virt-inspector program cannot be found, or if
11216     it doesn't generate valid XML.
11217 *)
11218 "
11219
11220 (* Generate ocaml/guestfs_inspector.ml. *)
11221 let generate_ocaml_inspector_ml () =
11222   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11223
11224   pr "open Unix\n";
11225   pr "\n";
11226
11227   generate_types grammar;
11228   pr "\n";
11229
11230   pr "\
11231 (* Misc functions which are used by the parser code below. *)
11232 let first_child = function
11233   | Xml.Element (_, _, c::_) -> c
11234   | Xml.Element (name, _, []) ->
11235       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11236   | Xml.PCData str ->
11237       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11238
11239 let string_child_or_empty = function
11240   | Xml.Element (_, _, [Xml.PCData s]) -> s
11241   | Xml.Element (_, _, []) -> \"\"
11242   | Xml.Element (x, _, _) ->
11243       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11244                 x ^ \" instead\")
11245   | Xml.PCData str ->
11246       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11247
11248 let optional_child name xml =
11249   let children = Xml.children xml in
11250   try
11251     Some (List.find (function
11252                      | Xml.Element (n, _, _) when n = name -> true
11253                      | _ -> false) children)
11254   with
11255     Not_found -> None
11256
11257 let child name xml =
11258   match optional_child name xml with
11259   | Some c -> c
11260   | None ->
11261       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11262
11263 let attribute name xml =
11264   try Xml.attrib xml name
11265   with Xml.No_attribute _ ->
11266     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11267
11268 ";
11269
11270   generate_parsers grammar;
11271   pr "\n";
11272
11273   pr "\
11274 (* Run external virt-inspector, then use parser to parse the XML. *)
11275 let inspect ?connect ?xml names =
11276   let xml =
11277     match xml with
11278     | None ->
11279         if names = [] then invalid_arg \"inspect: no names given\";
11280         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11281           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11282           names in
11283         let cmd = List.map Filename.quote cmd in
11284         let cmd = String.concat \" \" cmd in
11285         let chan = open_process_in cmd in
11286         let xml = Xml.parse_in chan in
11287         (match close_process_in chan with
11288          | WEXITED 0 -> ()
11289          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11290          | WSIGNALED i | WSTOPPED i ->
11291              failwith (\"external virt-inspector command died or stopped on sig \" ^
11292                        string_of_int i)
11293         );
11294         xml
11295     | Some doc ->
11296         Xml.parse_string doc in
11297   parse_operatingsystems xml
11298 "
11299
11300 (* This is used to generate the src/MAX_PROC_NR file which
11301  * contains the maximum procedure number, a surrogate for the
11302  * ABI version number.  See src/Makefile.am for the details.
11303  *)
11304 and generate_max_proc_nr () =
11305   let proc_nrs = List.map (
11306     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11307   ) daemon_functions in
11308
11309   let max_proc_nr = List.fold_left max 0 proc_nrs in
11310
11311   pr "%d\n" max_proc_nr
11312
11313 let output_to filename k =
11314   let filename_new = filename ^ ".new" in
11315   chan := open_out filename_new;
11316   k ();
11317   close_out !chan;
11318   chan := Pervasives.stdout;
11319
11320   (* Is the new file different from the current file? *)
11321   if Sys.file_exists filename && files_equal filename filename_new then
11322     unlink filename_new                 (* same, so skip it *)
11323   else (
11324     (* different, overwrite old one *)
11325     (try chmod filename 0o644 with Unix_error _ -> ());
11326     rename filename_new filename;
11327     chmod filename 0o444;
11328     printf "written %s\n%!" filename;
11329   )
11330
11331 let perror msg = function
11332   | Unix_error (err, _, _) ->
11333       eprintf "%s: %s\n" msg (error_message err)
11334   | exn ->
11335       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11336
11337 (* Main program. *)
11338 let () =
11339   let lock_fd =
11340     try openfile "HACKING" [O_RDWR] 0
11341     with
11342     | Unix_error (ENOENT, _, _) ->
11343         eprintf "\
11344 You are probably running this from the wrong directory.
11345 Run it from the top source directory using the command
11346   src/generator.ml
11347 ";
11348         exit 1
11349     | exn ->
11350         perror "open: HACKING" exn;
11351         exit 1 in
11352
11353   (* Acquire a lock so parallel builds won't try to run the generator
11354    * twice at the same time.  Subsequent builds will wait for the first
11355    * one to finish.  Note the lock is released implicitly when the
11356    * program exits.
11357    *)
11358   (try lockf lock_fd F_LOCK 1
11359    with exn ->
11360      perror "lock: HACKING" exn;
11361      exit 1);
11362
11363   check_functions ();
11364
11365   output_to "src/guestfs_protocol.x" generate_xdr;
11366   output_to "src/guestfs-structs.h" generate_structs_h;
11367   output_to "src/guestfs-actions.h" generate_actions_h;
11368   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11369   output_to "src/guestfs-actions.c" generate_client_actions;
11370   output_to "src/guestfs-bindtests.c" generate_bindtests;
11371   output_to "src/guestfs-structs.pod" generate_structs_pod;
11372   output_to "src/guestfs-actions.pod" generate_actions_pod;
11373   output_to "src/guestfs-availability.pod" generate_availability_pod;
11374   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11375   output_to "src/libguestfs.syms" generate_linker_script;
11376   output_to "daemon/actions.h" generate_daemon_actions_h;
11377   output_to "daemon/stubs.c" generate_daemon_actions;
11378   output_to "daemon/names.c" generate_daemon_names;
11379   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11380   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11381   output_to "capitests/tests.c" generate_tests;
11382   output_to "fish/cmds.c" generate_fish_cmds;
11383   output_to "fish/completion.c" generate_fish_completion;
11384   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11385   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11386   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11387   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11388   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11389   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11390   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11391   output_to "perl/Guestfs.xs" generate_perl_xs;
11392   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11393   output_to "perl/bindtests.pl" generate_perl_bindtests;
11394   output_to "python/guestfs-py.c" generate_python_c;
11395   output_to "python/guestfs.py" generate_python_py;
11396   output_to "python/bindtests.py" generate_python_bindtests;
11397   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11398   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11399   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11400
11401   List.iter (
11402     fun (typ, jtyp) ->
11403       let cols = cols_of_struct typ in
11404       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11405       output_to filename (generate_java_struct jtyp cols);
11406   ) java_structs;
11407
11408   output_to "java/Makefile.inc" generate_java_makefile_inc;
11409   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11410   output_to "java/Bindtests.java" generate_java_bindtests;
11411   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11412   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11413   output_to "csharp/Libguestfs.cs" generate_csharp;
11414
11415   (* Always generate this file last, and unconditionally.  It's used
11416    * by the Makefile to know when we must re-run the generator.
11417    *)
11418   let chan = open_out "src/stamp-generator" in
11419   fprintf chan "1\n";
11420   close_out chan;
11421
11422   printf "generated %d lines of code\n" !lines