add_cdrom: Update docs for adding ISO images.
[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 C<cache=off> is omitted in cases where it is not supported by
493 the underlying filesystem.
494
495 Note that this call checks for the existence of C<filename>.  This
496 stops you from specifying other types of drive which are supported
497 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
498 the general C<guestfs_config> call instead.");
499
500   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
501    [],
502    "add a CD-ROM disk image to examine",
503    "\
504 This function adds a virtual CD-ROM disk image to the guest.
505
506 This is equivalent to the qemu parameter C<-cdrom filename>.
507
508 Notes:
509
510 =over 4
511
512 =item *
513
514 This call checks for the existence of C<filename>.  This
515 stops you from specifying other types of drive which are supported
516 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
517 the general C<guestfs_config> call instead.
518
519 =item *
520
521 If you just want to add an ISO file (often you use this as an
522 efficient way to transfer large files into the guest), then you
523 should probably use C<guestfs_add_drive_ro> instead.
524
525 =back");
526
527   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
528    [],
529    "add a drive in snapshot mode (read-only)",
530    "\
531 This adds a drive in snapshot mode, making it effectively
532 read-only.
533
534 Note that writes to the device are allowed, and will be seen for
535 the duration of the guestfs handle, but they are written
536 to a temporary file which is discarded as soon as the guestfs
537 handle is closed.  We don't currently have any method to enable
538 changes to be committed, although qemu can support this.
539
540 This is equivalent to the qemu parameter
541 C<-drive file=filename,snapshot=on,if=...>.
542
543 Note that this call checks for the existence of C<filename>.  This
544 stops you from specifying other types of drive which are supported
545 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
546 the general C<guestfs_config> call instead.");
547
548   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
549    [],
550    "add qemu parameters",
551    "\
552 This can be used to add arbitrary qemu command line parameters
553 of the form C<-param value>.  Actually it's not quite arbitrary - we
554 prevent you from setting some parameters which would interfere with
555 parameters that we use.
556
557 The first character of C<param> string must be a C<-> (dash).
558
559 C<value> can be NULL.");
560
561   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
562    [],
563    "set the qemu binary",
564    "\
565 Set the qemu binary that we will use.
566
567 The default is chosen when the library was compiled by the
568 configure script.
569
570 You can also override this by setting the C<LIBGUESTFS_QEMU>
571 environment variable.
572
573 Setting C<qemu> to C<NULL> restores the default qemu binary.");
574
575   ("get_qemu", (RConstString "qemu", []), -1, [],
576    [InitNone, Always, TestRun (
577       [["get_qemu"]])],
578    "get the qemu binary",
579    "\
580 Return the current qemu binary.
581
582 This is always non-NULL.  If it wasn't set already, then this will
583 return the default qemu binary name.");
584
585   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
586    [],
587    "set the search path",
588    "\
589 Set the path that libguestfs searches for kernel and initrd.img.
590
591 The default is C<$libdir/guestfs> unless overridden by setting
592 C<LIBGUESTFS_PATH> environment variable.
593
594 Setting C<path> to C<NULL> restores the default path.");
595
596   ("get_path", (RConstString "path", []), -1, [],
597    [InitNone, Always, TestRun (
598       [["get_path"]])],
599    "get the search path",
600    "\
601 Return the current search path.
602
603 This is always non-NULL.  If it wasn't set already, then this will
604 return the default path.");
605
606   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
607    [],
608    "add options to kernel command line",
609    "\
610 This function is used to add additional options to the
611 guest kernel command line.
612
613 The default is C<NULL> unless overridden by setting
614 C<LIBGUESTFS_APPEND> environment variable.
615
616 Setting C<append> to C<NULL> means I<no> additional options
617 are passed (libguestfs always adds a few of its own).");
618
619   ("get_append", (RConstOptString "append", []), -1, [],
620    (* This cannot be tested with the current framework.  The
621     * function can return NULL in normal operations, which the
622     * test framework interprets as an error.
623     *)
624    [],
625    "get the additional kernel options",
626    "\
627 Return the additional kernel options which are added to the
628 guest kernel command line.
629
630 If C<NULL> then no options are added.");
631
632   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
633    [],
634    "set autosync mode",
635    "\
636 If C<autosync> is true, this enables autosync.  Libguestfs will make a
637 best effort attempt to run C<guestfs_umount_all> followed by
638 C<guestfs_sync> when the handle is closed
639 (also if the program exits without closing handles).
640
641 This is disabled by default (except in guestfish where it is
642 enabled by default).");
643
644   ("get_autosync", (RBool "autosync", []), -1, [],
645    [InitNone, Always, TestRun (
646       [["get_autosync"]])],
647    "get autosync mode",
648    "\
649 Get the autosync flag.");
650
651   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
652    [],
653    "set verbose mode",
654    "\
655 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
656
657 Verbose messages are disabled unless the environment variable
658 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
659
660   ("get_verbose", (RBool "verbose", []), -1, [],
661    [],
662    "get verbose mode",
663    "\
664 This returns the verbose messages flag.");
665
666   ("is_ready", (RBool "ready", []), -1, [],
667    [InitNone, Always, TestOutputTrue (
668       [["is_ready"]])],
669    "is ready to accept commands",
670    "\
671 This returns true iff this handle is ready to accept commands
672 (in the C<READY> state).
673
674 For more information on states, see L<guestfs(3)>.");
675
676   ("is_config", (RBool "config", []), -1, [],
677    [InitNone, Always, TestOutputFalse (
678       [["is_config"]])],
679    "is in configuration state",
680    "\
681 This returns true iff this handle is being configured
682 (in the C<CONFIG> state).
683
684 For more information on states, see L<guestfs(3)>.");
685
686   ("is_launching", (RBool "launching", []), -1, [],
687    [InitNone, Always, TestOutputFalse (
688       [["is_launching"]])],
689    "is launching subprocess",
690    "\
691 This returns true iff this handle is launching the subprocess
692 (in the C<LAUNCHING> state).
693
694 For more information on states, see L<guestfs(3)>.");
695
696   ("is_busy", (RBool "busy", []), -1, [],
697    [InitNone, Always, TestOutputFalse (
698       [["is_busy"]])],
699    "is busy processing a command",
700    "\
701 This returns true iff this handle is busy processing a command
702 (in the C<BUSY> state).
703
704 For more information on states, see L<guestfs(3)>.");
705
706   ("get_state", (RInt "state", []), -1, [],
707    [],
708    "get the current state",
709    "\
710 This returns the current state as an opaque integer.  This is
711 only useful for printing debug and internal error messages.
712
713 For more information on states, see L<guestfs(3)>.");
714
715   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
716    [InitNone, Always, TestOutputInt (
717       [["set_memsize"; "500"];
718        ["get_memsize"]], 500)],
719    "set memory allocated to the qemu subprocess",
720    "\
721 This sets the memory size in megabytes allocated to the
722 qemu subprocess.  This only has any effect if called before
723 C<guestfs_launch>.
724
725 You can also change this by setting the environment
726 variable C<LIBGUESTFS_MEMSIZE> before the handle is
727 created.
728
729 For more information on the architecture of libguestfs,
730 see L<guestfs(3)>.");
731
732   ("get_memsize", (RInt "memsize", []), -1, [],
733    [InitNone, Always, TestOutputIntOp (
734       [["get_memsize"]], ">=", 256)],
735    "get memory allocated to the qemu subprocess",
736    "\
737 This gets the memory size in megabytes allocated to the
738 qemu subprocess.
739
740 If C<guestfs_set_memsize> was not called
741 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
742 then this returns the compiled-in default value for memsize.
743
744 For more information on the architecture of libguestfs,
745 see L<guestfs(3)>.");
746
747   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
748    [InitNone, Always, TestOutputIntOp (
749       [["get_pid"]], ">=", 1)],
750    "get PID of qemu subprocess",
751    "\
752 Return the process ID of the qemu subprocess.  If there is no
753 qemu subprocess, then this will return an error.
754
755 This is an internal call used for debugging and testing.");
756
757   ("version", (RStruct ("version", "version"), []), -1, [],
758    [InitNone, Always, TestOutputStruct (
759       [["version"]], [CompareWithInt ("major", 1)])],
760    "get the library version number",
761    "\
762 Return the libguestfs version number that the program is linked
763 against.
764
765 Note that because of dynamic linking this is not necessarily
766 the version of libguestfs that you compiled against.  You can
767 compile the program, and then at runtime dynamically link
768 against a completely different C<libguestfs.so> library.
769
770 This call was added in version C<1.0.58>.  In previous
771 versions of libguestfs there was no way to get the version
772 number.  From C code you can use ELF weak linking tricks to find out if
773 this symbol exists (if it doesn't, then it's an earlier version).
774
775 The call returns a structure with four elements.  The first
776 three (C<major>, C<minor> and C<release>) are numbers and
777 correspond to the usual version triplet.  The fourth element
778 (C<extra>) is a string and is normally empty, but may be
779 used for distro-specific information.
780
781 To construct the original version string:
782 C<$major.$minor.$release$extra>
783
784 I<Note:> Don't use this call to test for availability
785 of features.  Distro backports makes this unreliable.  Use
786 C<guestfs_available> instead.");
787
788   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
789    [InitNone, Always, TestOutputTrue (
790       [["set_selinux"; "true"];
791        ["get_selinux"]])],
792    "set SELinux enabled or disabled at appliance boot",
793    "\
794 This sets the selinux flag that is passed to the appliance
795 at boot time.  The default is C<selinux=0> (disabled).
796
797 Note that if SELinux is enabled, it is always in
798 Permissive mode (C<enforcing=0>).
799
800 For more information on the architecture of libguestfs,
801 see L<guestfs(3)>.");
802
803   ("get_selinux", (RBool "selinux", []), -1, [],
804    [],
805    "get SELinux enabled flag",
806    "\
807 This returns the current setting of the selinux flag which
808 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
809
810 For more information on the architecture of libguestfs,
811 see L<guestfs(3)>.");
812
813   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
814    [InitNone, Always, TestOutputFalse (
815       [["set_trace"; "false"];
816        ["get_trace"]])],
817    "enable or disable command traces",
818    "\
819 If the command trace flag is set to 1, then commands are
820 printed on stdout before they are executed in a format
821 which is very similar to the one used by guestfish.  In
822 other words, you can run a program with this enabled, and
823 you will get out a script which you can feed to guestfish
824 to perform the same set of actions.
825
826 If you want to trace C API calls into libguestfs (and
827 other libraries) then possibly a better way is to use
828 the external ltrace(1) command.
829
830 Command traces are disabled unless the environment variable
831 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
832
833   ("get_trace", (RBool "trace", []), -1, [],
834    [],
835    "get command trace enabled flag",
836    "\
837 Return the command trace flag.");
838
839   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
840    [InitNone, Always, TestOutputFalse (
841       [["set_direct"; "false"];
842        ["get_direct"]])],
843    "enable or disable direct appliance mode",
844    "\
845 If the direct appliance mode flag is enabled, then stdin and
846 stdout are passed directly through to the appliance once it
847 is launched.
848
849 One consequence of this is that log messages aren't caught
850 by the library and handled by C<guestfs_set_log_message_callback>,
851 but go straight to stdout.
852
853 You probably don't want to use this unless you know what you
854 are doing.
855
856 The default is disabled.");
857
858   ("get_direct", (RBool "direct", []), -1, [],
859    [],
860    "get direct appliance mode flag",
861    "\
862 Return the direct appliance mode flag.");
863
864   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
865    [InitNone, Always, TestOutputTrue (
866       [["set_recovery_proc"; "true"];
867        ["get_recovery_proc"]])],
868    "enable or disable the recovery process",
869    "\
870 If this is called with the parameter C<false> then
871 C<guestfs_launch> does not create a recovery process.  The
872 purpose of the recovery process is to stop runaway qemu
873 processes in the case where the main program aborts abruptly.
874
875 This only has any effect if called before C<guestfs_launch>,
876 and the default is true.
877
878 About the only time when you would want to disable this is
879 if the main process will fork itself into the background
880 (\"daemonize\" itself).  In this case the recovery process
881 thinks that the main program has disappeared and so kills
882 qemu, which is not very helpful.");
883
884   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
885    [],
886    "get recovery process enabled flag",
887    "\
888 Return the recovery process enabled flag.");
889
890 ]
891
892 (* daemon_functions are any functions which cause some action
893  * to take place in the daemon.
894  *)
895
896 let daemon_functions = [
897   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
898    [InitEmpty, Always, TestOutput (
899       [["part_disk"; "/dev/sda"; "mbr"];
900        ["mkfs"; "ext2"; "/dev/sda1"];
901        ["mount"; "/dev/sda1"; "/"];
902        ["write_file"; "/new"; "new file contents"; "0"];
903        ["cat"; "/new"]], "new file contents")],
904    "mount a guest disk at a position in the filesystem",
905    "\
906 Mount a guest disk at a position in the filesystem.  Block devices
907 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
908 the guest.  If those block devices contain partitions, they will have
909 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
910 names can be used.
911
912 The rules are the same as for L<mount(2)>:  A filesystem must
913 first be mounted on C</> before others can be mounted.  Other
914 filesystems can only be mounted on directories which already
915 exist.
916
917 The mounted filesystem is writable, if we have sufficient permissions
918 on the underlying device.
919
920 The filesystem options C<sync> and C<noatime> are set with this
921 call, in order to improve reliability.");
922
923   ("sync", (RErr, []), 2, [],
924    [ InitEmpty, Always, TestRun [["sync"]]],
925    "sync disks, writes are flushed through to the disk image",
926    "\
927 This syncs the disk, so that any writes are flushed through to the
928 underlying disk image.
929
930 You should always call this if you have modified a disk image, before
931 closing the handle.");
932
933   ("touch", (RErr, [Pathname "path"]), 3, [],
934    [InitBasicFS, Always, TestOutputTrue (
935       [["touch"; "/new"];
936        ["exists"; "/new"]])],
937    "update file timestamps or create a new file",
938    "\
939 Touch acts like the L<touch(1)> command.  It can be used to
940 update the timestamps on a file, or, if the file does not exist,
941 to create a new zero-length file.");
942
943   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
944    [InitISOFS, Always, TestOutput (
945       [["cat"; "/known-2"]], "abcdef\n")],
946    "list the contents of a file",
947    "\
948 Return the contents of the file named C<path>.
949
950 Note that this function cannot correctly handle binary files
951 (specifically, files containing C<\\0> character which is treated
952 as end of string).  For those you need to use the C<guestfs_read_file>
953 or C<guestfs_download> functions which have a more complex interface.");
954
955   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
956    [], (* XXX Tricky to test because it depends on the exact format
957         * of the 'ls -l' command, which changes between F10 and F11.
958         *)
959    "list the files in a directory (long format)",
960    "\
961 List the files in C<directory> (relative to the root directory,
962 there is no cwd) in the format of 'ls -la'.
963
964 This command is mostly useful for interactive sessions.  It
965 is I<not> intended that you try to parse the output string.");
966
967   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
968    [InitBasicFS, Always, TestOutputList (
969       [["touch"; "/new"];
970        ["touch"; "/newer"];
971        ["touch"; "/newest"];
972        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
973    "list the files in a directory",
974    "\
975 List the files in C<directory> (relative to the root directory,
976 there is no cwd).  The '.' and '..' entries are not returned, but
977 hidden files are shown.
978
979 This command is mostly useful for interactive sessions.  Programs
980 should probably use C<guestfs_readdir> instead.");
981
982   ("list_devices", (RStringList "devices", []), 7, [],
983    [InitEmpty, Always, TestOutputListOfDevices (
984       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
985    "list the block devices",
986    "\
987 List all the block devices.
988
989 The full block device names are returned, eg. C</dev/sda>");
990
991   ("list_partitions", (RStringList "partitions", []), 8, [],
992    [InitBasicFS, Always, TestOutputListOfDevices (
993       [["list_partitions"]], ["/dev/sda1"]);
994     InitEmpty, Always, TestOutputListOfDevices (
995       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
996        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
997    "list the partitions",
998    "\
999 List all the partitions detected on all block devices.
1000
1001 The full partition device names are returned, eg. C</dev/sda1>
1002
1003 This does not return logical volumes.  For that you will need to
1004 call C<guestfs_lvs>.");
1005
1006   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1007    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1008       [["pvs"]], ["/dev/sda1"]);
1009     InitEmpty, Always, TestOutputListOfDevices (
1010       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1011        ["pvcreate"; "/dev/sda1"];
1012        ["pvcreate"; "/dev/sda2"];
1013        ["pvcreate"; "/dev/sda3"];
1014        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1015    "list the LVM physical volumes (PVs)",
1016    "\
1017 List all the physical volumes detected.  This is the equivalent
1018 of the L<pvs(8)> command.
1019
1020 This returns a list of just the device names that contain
1021 PVs (eg. C</dev/sda2>).
1022
1023 See also C<guestfs_pvs_full>.");
1024
1025   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1026    [InitBasicFSonLVM, Always, TestOutputList (
1027       [["vgs"]], ["VG"]);
1028     InitEmpty, Always, TestOutputList (
1029       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1030        ["pvcreate"; "/dev/sda1"];
1031        ["pvcreate"; "/dev/sda2"];
1032        ["pvcreate"; "/dev/sda3"];
1033        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1034        ["vgcreate"; "VG2"; "/dev/sda3"];
1035        ["vgs"]], ["VG1"; "VG2"])],
1036    "list the LVM volume groups (VGs)",
1037    "\
1038 List all the volumes groups detected.  This is the equivalent
1039 of the L<vgs(8)> command.
1040
1041 This returns a list of just the volume group names that were
1042 detected (eg. C<VolGroup00>).
1043
1044 See also C<guestfs_vgs_full>.");
1045
1046   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1047    [InitBasicFSonLVM, Always, TestOutputList (
1048       [["lvs"]], ["/dev/VG/LV"]);
1049     InitEmpty, Always, TestOutputList (
1050       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1051        ["pvcreate"; "/dev/sda1"];
1052        ["pvcreate"; "/dev/sda2"];
1053        ["pvcreate"; "/dev/sda3"];
1054        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1055        ["vgcreate"; "VG2"; "/dev/sda3"];
1056        ["lvcreate"; "LV1"; "VG1"; "50"];
1057        ["lvcreate"; "LV2"; "VG1"; "50"];
1058        ["lvcreate"; "LV3"; "VG2"; "50"];
1059        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1060    "list the LVM logical volumes (LVs)",
1061    "\
1062 List all the logical volumes detected.  This is the equivalent
1063 of the L<lvs(8)> command.
1064
1065 This returns a list of the logical volume device names
1066 (eg. C</dev/VolGroup00/LogVol00>).
1067
1068 See also C<guestfs_lvs_full>.");
1069
1070   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1071    [], (* XXX how to test? *)
1072    "list the LVM physical volumes (PVs)",
1073    "\
1074 List all the physical volumes detected.  This is the equivalent
1075 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1076
1077   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1078    [], (* XXX how to test? *)
1079    "list the LVM volume groups (VGs)",
1080    "\
1081 List all the volumes groups detected.  This is the equivalent
1082 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1083
1084   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1085    [], (* XXX how to test? *)
1086    "list the LVM logical volumes (LVs)",
1087    "\
1088 List all the logical volumes detected.  This is the equivalent
1089 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1090
1091   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1092    [InitISOFS, Always, TestOutputList (
1093       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1094     InitISOFS, Always, TestOutputList (
1095       [["read_lines"; "/empty"]], [])],
1096    "read file as lines",
1097    "\
1098 Return the contents of the file named C<path>.
1099
1100 The file contents are returned as a list of lines.  Trailing
1101 C<LF> and C<CRLF> character sequences are I<not> returned.
1102
1103 Note that this function cannot correctly handle binary files
1104 (specifically, files containing C<\\0> character which is treated
1105 as end of line).  For those you need to use the C<guestfs_read_file>
1106 function which has a more complex interface.");
1107
1108   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1109    [], (* XXX Augeas code needs tests. *)
1110    "create a new Augeas handle",
1111    "\
1112 Create a new Augeas handle for editing configuration files.
1113 If there was any previous Augeas handle associated with this
1114 guestfs session, then it is closed.
1115
1116 You must call this before using any other C<guestfs_aug_*>
1117 commands.
1118
1119 C<root> is the filesystem root.  C<root> must not be NULL,
1120 use C</> instead.
1121
1122 The flags are the same as the flags defined in
1123 E<lt>augeas.hE<gt>, the logical I<or> of the following
1124 integers:
1125
1126 =over 4
1127
1128 =item C<AUG_SAVE_BACKUP> = 1
1129
1130 Keep the original file with a C<.augsave> extension.
1131
1132 =item C<AUG_SAVE_NEWFILE> = 2
1133
1134 Save changes into a file with extension C<.augnew>, and
1135 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1136
1137 =item C<AUG_TYPE_CHECK> = 4
1138
1139 Typecheck lenses (can be expensive).
1140
1141 =item C<AUG_NO_STDINC> = 8
1142
1143 Do not use standard load path for modules.
1144
1145 =item C<AUG_SAVE_NOOP> = 16
1146
1147 Make save a no-op, just record what would have been changed.
1148
1149 =item C<AUG_NO_LOAD> = 32
1150
1151 Do not load the tree in C<guestfs_aug_init>.
1152
1153 =back
1154
1155 To close the handle, you can call C<guestfs_aug_close>.
1156
1157 To find out more about Augeas, see L<http://augeas.net/>.");
1158
1159   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1160    [], (* XXX Augeas code needs tests. *)
1161    "close the current Augeas handle",
1162    "\
1163 Close the current Augeas handle and free up any resources
1164 used by it.  After calling this, you have to call
1165 C<guestfs_aug_init> again before you can use any other
1166 Augeas functions.");
1167
1168   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1169    [], (* XXX Augeas code needs tests. *)
1170    "define an Augeas variable",
1171    "\
1172 Defines an Augeas variable C<name> whose value is the result
1173 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1174 undefined.
1175
1176 On success this returns the number of nodes in C<expr>, or
1177 C<0> if C<expr> evaluates to something which is not a nodeset.");
1178
1179   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1180    [], (* XXX Augeas code needs tests. *)
1181    "define an Augeas node",
1182    "\
1183 Defines a variable C<name> whose value is the result of
1184 evaluating C<expr>.
1185
1186 If C<expr> evaluates to an empty nodeset, a node is created,
1187 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1188 C<name> will be the nodeset containing that single node.
1189
1190 On success this returns a pair containing the
1191 number of nodes in the nodeset, and a boolean flag
1192 if a node was created.");
1193
1194   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1195    [], (* XXX Augeas code needs tests. *)
1196    "look up the value of an Augeas path",
1197    "\
1198 Look up the value associated with C<path>.  If C<path>
1199 matches exactly one node, the C<value> is returned.");
1200
1201   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1202    [], (* XXX Augeas code needs tests. *)
1203    "set Augeas path to value",
1204    "\
1205 Set the value associated with C<path> to C<value>.");
1206
1207   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "insert a sibling Augeas node",
1210    "\
1211 Create a new sibling C<label> for C<path>, inserting it into
1212 the tree before or after C<path> (depending on the boolean
1213 flag C<before>).
1214
1215 C<path> must match exactly one existing node in the tree, and
1216 C<label> must be a label, ie. not contain C</>, C<*> or end
1217 with a bracketed index C<[N]>.");
1218
1219   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "remove an Augeas path",
1222    "\
1223 Remove C<path> and all of its children.
1224
1225 On success this returns the number of entries which were removed.");
1226
1227   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "move Augeas node",
1230    "\
1231 Move the node C<src> to C<dest>.  C<src> must match exactly
1232 one node.  C<dest> is overwritten if it exists.");
1233
1234   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1235    [], (* XXX Augeas code needs tests. *)
1236    "return Augeas nodes which match augpath",
1237    "\
1238 Returns a list of paths which match the path expression C<path>.
1239 The returned paths are sufficiently qualified so that they match
1240 exactly one node in the current tree.");
1241
1242   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "write all pending Augeas changes to disk",
1245    "\
1246 This writes all pending changes to disk.
1247
1248 The flags which were passed to C<guestfs_aug_init> affect exactly
1249 how files are saved.");
1250
1251   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1252    [], (* XXX Augeas code needs tests. *)
1253    "load files into the tree",
1254    "\
1255 Load files into the tree.
1256
1257 See C<aug_load> in the Augeas documentation for the full gory
1258 details.");
1259
1260   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "list Augeas nodes under augpath",
1263    "\
1264 This is just a shortcut for listing C<guestfs_aug_match>
1265 C<path/*> and sorting the resulting nodes into alphabetical order.");
1266
1267   ("rm", (RErr, [Pathname "path"]), 29, [],
1268    [InitBasicFS, Always, TestRun
1269       [["touch"; "/new"];
1270        ["rm"; "/new"]];
1271     InitBasicFS, Always, TestLastFail
1272       [["rm"; "/new"]];
1273     InitBasicFS, Always, TestLastFail
1274       [["mkdir"; "/new"];
1275        ["rm"; "/new"]]],
1276    "remove a file",
1277    "\
1278 Remove the single file C<path>.");
1279
1280   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1281    [InitBasicFS, Always, TestRun
1282       [["mkdir"; "/new"];
1283        ["rmdir"; "/new"]];
1284     InitBasicFS, Always, TestLastFail
1285       [["rmdir"; "/new"]];
1286     InitBasicFS, Always, TestLastFail
1287       [["touch"; "/new"];
1288        ["rmdir"; "/new"]]],
1289    "remove a directory",
1290    "\
1291 Remove the single directory C<path>.");
1292
1293   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1294    [InitBasicFS, Always, TestOutputFalse
1295       [["mkdir"; "/new"];
1296        ["mkdir"; "/new/foo"];
1297        ["touch"; "/new/foo/bar"];
1298        ["rm_rf"; "/new"];
1299        ["exists"; "/new"]]],
1300    "remove a file or directory recursively",
1301    "\
1302 Remove the file or directory C<path>, recursively removing the
1303 contents if its a directory.  This is like the C<rm -rf> shell
1304 command.");
1305
1306   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1307    [InitBasicFS, Always, TestOutputTrue
1308       [["mkdir"; "/new"];
1309        ["is_dir"; "/new"]];
1310     InitBasicFS, Always, TestLastFail
1311       [["mkdir"; "/new/foo/bar"]]],
1312    "create a directory",
1313    "\
1314 Create a directory named C<path>.");
1315
1316   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1317    [InitBasicFS, Always, TestOutputTrue
1318       [["mkdir_p"; "/new/foo/bar"];
1319        ["is_dir"; "/new/foo/bar"]];
1320     InitBasicFS, Always, TestOutputTrue
1321       [["mkdir_p"; "/new/foo/bar"];
1322        ["is_dir"; "/new/foo"]];
1323     InitBasicFS, Always, TestOutputTrue
1324       [["mkdir_p"; "/new/foo/bar"];
1325        ["is_dir"; "/new"]];
1326     (* Regression tests for RHBZ#503133: *)
1327     InitBasicFS, Always, TestRun
1328       [["mkdir"; "/new"];
1329        ["mkdir_p"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["touch"; "/new"];
1332        ["mkdir_p"; "/new"]]],
1333    "create a directory and parents",
1334    "\
1335 Create a directory named C<path>, creating any parent directories
1336 as necessary.  This is like the C<mkdir -p> shell command.");
1337
1338   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1339    [], (* XXX Need stat command to test *)
1340    "change file mode",
1341    "\
1342 Change the mode (permissions) of C<path> to C<mode>.  Only
1343 numeric modes are supported.
1344
1345 I<Note>: When using this command from guestfish, C<mode>
1346 by default would be decimal, unless you prefix it with
1347 C<0> to get octal, ie. use C<0700> not C<700>.");
1348
1349   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1350    [], (* XXX Need stat command to test *)
1351    "change file owner and group",
1352    "\
1353 Change the file owner to C<owner> and group to C<group>.
1354
1355 Only numeric uid and gid are supported.  If you want to use
1356 names, you will need to locate and parse the password file
1357 yourself (Augeas support makes this relatively easy).");
1358
1359   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1360    [InitISOFS, Always, TestOutputTrue (
1361       [["exists"; "/empty"]]);
1362     InitISOFS, Always, TestOutputTrue (
1363       [["exists"; "/directory"]])],
1364    "test if file or directory exists",
1365    "\
1366 This returns C<true> if and only if there is a file, directory
1367 (or anything) with the given C<path> name.
1368
1369 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1370
1371   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1372    [InitISOFS, Always, TestOutputTrue (
1373       [["is_file"; "/known-1"]]);
1374     InitISOFS, Always, TestOutputFalse (
1375       [["is_file"; "/directory"]])],
1376    "test if file exists",
1377    "\
1378 This returns C<true> if and only if there is a file
1379 with the given C<path> name.  Note that it returns false for
1380 other objects like directories.
1381
1382 See also C<guestfs_stat>.");
1383
1384   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1385    [InitISOFS, Always, TestOutputFalse (
1386       [["is_dir"; "/known-3"]]);
1387     InitISOFS, Always, TestOutputTrue (
1388       [["is_dir"; "/directory"]])],
1389    "test if file exists",
1390    "\
1391 This returns C<true> if and only if there is a directory
1392 with the given C<path> name.  Note that it returns false for
1393 other objects like files.
1394
1395 See also C<guestfs_stat>.");
1396
1397   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1398    [InitEmpty, Always, TestOutputListOfDevices (
1399       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1400        ["pvcreate"; "/dev/sda1"];
1401        ["pvcreate"; "/dev/sda2"];
1402        ["pvcreate"; "/dev/sda3"];
1403        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1404    "create an LVM physical volume",
1405    "\
1406 This creates an LVM physical volume on the named C<device>,
1407 where C<device> should usually be a partition name such
1408 as C</dev/sda1>.");
1409
1410   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1411    [InitEmpty, Always, TestOutputList (
1412       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1413        ["pvcreate"; "/dev/sda1"];
1414        ["pvcreate"; "/dev/sda2"];
1415        ["pvcreate"; "/dev/sda3"];
1416        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1417        ["vgcreate"; "VG2"; "/dev/sda3"];
1418        ["vgs"]], ["VG1"; "VG2"])],
1419    "create an LVM volume group",
1420    "\
1421 This creates an LVM volume group called C<volgroup>
1422 from the non-empty list of physical volumes C<physvols>.");
1423
1424   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1425    [InitEmpty, Always, TestOutputList (
1426       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1427        ["pvcreate"; "/dev/sda1"];
1428        ["pvcreate"; "/dev/sda2"];
1429        ["pvcreate"; "/dev/sda3"];
1430        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1431        ["vgcreate"; "VG2"; "/dev/sda3"];
1432        ["lvcreate"; "LV1"; "VG1"; "50"];
1433        ["lvcreate"; "LV2"; "VG1"; "50"];
1434        ["lvcreate"; "LV3"; "VG2"; "50"];
1435        ["lvcreate"; "LV4"; "VG2"; "50"];
1436        ["lvcreate"; "LV5"; "VG2"; "50"];
1437        ["lvs"]],
1438       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1439        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1440    "create an LVM volume group",
1441    "\
1442 This creates an LVM volume group called C<logvol>
1443 on the volume group C<volgroup>, with C<size> megabytes.");
1444
1445   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1446    [InitEmpty, Always, TestOutput (
1447       [["part_disk"; "/dev/sda"; "mbr"];
1448        ["mkfs"; "ext2"; "/dev/sda1"];
1449        ["mount_options"; ""; "/dev/sda1"; "/"];
1450        ["write_file"; "/new"; "new file contents"; "0"];
1451        ["cat"; "/new"]], "new file contents")],
1452    "make a filesystem",
1453    "\
1454 This creates a filesystem on C<device> (usually a partition
1455 or LVM logical volume).  The filesystem type is C<fstype>, for
1456 example C<ext3>.");
1457
1458   ("sfdisk", (RErr, [Device "device";
1459                      Int "cyls"; Int "heads"; Int "sectors";
1460                      StringList "lines"]), 43, [DangerWillRobinson],
1461    [],
1462    "create partitions on a block device",
1463    "\
1464 This is a direct interface to the L<sfdisk(8)> program for creating
1465 partitions on block devices.
1466
1467 C<device> should be a block device, for example C</dev/sda>.
1468
1469 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1470 and sectors on the device, which are passed directly to sfdisk as
1471 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1472 of these, then the corresponding parameter is omitted.  Usually for
1473 'large' disks, you can just pass C<0> for these, but for small
1474 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1475 out the right geometry and you will need to tell it.
1476
1477 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1478 information refer to the L<sfdisk(8)> manpage.
1479
1480 To create a single partition occupying the whole disk, you would
1481 pass C<lines> as a single element list, when the single element being
1482 the string C<,> (comma).
1483
1484 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1485 C<guestfs_part_init>");
1486
1487   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1488    [InitBasicFS, Always, TestOutput (
1489       [["write_file"; "/new"; "new file contents"; "0"];
1490        ["cat"; "/new"]], "new file contents");
1491     InitBasicFS, Always, TestOutput (
1492       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1493        ["cat"; "/new"]], "\nnew file contents\n");
1494     InitBasicFS, Always, TestOutput (
1495       [["write_file"; "/new"; "\n\n"; "0"];
1496        ["cat"; "/new"]], "\n\n");
1497     InitBasicFS, Always, TestOutput (
1498       [["write_file"; "/new"; ""; "0"];
1499        ["cat"; "/new"]], "");
1500     InitBasicFS, Always, TestOutput (
1501       [["write_file"; "/new"; "\n\n\n"; "0"];
1502        ["cat"; "/new"]], "\n\n\n");
1503     InitBasicFS, Always, TestOutput (
1504       [["write_file"; "/new"; "\n"; "0"];
1505        ["cat"; "/new"]], "\n")],
1506    "create a file",
1507    "\
1508 This call creates a file called C<path>.  The contents of the
1509 file is the string C<content> (which can contain any 8 bit data),
1510 with length C<size>.
1511
1512 As a special case, if C<size> is C<0>
1513 then the length is calculated using C<strlen> (so in this case
1514 the content cannot contain embedded ASCII NULs).
1515
1516 I<NB.> Owing to a bug, writing content containing ASCII NUL
1517 characters does I<not> work, even if the length is specified.
1518 We hope to resolve this bug in a future version.  In the meantime
1519 use C<guestfs_upload>.");
1520
1521   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1522    [InitEmpty, Always, TestOutputListOfDevices (
1523       [["part_disk"; "/dev/sda"; "mbr"];
1524        ["mkfs"; "ext2"; "/dev/sda1"];
1525        ["mount_options"; ""; "/dev/sda1"; "/"];
1526        ["mounts"]], ["/dev/sda1"]);
1527     InitEmpty, Always, TestOutputList (
1528       [["part_disk"; "/dev/sda"; "mbr"];
1529        ["mkfs"; "ext2"; "/dev/sda1"];
1530        ["mount_options"; ""; "/dev/sda1"; "/"];
1531        ["umount"; "/"];
1532        ["mounts"]], [])],
1533    "unmount a filesystem",
1534    "\
1535 This unmounts the given filesystem.  The filesystem may be
1536 specified either by its mountpoint (path) or the device which
1537 contains the filesystem.");
1538
1539   ("mounts", (RStringList "devices", []), 46, [],
1540    [InitBasicFS, Always, TestOutputListOfDevices (
1541       [["mounts"]], ["/dev/sda1"])],
1542    "show mounted filesystems",
1543    "\
1544 This returns the list of currently mounted filesystems.  It returns
1545 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1546
1547 Some internal mounts are not shown.
1548
1549 See also: C<guestfs_mountpoints>");
1550
1551   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1552    [InitBasicFS, Always, TestOutputList (
1553       [["umount_all"];
1554        ["mounts"]], []);
1555     (* check that umount_all can unmount nested mounts correctly: *)
1556     InitEmpty, Always, TestOutputList (
1557       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1558        ["mkfs"; "ext2"; "/dev/sda1"];
1559        ["mkfs"; "ext2"; "/dev/sda2"];
1560        ["mkfs"; "ext2"; "/dev/sda3"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mkdir"; "/mp1"];
1563        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1564        ["mkdir"; "/mp1/mp2"];
1565        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1566        ["mkdir"; "/mp1/mp2/mp3"];
1567        ["umount_all"];
1568        ["mounts"]], [])],
1569    "unmount all filesystems",
1570    "\
1571 This unmounts all mounted filesystems.
1572
1573 Some internal mounts are not unmounted by this call.");
1574
1575   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1576    [],
1577    "remove all LVM LVs, VGs and PVs",
1578    "\
1579 This command removes all LVM logical volumes, volume groups
1580 and physical volumes.");
1581
1582   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1583    [InitISOFS, Always, TestOutput (
1584       [["file"; "/empty"]], "empty");
1585     InitISOFS, Always, TestOutput (
1586       [["file"; "/known-1"]], "ASCII text");
1587     InitISOFS, Always, TestLastFail (
1588       [["file"; "/notexists"]])],
1589    "determine file type",
1590    "\
1591 This call uses the standard L<file(1)> command to determine
1592 the type or contents of the file.  This also works on devices,
1593 for example to find out whether a partition contains a filesystem.
1594
1595 This call will also transparently look inside various types
1596 of compressed file.
1597
1598 The exact command which runs is C<file -zbsL path>.  Note in
1599 particular that the filename is not prepended to the output
1600 (the C<-b> option).");
1601
1602   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1603    [InitBasicFS, Always, TestOutput (
1604       [["upload"; "test-command"; "/test-command"];
1605        ["chmod"; "0o755"; "/test-command"];
1606        ["command"; "/test-command 1"]], "Result1");
1607     InitBasicFS, Always, TestOutput (
1608       [["upload"; "test-command"; "/test-command"];
1609        ["chmod"; "0o755"; "/test-command"];
1610        ["command"; "/test-command 2"]], "Result2\n");
1611     InitBasicFS, Always, TestOutput (
1612       [["upload"; "test-command"; "/test-command"];
1613        ["chmod"; "0o755"; "/test-command"];
1614        ["command"; "/test-command 3"]], "\nResult3");
1615     InitBasicFS, Always, TestOutput (
1616       [["upload"; "test-command"; "/test-command"];
1617        ["chmod"; "0o755"; "/test-command"];
1618        ["command"; "/test-command 4"]], "\nResult4\n");
1619     InitBasicFS, Always, TestOutput (
1620       [["upload"; "test-command"; "/test-command"];
1621        ["chmod"; "0o755"; "/test-command"];
1622        ["command"; "/test-command 5"]], "\nResult5\n\n");
1623     InitBasicFS, Always, TestOutput (
1624       [["upload"; "test-command"; "/test-command"];
1625        ["chmod"; "0o755"; "/test-command"];
1626        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1627     InitBasicFS, Always, TestOutput (
1628       [["upload"; "test-command"; "/test-command"];
1629        ["chmod"; "0o755"; "/test-command"];
1630        ["command"; "/test-command 7"]], "");
1631     InitBasicFS, Always, TestOutput (
1632       [["upload"; "test-command"; "/test-command"];
1633        ["chmod"; "0o755"; "/test-command"];
1634        ["command"; "/test-command 8"]], "\n");
1635     InitBasicFS, Always, TestOutput (
1636       [["upload"; "test-command"; "/test-command"];
1637        ["chmod"; "0o755"; "/test-command"];
1638        ["command"; "/test-command 9"]], "\n\n");
1639     InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1647     InitBasicFS, Always, TestLastFail (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command"]])],
1651    "run a command from the guest filesystem",
1652    "\
1653 This call runs a command from the guest filesystem.  The
1654 filesystem must be mounted, and must contain a compatible
1655 operating system (ie. something Linux, with the same
1656 or compatible processor architecture).
1657
1658 The single parameter is an argv-style list of arguments.
1659 The first element is the name of the program to run.
1660 Subsequent elements are parameters.  The list must be
1661 non-empty (ie. must contain a program name).  Note that
1662 the command runs directly, and is I<not> invoked via
1663 the shell (see C<guestfs_sh>).
1664
1665 The return value is anything printed to I<stdout> by
1666 the command.
1667
1668 If the command returns a non-zero exit status, then
1669 this function returns an error message.  The error message
1670 string is the content of I<stderr> from the command.
1671
1672 The C<$PATH> environment variable will contain at least
1673 C</usr/bin> and C</bin>.  If you require a program from
1674 another location, you should provide the full path in the
1675 first parameter.
1676
1677 Shared libraries and data files required by the program
1678 must be available on filesystems which are mounted in the
1679 correct places.  It is the caller's responsibility to ensure
1680 all filesystems that are needed are mounted at the right
1681 locations.");
1682
1683   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1684    [InitBasicFS, Always, TestOutputList (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command_lines"; "/test-command 1"]], ["Result1"]);
1688     InitBasicFS, Always, TestOutputList (
1689       [["upload"; "test-command"; "/test-command"];
1690        ["chmod"; "0o755"; "/test-command"];
1691        ["command_lines"; "/test-command 2"]], ["Result2"]);
1692     InitBasicFS, Always, TestOutputList (
1693       [["upload"; "test-command"; "/test-command"];
1694        ["chmod"; "0o755"; "/test-command"];
1695        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1696     InitBasicFS, Always, TestOutputList (
1697       [["upload"; "test-command"; "/test-command"];
1698        ["chmod"; "0o755"; "/test-command"];
1699        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1700     InitBasicFS, Always, TestOutputList (
1701       [["upload"; "test-command"; "/test-command"];
1702        ["chmod"; "0o755"; "/test-command"];
1703        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1704     InitBasicFS, Always, TestOutputList (
1705       [["upload"; "test-command"; "/test-command"];
1706        ["chmod"; "0o755"; "/test-command"];
1707        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1708     InitBasicFS, Always, TestOutputList (
1709       [["upload"; "test-command"; "/test-command"];
1710        ["chmod"; "0o755"; "/test-command"];
1711        ["command_lines"; "/test-command 7"]], []);
1712     InitBasicFS, Always, TestOutputList (
1713       [["upload"; "test-command"; "/test-command"];
1714        ["chmod"; "0o755"; "/test-command"];
1715        ["command_lines"; "/test-command 8"]], [""]);
1716     InitBasicFS, Always, TestOutputList (
1717       [["upload"; "test-command"; "/test-command"];
1718        ["chmod"; "0o755"; "/test-command"];
1719        ["command_lines"; "/test-command 9"]], ["";""]);
1720     InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1728    "run a command, returning lines",
1729    "\
1730 This is the same as C<guestfs_command>, but splits the
1731 result into a list of lines.
1732
1733 See also: C<guestfs_sh_lines>");
1734
1735   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1736    [InitISOFS, Always, TestOutputStruct (
1737       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1738    "get file information",
1739    "\
1740 Returns file information for the given C<path>.
1741
1742 This is the same as the C<stat(2)> system call.");
1743
1744   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1745    [InitISOFS, Always, TestOutputStruct (
1746       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1747    "get file information for a symbolic link",
1748    "\
1749 Returns file information for the given C<path>.
1750
1751 This is the same as C<guestfs_stat> except that if C<path>
1752 is a symbolic link, then the link is stat-ed, not the file it
1753 refers to.
1754
1755 This is the same as the C<lstat(2)> system call.");
1756
1757   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1758    [InitISOFS, Always, TestOutputStruct (
1759       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1760    "get file system statistics",
1761    "\
1762 Returns file system statistics for any mounted file system.
1763 C<path> should be a file or directory in the mounted file system
1764 (typically it is the mount point itself, but it doesn't need to be).
1765
1766 This is the same as the C<statvfs(2)> system call.");
1767
1768   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1769    [], (* XXX test *)
1770    "get ext2/ext3/ext4 superblock details",
1771    "\
1772 This returns the contents of the ext2, ext3 or ext4 filesystem
1773 superblock on C<device>.
1774
1775 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1776 manpage for more details.  The list of fields returned isn't
1777 clearly defined, and depends on both the version of C<tune2fs>
1778 that libguestfs was built against, and the filesystem itself.");
1779
1780   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1781    [InitEmpty, Always, TestOutputTrue (
1782       [["blockdev_setro"; "/dev/sda"];
1783        ["blockdev_getro"; "/dev/sda"]])],
1784    "set block device to read-only",
1785    "\
1786 Sets the block device named C<device> to read-only.
1787
1788 This uses the L<blockdev(8)> command.");
1789
1790   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1791    [InitEmpty, Always, TestOutputFalse (
1792       [["blockdev_setrw"; "/dev/sda"];
1793        ["blockdev_getro"; "/dev/sda"]])],
1794    "set block device to read-write",
1795    "\
1796 Sets the block device named C<device> to read-write.
1797
1798 This uses the L<blockdev(8)> command.");
1799
1800   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1801    [InitEmpty, Always, TestOutputTrue (
1802       [["blockdev_setro"; "/dev/sda"];
1803        ["blockdev_getro"; "/dev/sda"]])],
1804    "is block device set to read-only",
1805    "\
1806 Returns a boolean indicating if the block device is read-only
1807 (true if read-only, false if not).
1808
1809 This uses the L<blockdev(8)> command.");
1810
1811   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1812    [InitEmpty, Always, TestOutputInt (
1813       [["blockdev_getss"; "/dev/sda"]], 512)],
1814    "get sectorsize of block device",
1815    "\
1816 This returns the size of sectors on a block device.
1817 Usually 512, but can be larger for modern devices.
1818
1819 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1820 for that).
1821
1822 This uses the L<blockdev(8)> command.");
1823
1824   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1825    [InitEmpty, Always, TestOutputInt (
1826       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1827    "get blocksize of block device",
1828    "\
1829 This returns the block size of a device.
1830
1831 (Note this is different from both I<size in blocks> and
1832 I<filesystem block size>).
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1837    [], (* XXX test *)
1838    "set blocksize of block device",
1839    "\
1840 This sets the block size of a device.
1841
1842 (Note this is different from both I<size in blocks> and
1843 I<filesystem block size>).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1850    "get total size of device in 512-byte sectors",
1851    "\
1852 This returns the size of the device in units of 512-byte sectors
1853 (even if the sectorsize isn't 512 bytes ... weird).
1854
1855 See also C<guestfs_blockdev_getss> for the real sector size of
1856 the device, and C<guestfs_blockdev_getsize64> for the more
1857 useful I<size in bytes>.
1858
1859 This uses the L<blockdev(8)> command.");
1860
1861   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1862    [InitEmpty, Always, TestOutputInt (
1863       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1864    "get total size of device in bytes",
1865    "\
1866 This returns the size of the device in bytes.
1867
1868 See also C<guestfs_blockdev_getsz>.
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1873    [InitEmpty, Always, TestRun
1874       [["blockdev_flushbufs"; "/dev/sda"]]],
1875    "flush device buffers",
1876    "\
1877 This tells the kernel to flush internal buffers associated
1878 with C<device>.
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1883    [InitEmpty, Always, TestRun
1884       [["blockdev_rereadpt"; "/dev/sda"]]],
1885    "reread partition table",
1886    "\
1887 Reread the partition table on C<device>.
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1892    [InitBasicFS, Always, TestOutput (
1893       (* Pick a file from cwd which isn't likely to change. *)
1894       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1895        ["checksum"; "md5"; "/COPYING.LIB"]],
1896       Digest.to_hex (Digest.file "COPYING.LIB"))],
1897    "upload a file from the local machine",
1898    "\
1899 Upload local file C<filename> to C<remotefilename> on the
1900 filesystem.
1901
1902 C<filename> can also be a named pipe.
1903
1904 See also C<guestfs_download>.");
1905
1906   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1907    [InitBasicFS, Always, TestOutput (
1908       (* Pick a file from cwd which isn't likely to change. *)
1909       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1910        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1911        ["upload"; "testdownload.tmp"; "/upload"];
1912        ["checksum"; "md5"; "/upload"]],
1913       Digest.to_hex (Digest.file "COPYING.LIB"))],
1914    "download a file to the local machine",
1915    "\
1916 Download file C<remotefilename> and save it as C<filename>
1917 on the local machine.
1918
1919 C<filename> can also be a named pipe.
1920
1921 See also C<guestfs_upload>, C<guestfs_cat>.");
1922
1923   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1924    [InitISOFS, Always, TestOutput (
1925       [["checksum"; "crc"; "/known-3"]], "2891671662");
1926     InitISOFS, Always, TestLastFail (
1927       [["checksum"; "crc"; "/notexists"]]);
1928     InitISOFS, Always, TestOutput (
1929       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1930     InitISOFS, Always, TestOutput (
1931       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1932     InitISOFS, Always, TestOutput (
1933       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1934     InitISOFS, Always, TestOutput (
1935       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1936     InitISOFS, Always, TestOutput (
1937       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1938     InitISOFS, Always, TestOutput (
1939       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1940    "compute MD5, SHAx or CRC checksum of file",
1941    "\
1942 This call computes the MD5, SHAx or CRC checksum of the
1943 file named C<path>.
1944
1945 The type of checksum to compute is given by the C<csumtype>
1946 parameter which must have one of the following values:
1947
1948 =over 4
1949
1950 =item C<crc>
1951
1952 Compute the cyclic redundancy check (CRC) specified by POSIX
1953 for the C<cksum> command.
1954
1955 =item C<md5>
1956
1957 Compute the MD5 hash (using the C<md5sum> program).
1958
1959 =item C<sha1>
1960
1961 Compute the SHA1 hash (using the C<sha1sum> program).
1962
1963 =item C<sha224>
1964
1965 Compute the SHA224 hash (using the C<sha224sum> program).
1966
1967 =item C<sha256>
1968
1969 Compute the SHA256 hash (using the C<sha256sum> program).
1970
1971 =item C<sha384>
1972
1973 Compute the SHA384 hash (using the C<sha384sum> program).
1974
1975 =item C<sha512>
1976
1977 Compute the SHA512 hash (using the C<sha512sum> program).
1978
1979 =back
1980
1981 The checksum is returned as a printable string.");
1982
1983   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1984    [InitBasicFS, Always, TestOutput (
1985       [["tar_in"; "../images/helloworld.tar"; "/"];
1986        ["cat"; "/hello"]], "hello\n")],
1987    "unpack tarfile to directory",
1988    "\
1989 This command uploads and unpacks local file C<tarfile> (an
1990 I<uncompressed> tar file) into C<directory>.
1991
1992 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1993
1994   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1995    [],
1996    "pack directory into tarfile",
1997    "\
1998 This command packs the contents of C<directory> and downloads
1999 it to local file C<tarfile>.
2000
2001 To download a compressed tarball, use C<guestfs_tgz_out>.");
2002
2003   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2004    [InitBasicFS, Always, TestOutput (
2005       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2006        ["cat"; "/hello"]], "hello\n")],
2007    "unpack compressed tarball to directory",
2008    "\
2009 This command uploads and unpacks local file C<tarball> (a
2010 I<gzip compressed> tar file) into C<directory>.
2011
2012 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2013
2014   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2015    [],
2016    "pack directory into compressed tarball",
2017    "\
2018 This command packs the contents of C<directory> and downloads
2019 it to local file C<tarball>.
2020
2021 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2022
2023   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2024    [InitBasicFS, Always, TestLastFail (
2025       [["umount"; "/"];
2026        ["mount_ro"; "/dev/sda1"; "/"];
2027        ["touch"; "/new"]]);
2028     InitBasicFS, Always, TestOutput (
2029       [["write_file"; "/new"; "data"; "0"];
2030        ["umount"; "/"];
2031        ["mount_ro"; "/dev/sda1"; "/"];
2032        ["cat"; "/new"]], "data")],
2033    "mount a guest disk, read-only",
2034    "\
2035 This is the same as the C<guestfs_mount> command, but it
2036 mounts the filesystem with the read-only (I<-o ro>) flag.");
2037
2038   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2039    [],
2040    "mount a guest disk with mount options",
2041    "\
2042 This is the same as the C<guestfs_mount> command, but it
2043 allows you to set the mount options as for the
2044 L<mount(8)> I<-o> flag.");
2045
2046   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2047    [],
2048    "mount a guest disk with mount options and vfstype",
2049    "\
2050 This is the same as the C<guestfs_mount> command, but it
2051 allows you to set both the mount options and the vfstype
2052 as for the L<mount(8)> I<-o> and I<-t> flags.");
2053
2054   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2055    [],
2056    "debugging and internals",
2057    "\
2058 The C<guestfs_debug> command exposes some internals of
2059 C<guestfsd> (the guestfs daemon) that runs inside the
2060 qemu subprocess.
2061
2062 There is no comprehensive help for this command.  You have
2063 to look at the file C<daemon/debug.c> in the libguestfs source
2064 to find out what you can do.");
2065
2066   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2067    [InitEmpty, Always, TestOutputList (
2068       [["part_disk"; "/dev/sda"; "mbr"];
2069        ["pvcreate"; "/dev/sda1"];
2070        ["vgcreate"; "VG"; "/dev/sda1"];
2071        ["lvcreate"; "LV1"; "VG"; "50"];
2072        ["lvcreate"; "LV2"; "VG"; "50"];
2073        ["lvremove"; "/dev/VG/LV1"];
2074        ["lvs"]], ["/dev/VG/LV2"]);
2075     InitEmpty, Always, TestOutputList (
2076       [["part_disk"; "/dev/sda"; "mbr"];
2077        ["pvcreate"; "/dev/sda1"];
2078        ["vgcreate"; "VG"; "/dev/sda1"];
2079        ["lvcreate"; "LV1"; "VG"; "50"];
2080        ["lvcreate"; "LV2"; "VG"; "50"];
2081        ["lvremove"; "/dev/VG"];
2082        ["lvs"]], []);
2083     InitEmpty, Always, TestOutputList (
2084       [["part_disk"; "/dev/sda"; "mbr"];
2085        ["pvcreate"; "/dev/sda1"];
2086        ["vgcreate"; "VG"; "/dev/sda1"];
2087        ["lvcreate"; "LV1"; "VG"; "50"];
2088        ["lvcreate"; "LV2"; "VG"; "50"];
2089        ["lvremove"; "/dev/VG"];
2090        ["vgs"]], ["VG"])],
2091    "remove an LVM logical volume",
2092    "\
2093 Remove an LVM logical volume C<device>, where C<device> is
2094 the path to the LV, such as C</dev/VG/LV>.
2095
2096 You can also remove all LVs in a volume group by specifying
2097 the VG name, C</dev/VG>.");
2098
2099   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2100    [InitEmpty, Always, TestOutputList (
2101       [["part_disk"; "/dev/sda"; "mbr"];
2102        ["pvcreate"; "/dev/sda1"];
2103        ["vgcreate"; "VG"; "/dev/sda1"];
2104        ["lvcreate"; "LV1"; "VG"; "50"];
2105        ["lvcreate"; "LV2"; "VG"; "50"];
2106        ["vgremove"; "VG"];
2107        ["lvs"]], []);
2108     InitEmpty, Always, TestOutputList (
2109       [["part_disk"; "/dev/sda"; "mbr"];
2110        ["pvcreate"; "/dev/sda1"];
2111        ["vgcreate"; "VG"; "/dev/sda1"];
2112        ["lvcreate"; "LV1"; "VG"; "50"];
2113        ["lvcreate"; "LV2"; "VG"; "50"];
2114        ["vgremove"; "VG"];
2115        ["vgs"]], [])],
2116    "remove an LVM volume group",
2117    "\
2118 Remove an LVM volume group C<vgname>, (for example C<VG>).
2119
2120 This also forcibly removes all logical volumes in the volume
2121 group (if any).");
2122
2123   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2124    [InitEmpty, Always, TestOutputListOfDevices (
2125       [["part_disk"; "/dev/sda"; "mbr"];
2126        ["pvcreate"; "/dev/sda1"];
2127        ["vgcreate"; "VG"; "/dev/sda1"];
2128        ["lvcreate"; "LV1"; "VG"; "50"];
2129        ["lvcreate"; "LV2"; "VG"; "50"];
2130        ["vgremove"; "VG"];
2131        ["pvremove"; "/dev/sda1"];
2132        ["lvs"]], []);
2133     InitEmpty, Always, TestOutputListOfDevices (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["vgremove"; "VG"];
2140        ["pvremove"; "/dev/sda1"];
2141        ["vgs"]], []);
2142     InitEmpty, Always, TestOutputListOfDevices (
2143       [["part_disk"; "/dev/sda"; "mbr"];
2144        ["pvcreate"; "/dev/sda1"];
2145        ["vgcreate"; "VG"; "/dev/sda1"];
2146        ["lvcreate"; "LV1"; "VG"; "50"];
2147        ["lvcreate"; "LV2"; "VG"; "50"];
2148        ["vgremove"; "VG"];
2149        ["pvremove"; "/dev/sda1"];
2150        ["pvs"]], [])],
2151    "remove an LVM physical volume",
2152    "\
2153 This wipes a physical volume C<device> so that LVM will no longer
2154 recognise it.
2155
2156 The implementation uses the C<pvremove> command which refuses to
2157 wipe physical volumes that contain any volume groups, so you have
2158 to remove those first.");
2159
2160   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2161    [InitBasicFS, Always, TestOutput (
2162       [["set_e2label"; "/dev/sda1"; "testlabel"];
2163        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2164    "set the ext2/3/4 filesystem label",
2165    "\
2166 This sets the ext2/3/4 filesystem label of the filesystem on
2167 C<device> to C<label>.  Filesystem labels are limited to
2168 16 characters.
2169
2170 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2171 to return the existing label on a filesystem.");
2172
2173   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2174    [],
2175    "get the ext2/3/4 filesystem label",
2176    "\
2177 This returns the ext2/3/4 filesystem label of the filesystem on
2178 C<device>.");
2179
2180   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2181    (let uuid = uuidgen () in
2182     [InitBasicFS, Always, TestOutput (
2183        [["set_e2uuid"; "/dev/sda1"; uuid];
2184         ["get_e2uuid"; "/dev/sda1"]], uuid);
2185      InitBasicFS, Always, TestOutput (
2186        [["set_e2uuid"; "/dev/sda1"; "clear"];
2187         ["get_e2uuid"; "/dev/sda1"]], "");
2188      (* We can't predict what UUIDs will be, so just check the commands run. *)
2189      InitBasicFS, Always, TestRun (
2190        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2191      InitBasicFS, Always, TestRun (
2192        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2193    "set the ext2/3/4 filesystem UUID",
2194    "\
2195 This sets the ext2/3/4 filesystem UUID of the filesystem on
2196 C<device> to C<uuid>.  The format of the UUID and alternatives
2197 such as C<clear>, C<random> and C<time> are described in the
2198 L<tune2fs(8)> manpage.
2199
2200 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2201 to return the existing UUID of a filesystem.");
2202
2203   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2204    [],
2205    "get the ext2/3/4 filesystem UUID",
2206    "\
2207 This returns the ext2/3/4 filesystem UUID of the filesystem on
2208 C<device>.");
2209
2210   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2211    [InitBasicFS, Always, TestOutputInt (
2212       [["umount"; "/dev/sda1"];
2213        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2214     InitBasicFS, Always, TestOutputInt (
2215       [["umount"; "/dev/sda1"];
2216        ["zero"; "/dev/sda1"];
2217        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2218    "run the filesystem checker",
2219    "\
2220 This runs the filesystem checker (fsck) on C<device> which
2221 should have filesystem type C<fstype>.
2222
2223 The returned integer is the status.  See L<fsck(8)> for the
2224 list of status codes from C<fsck>.
2225
2226 Notes:
2227
2228 =over 4
2229
2230 =item *
2231
2232 Multiple status codes can be summed together.
2233
2234 =item *
2235
2236 A non-zero return code can mean \"success\", for example if
2237 errors have been corrected on the filesystem.
2238
2239 =item *
2240
2241 Checking or repairing NTFS volumes is not supported
2242 (by linux-ntfs).
2243
2244 =back
2245
2246 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2247
2248   ("zero", (RErr, [Device "device"]), 85, [],
2249    [InitBasicFS, Always, TestOutput (
2250       [["umount"; "/dev/sda1"];
2251        ["zero"; "/dev/sda1"];
2252        ["file"; "/dev/sda1"]], "data")],
2253    "write zeroes to the device",
2254    "\
2255 This command writes zeroes over the first few blocks of C<device>.
2256
2257 How many blocks are zeroed isn't specified (but it's I<not> enough
2258 to securely wipe the device).  It should be sufficient to remove
2259 any partition tables, filesystem superblocks and so on.
2260
2261 See also: C<guestfs_scrub_device>.");
2262
2263   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2264    (* Test disabled because grub-install incompatible with virtio-blk driver.
2265     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2266     *)
2267    [InitBasicFS, Disabled, TestOutputTrue (
2268       [["grub_install"; "/"; "/dev/sda1"];
2269        ["is_dir"; "/boot"]])],
2270    "install GRUB",
2271    "\
2272 This command installs GRUB (the Grand Unified Bootloader) on
2273 C<device>, with the root directory being C<root>.");
2274
2275   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2276    [InitBasicFS, Always, TestOutput (
2277       [["write_file"; "/old"; "file content"; "0"];
2278        ["cp"; "/old"; "/new"];
2279        ["cat"; "/new"]], "file content");
2280     InitBasicFS, Always, TestOutputTrue (
2281       [["write_file"; "/old"; "file content"; "0"];
2282        ["cp"; "/old"; "/new"];
2283        ["is_file"; "/old"]]);
2284     InitBasicFS, Always, TestOutput (
2285       [["write_file"; "/old"; "file content"; "0"];
2286        ["mkdir"; "/dir"];
2287        ["cp"; "/old"; "/dir/new"];
2288        ["cat"; "/dir/new"]], "file content")],
2289    "copy a file",
2290    "\
2291 This copies a file from C<src> to C<dest> where C<dest> is
2292 either a destination filename or destination directory.");
2293
2294   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2295    [InitBasicFS, Always, TestOutput (
2296       [["mkdir"; "/olddir"];
2297        ["mkdir"; "/newdir"];
2298        ["write_file"; "/olddir/file"; "file content"; "0"];
2299        ["cp_a"; "/olddir"; "/newdir"];
2300        ["cat"; "/newdir/olddir/file"]], "file content")],
2301    "copy a file or directory recursively",
2302    "\
2303 This copies a file or directory from C<src> to C<dest>
2304 recursively using the C<cp -a> command.");
2305
2306   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2307    [InitBasicFS, Always, TestOutput (
2308       [["write_file"; "/old"; "file content"; "0"];
2309        ["mv"; "/old"; "/new"];
2310        ["cat"; "/new"]], "file content");
2311     InitBasicFS, Always, TestOutputFalse (
2312       [["write_file"; "/old"; "file content"; "0"];
2313        ["mv"; "/old"; "/new"];
2314        ["is_file"; "/old"]])],
2315    "move a file",
2316    "\
2317 This moves a file from C<src> to C<dest> where C<dest> is
2318 either a destination filename or destination directory.");
2319
2320   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2321    [InitEmpty, Always, TestRun (
2322       [["drop_caches"; "3"]])],
2323    "drop kernel page cache, dentries and inodes",
2324    "\
2325 This instructs the guest kernel to drop its page cache,
2326 and/or dentries and inode caches.  The parameter C<whattodrop>
2327 tells the kernel what precisely to drop, see
2328 L<http://linux-mm.org/Drop_Caches>
2329
2330 Setting C<whattodrop> to 3 should drop everything.
2331
2332 This automatically calls L<sync(2)> before the operation,
2333 so that the maximum guest memory is freed.");
2334
2335   ("dmesg", (RString "kmsgs", []), 91, [],
2336    [InitEmpty, Always, TestRun (
2337       [["dmesg"]])],
2338    "return kernel messages",
2339    "\
2340 This returns the kernel messages (C<dmesg> output) from
2341 the guest kernel.  This is sometimes useful for extended
2342 debugging of problems.
2343
2344 Another way to get the same information is to enable
2345 verbose messages with C<guestfs_set_verbose> or by setting
2346 the environment variable C<LIBGUESTFS_DEBUG=1> before
2347 running the program.");
2348
2349   ("ping_daemon", (RErr, []), 92, [],
2350    [InitEmpty, Always, TestRun (
2351       [["ping_daemon"]])],
2352    "ping the guest daemon",
2353    "\
2354 This is a test probe into the guestfs daemon running inside
2355 the qemu subprocess.  Calling this function checks that the
2356 daemon responds to the ping message, without affecting the daemon
2357 or attached block device(s) in any other way.");
2358
2359   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2360    [InitBasicFS, Always, TestOutputTrue (
2361       [["write_file"; "/file1"; "contents of a file"; "0"];
2362        ["cp"; "/file1"; "/file2"];
2363        ["equal"; "/file1"; "/file2"]]);
2364     InitBasicFS, Always, TestOutputFalse (
2365       [["write_file"; "/file1"; "contents of a file"; "0"];
2366        ["write_file"; "/file2"; "contents of another file"; "0"];
2367        ["equal"; "/file1"; "/file2"]]);
2368     InitBasicFS, Always, TestLastFail (
2369       [["equal"; "/file1"; "/file2"]])],
2370    "test if two files have equal contents",
2371    "\
2372 This compares the two files C<file1> and C<file2> and returns
2373 true if their content is exactly equal, or false otherwise.
2374
2375 The external L<cmp(1)> program is used for the comparison.");
2376
2377   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2378    [InitISOFS, Always, TestOutputList (
2379       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2380     InitISOFS, Always, TestOutputList (
2381       [["strings"; "/empty"]], [])],
2382    "print the printable strings in a file",
2383    "\
2384 This runs the L<strings(1)> command on a file and returns
2385 the list of printable strings found.");
2386
2387   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2388    [InitISOFS, Always, TestOutputList (
2389       [["strings_e"; "b"; "/known-5"]], []);
2390     InitBasicFS, Disabled, TestOutputList (
2391       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2392        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2393    "print the printable strings in a file",
2394    "\
2395 This is like the C<guestfs_strings> command, but allows you to
2396 specify the encoding.
2397
2398 See the L<strings(1)> manpage for the full list of encodings.
2399
2400 Commonly useful encodings are C<l> (lower case L) which will
2401 show strings inside Windows/x86 files.
2402
2403 The returned strings are transcoded to UTF-8.");
2404
2405   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2406    [InitISOFS, Always, TestOutput (
2407       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2408     (* Test for RHBZ#501888c2 regression which caused large hexdump
2409      * commands to segfault.
2410      *)
2411     InitISOFS, Always, TestRun (
2412       [["hexdump"; "/100krandom"]])],
2413    "dump a file in hexadecimal",
2414    "\
2415 This runs C<hexdump -C> on the given C<path>.  The result is
2416 the human-readable, canonical hex dump of the file.");
2417
2418   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2419    [InitNone, Always, TestOutput (
2420       [["part_disk"; "/dev/sda"; "mbr"];
2421        ["mkfs"; "ext3"; "/dev/sda1"];
2422        ["mount_options"; ""; "/dev/sda1"; "/"];
2423        ["write_file"; "/new"; "test file"; "0"];
2424        ["umount"; "/dev/sda1"];
2425        ["zerofree"; "/dev/sda1"];
2426        ["mount_options"; ""; "/dev/sda1"; "/"];
2427        ["cat"; "/new"]], "test file")],
2428    "zero unused inodes and disk blocks on ext2/3 filesystem",
2429    "\
2430 This runs the I<zerofree> program on C<device>.  This program
2431 claims to zero unused inodes and disk blocks on an ext2/3
2432 filesystem, thus making it possible to compress the filesystem
2433 more effectively.
2434
2435 You should B<not> run this program if the filesystem is
2436 mounted.
2437
2438 It is possible that using this program can damage the filesystem
2439 or data on the filesystem.");
2440
2441   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2442    [],
2443    "resize an LVM physical volume",
2444    "\
2445 This resizes (expands or shrinks) an existing LVM physical
2446 volume to match the new size of the underlying device.");
2447
2448   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2449                        Int "cyls"; Int "heads"; Int "sectors";
2450                        String "line"]), 99, [DangerWillRobinson],
2451    [],
2452    "modify a single partition on a block device",
2453    "\
2454 This runs L<sfdisk(8)> option to modify just the single
2455 partition C<n> (note: C<n> counts from 1).
2456
2457 For other parameters, see C<guestfs_sfdisk>.  You should usually
2458 pass C<0> for the cyls/heads/sectors parameters.
2459
2460 See also: C<guestfs_part_add>");
2461
2462   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2463    [],
2464    "display the partition table",
2465    "\
2466 This displays the partition table on C<device>, in the
2467 human-readable output of the L<sfdisk(8)> command.  It is
2468 not intended to be parsed.
2469
2470 See also: C<guestfs_part_list>");
2471
2472   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2473    [],
2474    "display the kernel geometry",
2475    "\
2476 This displays the kernel's idea of the geometry of C<device>.
2477
2478 The result is in human-readable format, and not designed to
2479 be parsed.");
2480
2481   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2482    [],
2483    "display the disk geometry from the partition table",
2484    "\
2485 This displays the disk geometry of C<device> read from the
2486 partition table.  Especially in the case where the underlying
2487 block device has been resized, this can be different from the
2488 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2489
2490 The result is in human-readable format, and not designed to
2491 be parsed.");
2492
2493   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2494    [],
2495    "activate or deactivate all volume groups",
2496    "\
2497 This command activates or (if C<activate> is false) deactivates
2498 all logical volumes in all volume groups.
2499 If activated, then they are made known to the
2500 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2501 then those devices disappear.
2502
2503 This command is the same as running C<vgchange -a y|n>");
2504
2505   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2506    [],
2507    "activate or deactivate some volume groups",
2508    "\
2509 This command activates or (if C<activate> is false) deactivates
2510 all logical volumes in the listed volume groups C<volgroups>.
2511 If activated, then they are made known to the
2512 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2513 then those devices disappear.
2514
2515 This command is the same as running C<vgchange -a y|n volgroups...>
2516
2517 Note that if C<volgroups> is an empty list then B<all> volume groups
2518 are activated or deactivated.");
2519
2520   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2521    [InitNone, Always, TestOutput (
2522       [["part_disk"; "/dev/sda"; "mbr"];
2523        ["pvcreate"; "/dev/sda1"];
2524        ["vgcreate"; "VG"; "/dev/sda1"];
2525        ["lvcreate"; "LV"; "VG"; "10"];
2526        ["mkfs"; "ext2"; "/dev/VG/LV"];
2527        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2528        ["write_file"; "/new"; "test content"; "0"];
2529        ["umount"; "/"];
2530        ["lvresize"; "/dev/VG/LV"; "20"];
2531        ["e2fsck_f"; "/dev/VG/LV"];
2532        ["resize2fs"; "/dev/VG/LV"];
2533        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2534        ["cat"; "/new"]], "test content")],
2535    "resize an LVM logical volume",
2536    "\
2537 This resizes (expands or shrinks) an existing LVM logical
2538 volume to C<mbytes>.  When reducing, data in the reduced part
2539 is lost.");
2540
2541   ("resize2fs", (RErr, [Device "device"]), 106, [],
2542    [], (* lvresize tests this *)
2543    "resize an ext2/ext3 filesystem",
2544    "\
2545 This resizes an ext2 or ext3 filesystem to match the size of
2546 the underlying device.
2547
2548 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2549 on the C<device> before calling this command.  For unknown reasons
2550 C<resize2fs> sometimes gives an error about this and sometimes not.
2551 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2552 calling this function.");
2553
2554   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2555    [InitBasicFS, Always, TestOutputList (
2556       [["find"; "/"]], ["lost+found"]);
2557     InitBasicFS, Always, TestOutputList (
2558       [["touch"; "/a"];
2559        ["mkdir"; "/b"];
2560        ["touch"; "/b/c"];
2561        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2562     InitBasicFS, Always, TestOutputList (
2563       [["mkdir_p"; "/a/b/c"];
2564        ["touch"; "/a/b/c/d"];
2565        ["find"; "/a/b/"]], ["c"; "c/d"])],
2566    "find all files and directories",
2567    "\
2568 This command lists out all files and directories, recursively,
2569 starting at C<directory>.  It is essentially equivalent to
2570 running the shell command C<find directory -print> but some
2571 post-processing happens on the output, described below.
2572
2573 This returns a list of strings I<without any prefix>.  Thus
2574 if the directory structure was:
2575
2576  /tmp/a
2577  /tmp/b
2578  /tmp/c/d
2579
2580 then the returned list from C<guestfs_find> C</tmp> would be
2581 4 elements:
2582
2583  a
2584  b
2585  c
2586  c/d
2587
2588 If C<directory> is not a directory, then this command returns
2589 an error.
2590
2591 The returned list is sorted.
2592
2593 See also C<guestfs_find0>.");
2594
2595   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2596    [], (* lvresize tests this *)
2597    "check an ext2/ext3 filesystem",
2598    "\
2599 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2600 filesystem checker on C<device>, noninteractively (C<-p>),
2601 even if the filesystem appears to be clean (C<-f>).
2602
2603 This command is only needed because of C<guestfs_resize2fs>
2604 (q.v.).  Normally you should use C<guestfs_fsck>.");
2605
2606   ("sleep", (RErr, [Int "secs"]), 109, [],
2607    [InitNone, Always, TestRun (
2608       [["sleep"; "1"]])],
2609    "sleep for some seconds",
2610    "\
2611 Sleep for C<secs> seconds.");
2612
2613   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2614    [InitNone, Always, TestOutputInt (
2615       [["part_disk"; "/dev/sda"; "mbr"];
2616        ["mkfs"; "ntfs"; "/dev/sda1"];
2617        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2618     InitNone, Always, TestOutputInt (
2619       [["part_disk"; "/dev/sda"; "mbr"];
2620        ["mkfs"; "ext2"; "/dev/sda1"];
2621        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2622    "probe NTFS volume",
2623    "\
2624 This command runs the L<ntfs-3g.probe(8)> command which probes
2625 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2626 be mounted read-write, and some cannot be mounted at all).
2627
2628 C<rw> is a boolean flag.  Set it to true if you want to test
2629 if the volume can be mounted read-write.  Set it to false if
2630 you want to test if the volume can be mounted read-only.
2631
2632 The return value is an integer which C<0> if the operation
2633 would succeed, or some non-zero value documented in the
2634 L<ntfs-3g.probe(8)> manual page.");
2635
2636   ("sh", (RString "output", [String "command"]), 111, [],
2637    [], (* XXX needs tests *)
2638    "run a command via the shell",
2639    "\
2640 This call runs a command from the guest filesystem via the
2641 guest's C</bin/sh>.
2642
2643 This is like C<guestfs_command>, but passes the command to:
2644
2645  /bin/sh -c \"command\"
2646
2647 Depending on the guest's shell, this usually results in
2648 wildcards being expanded, shell expressions being interpolated
2649 and so on.
2650
2651 All the provisos about C<guestfs_command> apply to this call.");
2652
2653   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2654    [], (* XXX needs tests *)
2655    "run a command via the shell returning lines",
2656    "\
2657 This is the same as C<guestfs_sh>, but splits the result
2658 into a list of lines.
2659
2660 See also: C<guestfs_command_lines>");
2661
2662   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2663    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2664     * code in stubs.c, since all valid glob patterns must start with "/".
2665     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2666     *)
2667    [InitBasicFS, Always, TestOutputList (
2668       [["mkdir_p"; "/a/b/c"];
2669        ["touch"; "/a/b/c/d"];
2670        ["touch"; "/a/b/c/e"];
2671        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2672     InitBasicFS, Always, TestOutputList (
2673       [["mkdir_p"; "/a/b/c"];
2674        ["touch"; "/a/b/c/d"];
2675        ["touch"; "/a/b/c/e"];
2676        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2677     InitBasicFS, Always, TestOutputList (
2678       [["mkdir_p"; "/a/b/c"];
2679        ["touch"; "/a/b/c/d"];
2680        ["touch"; "/a/b/c/e"];
2681        ["glob_expand"; "/a/*/x/*"]], [])],
2682    "expand a wildcard path",
2683    "\
2684 This command searches for all the pathnames matching
2685 C<pattern> according to the wildcard expansion rules
2686 used by the shell.
2687
2688 If no paths match, then this returns an empty list
2689 (note: not an error).
2690
2691 It is just a wrapper around the C L<glob(3)> function
2692 with flags C<GLOB_MARK|GLOB_BRACE>.
2693 See that manual page for more details.");
2694
2695   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2696    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2697       [["scrub_device"; "/dev/sdc"]])],
2698    "scrub (securely wipe) a device",
2699    "\
2700 This command writes patterns over C<device> to make data retrieval
2701 more difficult.
2702
2703 It is an interface to the L<scrub(1)> program.  See that
2704 manual page for more details.");
2705
2706   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2707    [InitBasicFS, Always, TestRun (
2708       [["write_file"; "/file"; "content"; "0"];
2709        ["scrub_file"; "/file"]])],
2710    "scrub (securely wipe) a file",
2711    "\
2712 This command writes patterns over a file to make data retrieval
2713 more difficult.
2714
2715 The file is I<removed> after scrubbing.
2716
2717 It is an interface to the L<scrub(1)> program.  See that
2718 manual page for more details.");
2719
2720   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2721    [], (* XXX needs testing *)
2722    "scrub (securely wipe) free space",
2723    "\
2724 This command creates the directory C<dir> and then fills it
2725 with files until the filesystem is full, and scrubs the files
2726 as for C<guestfs_scrub_file>, and deletes them.
2727 The intention is to scrub any free space on the partition
2728 containing C<dir>.
2729
2730 It is an interface to the L<scrub(1)> program.  See that
2731 manual page for more details.");
2732
2733   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2734    [InitBasicFS, Always, TestRun (
2735       [["mkdir"; "/tmp"];
2736        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2737    "create a temporary directory",
2738    "\
2739 This command creates a temporary directory.  The
2740 C<template> parameter should be a full pathname for the
2741 temporary directory name with the final six characters being
2742 \"XXXXXX\".
2743
2744 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2745 the second one being suitable for Windows filesystems.
2746
2747 The name of the temporary directory that was created
2748 is returned.
2749
2750 The temporary directory is created with mode 0700
2751 and is owned by root.
2752
2753 The caller is responsible for deleting the temporary
2754 directory and its contents after use.
2755
2756 See also: L<mkdtemp(3)>");
2757
2758   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2759    [InitISOFS, Always, TestOutputInt (
2760       [["wc_l"; "/10klines"]], 10000)],
2761    "count lines in a file",
2762    "\
2763 This command counts the lines in a file, using the
2764 C<wc -l> external command.");
2765
2766   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2767    [InitISOFS, Always, TestOutputInt (
2768       [["wc_w"; "/10klines"]], 10000)],
2769    "count words in a file",
2770    "\
2771 This command counts the words in a file, using the
2772 C<wc -w> external command.");
2773
2774   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2775    [InitISOFS, Always, TestOutputInt (
2776       [["wc_c"; "/100kallspaces"]], 102400)],
2777    "count characters in a file",
2778    "\
2779 This command counts the characters in a file, using the
2780 C<wc -c> external command.");
2781
2782   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2783    [InitISOFS, Always, TestOutputList (
2784       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2785    "return first 10 lines of a file",
2786    "\
2787 This command returns up to the first 10 lines of a file as
2788 a list of strings.");
2789
2790   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2791    [InitISOFS, Always, TestOutputList (
2792       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2793     InitISOFS, Always, TestOutputList (
2794       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2795     InitISOFS, Always, TestOutputList (
2796       [["head_n"; "0"; "/10klines"]], [])],
2797    "return first N lines of a file",
2798    "\
2799 If the parameter C<nrlines> is a positive number, this returns the first
2800 C<nrlines> lines of the file C<path>.
2801
2802 If the parameter C<nrlines> is a negative number, this returns lines
2803 from the file C<path>, excluding the last C<nrlines> lines.
2804
2805 If the parameter C<nrlines> is zero, this returns an empty list.");
2806
2807   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2808    [InitISOFS, Always, TestOutputList (
2809       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2810    "return last 10 lines of a file",
2811    "\
2812 This command returns up to the last 10 lines of a file as
2813 a list of strings.");
2814
2815   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2816    [InitISOFS, Always, TestOutputList (
2817       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2818     InitISOFS, Always, TestOutputList (
2819       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2820     InitISOFS, Always, TestOutputList (
2821       [["tail_n"; "0"; "/10klines"]], [])],
2822    "return last N lines of a file",
2823    "\
2824 If the parameter C<nrlines> is a positive number, this returns the last
2825 C<nrlines> lines of the file C<path>.
2826
2827 If the parameter C<nrlines> is a negative number, this returns lines
2828 from the file C<path>, starting with the C<-nrlines>th line.
2829
2830 If the parameter C<nrlines> is zero, this returns an empty list.");
2831
2832   ("df", (RString "output", []), 125, [],
2833    [], (* XXX Tricky to test because it depends on the exact format
2834         * of the 'df' command and other imponderables.
2835         *)
2836    "report file system disk space usage",
2837    "\
2838 This command runs the C<df> command to report disk space used.
2839
2840 This command is mostly useful for interactive sessions.  It
2841 is I<not> intended that you try to parse the output string.
2842 Use C<statvfs> from programs.");
2843
2844   ("df_h", (RString "output", []), 126, [],
2845    [], (* XXX Tricky to test because it depends on the exact format
2846         * of the 'df' command and other imponderables.
2847         *)
2848    "report file system disk space usage (human readable)",
2849    "\
2850 This command runs the C<df -h> command to report disk space used
2851 in human-readable format.
2852
2853 This command is mostly useful for interactive sessions.  It
2854 is I<not> intended that you try to parse the output string.
2855 Use C<statvfs> from programs.");
2856
2857   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2858    [InitISOFS, Always, TestOutputInt (
2859       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2860    "estimate file space usage",
2861    "\
2862 This command runs the C<du -s> command to estimate file space
2863 usage for C<path>.
2864
2865 C<path> can be a file or a directory.  If C<path> is a directory
2866 then the estimate includes the contents of the directory and all
2867 subdirectories (recursively).
2868
2869 The result is the estimated size in I<kilobytes>
2870 (ie. units of 1024 bytes).");
2871
2872   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2873    [InitISOFS, Always, TestOutputList (
2874       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2875    "list files in an initrd",
2876    "\
2877 This command lists out files contained in an initrd.
2878
2879 The files are listed without any initial C</> character.  The
2880 files are listed in the order they appear (not necessarily
2881 alphabetical).  Directory names are listed as separate items.
2882
2883 Old Linux kernels (2.4 and earlier) used a compressed ext2
2884 filesystem as initrd.  We I<only> support the newer initramfs
2885 format (compressed cpio files).");
2886
2887   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2888    [],
2889    "mount a file using the loop device",
2890    "\
2891 This command lets you mount C<file> (a filesystem image
2892 in a file) on a mount point.  It is entirely equivalent to
2893 the command C<mount -o loop file mountpoint>.");
2894
2895   ("mkswap", (RErr, [Device "device"]), 130, [],
2896    [InitEmpty, Always, TestRun (
2897       [["part_disk"; "/dev/sda"; "mbr"];
2898        ["mkswap"; "/dev/sda1"]])],
2899    "create a swap partition",
2900    "\
2901 Create a swap partition on C<device>.");
2902
2903   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2904    [InitEmpty, Always, TestRun (
2905       [["part_disk"; "/dev/sda"; "mbr"];
2906        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2907    "create a swap partition with a label",
2908    "\
2909 Create a swap partition on C<device> with label C<label>.
2910
2911 Note that you cannot attach a swap label to a block device
2912 (eg. C</dev/sda>), just to a partition.  This appears to be
2913 a limitation of the kernel or swap tools.");
2914
2915   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2916    (let uuid = uuidgen () in
2917     [InitEmpty, Always, TestRun (
2918        [["part_disk"; "/dev/sda"; "mbr"];
2919         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2920    "create a swap partition with an explicit UUID",
2921    "\
2922 Create a swap partition on C<device> with UUID C<uuid>.");
2923
2924   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2925    [InitBasicFS, Always, TestOutputStruct (
2926       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2927        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2928        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2929     InitBasicFS, Always, TestOutputStruct (
2930       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2931        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2932    "make block, character or FIFO devices",
2933    "\
2934 This call creates block or character special devices, or
2935 named pipes (FIFOs).
2936
2937 The C<mode> parameter should be the mode, using the standard
2938 constants.  C<devmajor> and C<devminor> are the
2939 device major and minor numbers, only used when creating block
2940 and character special devices.");
2941
2942   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2943    [InitBasicFS, Always, TestOutputStruct (
2944       [["mkfifo"; "0o777"; "/node"];
2945        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2946    "make FIFO (named pipe)",
2947    "\
2948 This call creates a FIFO (named pipe) called C<path> with
2949 mode C<mode>.  It is just a convenient wrapper around
2950 C<guestfs_mknod>.");
2951
2952   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2953    [InitBasicFS, Always, TestOutputStruct (
2954       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2955        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2956    "make block device node",
2957    "\
2958 This call creates a block device node called C<path> with
2959 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2960 It is just a convenient wrapper around C<guestfs_mknod>.");
2961
2962   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2963    [InitBasicFS, Always, TestOutputStruct (
2964       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2965        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2966    "make char device node",
2967    "\
2968 This call creates a char device node called C<path> with
2969 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2970 It is just a convenient wrapper around C<guestfs_mknod>.");
2971
2972   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2973    [], (* XXX umask is one of those stateful things that we should
2974         * reset between each test.
2975         *)
2976    "set file mode creation mask (umask)",
2977    "\
2978 This function sets the mask used for creating new files and
2979 device nodes to C<mask & 0777>.
2980
2981 Typical umask values would be C<022> which creates new files
2982 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2983 C<002> which creates new files with permissions like
2984 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2985
2986 The default umask is C<022>.  This is important because it
2987 means that directories and device nodes will be created with
2988 C<0644> or C<0755> mode even if you specify C<0777>.
2989
2990 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2991
2992 This call returns the previous umask.");
2993
2994   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2995    [],
2996    "read directories entries",
2997    "\
2998 This returns the list of directory entries in directory C<dir>.
2999
3000 All entries in the directory are returned, including C<.> and
3001 C<..>.  The entries are I<not> sorted, but returned in the same
3002 order as the underlying filesystem.
3003
3004 Also this call returns basic file type information about each
3005 file.  The C<ftyp> field will contain one of the following characters:
3006
3007 =over 4
3008
3009 =item 'b'
3010
3011 Block special
3012
3013 =item 'c'
3014
3015 Char special
3016
3017 =item 'd'
3018
3019 Directory
3020
3021 =item 'f'
3022
3023 FIFO (named pipe)
3024
3025 =item 'l'
3026
3027 Symbolic link
3028
3029 =item 'r'
3030
3031 Regular file
3032
3033 =item 's'
3034
3035 Socket
3036
3037 =item 'u'
3038
3039 Unknown file type
3040
3041 =item '?'
3042
3043 The L<readdir(3)> returned a C<d_type> field with an
3044 unexpected value
3045
3046 =back
3047
3048 This function is primarily intended for use by programs.  To
3049 get a simple list of names, use C<guestfs_ls>.  To get a printable
3050 directory for human consumption, use C<guestfs_ll>.");
3051
3052   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3053    [],
3054    "create partitions on a block device",
3055    "\
3056 This is a simplified interface to the C<guestfs_sfdisk>
3057 command, where partition sizes are specified in megabytes
3058 only (rounded to the nearest cylinder) and you don't need
3059 to specify the cyls, heads and sectors parameters which
3060 were rarely if ever used anyway.
3061
3062 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3063 and C<guestfs_part_disk>");
3064
3065   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3066    [],
3067    "determine file type inside a compressed file",
3068    "\
3069 This command runs C<file> after first decompressing C<path>
3070 using C<method>.
3071
3072 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3073
3074 Since 1.0.63, use C<guestfs_file> instead which can now
3075 process compressed files.");
3076
3077   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3078    [],
3079    "list extended attributes of a file or directory",
3080    "\
3081 This call lists the extended attributes of the file or directory
3082 C<path>.
3083
3084 At the system call level, this is a combination of the
3085 L<listxattr(2)> and L<getxattr(2)> calls.
3086
3087 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3088
3089   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3090    [],
3091    "list extended attributes of a file or directory",
3092    "\
3093 This is the same as C<guestfs_getxattrs>, but if C<path>
3094 is a symbolic link, then it returns the extended attributes
3095 of the link itself.");
3096
3097   ("setxattr", (RErr, [String "xattr";
3098                        String "val"; Int "vallen"; (* will be BufferIn *)
3099                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3100    [],
3101    "set extended attribute of a file or directory",
3102    "\
3103 This call sets the extended attribute named C<xattr>
3104 of the file C<path> to the value C<val> (of length C<vallen>).
3105 The value is arbitrary 8 bit data.
3106
3107 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3108
3109   ("lsetxattr", (RErr, [String "xattr";
3110                         String "val"; Int "vallen"; (* will be BufferIn *)
3111                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3112    [],
3113    "set extended attribute of a file or directory",
3114    "\
3115 This is the same as C<guestfs_setxattr>, but if C<path>
3116 is a symbolic link, then it sets an extended attribute
3117 of the link itself.");
3118
3119   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3120    [],
3121    "remove extended attribute of a file or directory",
3122    "\
3123 This call removes the extended attribute named C<xattr>
3124 of the file C<path>.
3125
3126 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3127
3128   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3129    [],
3130    "remove extended attribute of a file or directory",
3131    "\
3132 This is the same as C<guestfs_removexattr>, but if C<path>
3133 is a symbolic link, then it removes an extended attribute
3134 of the link itself.");
3135
3136   ("mountpoints", (RHashtable "mps", []), 147, [],
3137    [],
3138    "show mountpoints",
3139    "\
3140 This call is similar to C<guestfs_mounts>.  That call returns
3141 a list of devices.  This one returns a hash table (map) of
3142 device name to directory where the device is mounted.");
3143
3144   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3145    (* This is a special case: while you would expect a parameter
3146     * of type "Pathname", that doesn't work, because it implies
3147     * NEED_ROOT in the generated calling code in stubs.c, and
3148     * this function cannot use NEED_ROOT.
3149     *)
3150    [],
3151    "create a mountpoint",
3152    "\
3153 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3154 specialized calls that can be used to create extra mountpoints
3155 before mounting the first filesystem.
3156
3157 These calls are I<only> necessary in some very limited circumstances,
3158 mainly the case where you want to mount a mix of unrelated and/or
3159 read-only filesystems together.
3160
3161 For example, live CDs often contain a \"Russian doll\" nest of
3162 filesystems, an ISO outer layer, with a squashfs image inside, with
3163 an ext2/3 image inside that.  You can unpack this as follows
3164 in guestfish:
3165
3166  add-ro Fedora-11-i686-Live.iso
3167  run
3168  mkmountpoint /cd
3169  mkmountpoint /squash
3170  mkmountpoint /ext3
3171  mount /dev/sda /cd
3172  mount-loop /cd/LiveOS/squashfs.img /squash
3173  mount-loop /squash/LiveOS/ext3fs.img /ext3
3174
3175 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3176
3177   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3178    [],
3179    "remove a mountpoint",
3180    "\
3181 This calls removes a mountpoint that was previously created
3182 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3183 for full details.");
3184
3185   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3186    [InitISOFS, Always, TestOutputBuffer (
3187       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3188    "read a file",
3189    "\
3190 This calls returns the contents of the file C<path> as a
3191 buffer.
3192
3193 Unlike C<guestfs_cat>, this function can correctly
3194 handle files that contain embedded ASCII NUL characters.
3195 However unlike C<guestfs_download>, this function is limited
3196 in the total size of file that can be handled.");
3197
3198   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3199    [InitISOFS, Always, TestOutputList (
3200       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3201     InitISOFS, Always, TestOutputList (
3202       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3203    "return lines matching a pattern",
3204    "\
3205 This calls the external C<grep> program and returns the
3206 matching lines.");
3207
3208   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3209    [InitISOFS, Always, TestOutputList (
3210       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3211    "return lines matching a pattern",
3212    "\
3213 This calls the external C<egrep> program and returns the
3214 matching lines.");
3215
3216   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3217    [InitISOFS, Always, TestOutputList (
3218       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3219    "return lines matching a pattern",
3220    "\
3221 This calls the external C<fgrep> program and returns the
3222 matching lines.");
3223
3224   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3225    [InitISOFS, Always, TestOutputList (
3226       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3227    "return lines matching a pattern",
3228    "\
3229 This calls the external C<grep -i> program and returns the
3230 matching lines.");
3231
3232   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3233    [InitISOFS, Always, TestOutputList (
3234       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3235    "return lines matching a pattern",
3236    "\
3237 This calls the external C<egrep -i> program and returns the
3238 matching lines.");
3239
3240   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3241    [InitISOFS, Always, TestOutputList (
3242       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3243    "return lines matching a pattern",
3244    "\
3245 This calls the external C<fgrep -i> program and returns the
3246 matching lines.");
3247
3248   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3249    [InitISOFS, Always, TestOutputList (
3250       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3251    "return lines matching a pattern",
3252    "\
3253 This calls the external C<zgrep> program and returns the
3254 matching lines.");
3255
3256   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3257    [InitISOFS, Always, TestOutputList (
3258       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3259    "return lines matching a pattern",
3260    "\
3261 This calls the external C<zegrep> program and returns the
3262 matching lines.");
3263
3264   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3265    [InitISOFS, Always, TestOutputList (
3266       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3267    "return lines matching a pattern",
3268    "\
3269 This calls the external C<zfgrep> program and returns the
3270 matching lines.");
3271
3272   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3273    [InitISOFS, Always, TestOutputList (
3274       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3275    "return lines matching a pattern",
3276    "\
3277 This calls the external C<zgrep -i> program and returns the
3278 matching lines.");
3279
3280   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3281    [InitISOFS, Always, TestOutputList (
3282       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3283    "return lines matching a pattern",
3284    "\
3285 This calls the external C<zegrep -i> program and returns the
3286 matching lines.");
3287
3288   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3289    [InitISOFS, Always, TestOutputList (
3290       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3291    "return lines matching a pattern",
3292    "\
3293 This calls the external C<zfgrep -i> program and returns the
3294 matching lines.");
3295
3296   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3297    [InitISOFS, Always, TestOutput (
3298       [["realpath"; "/../directory"]], "/directory")],
3299    "canonicalized absolute pathname",
3300    "\
3301 Return the canonicalized absolute pathname of C<path>.  The
3302 returned path has no C<.>, C<..> or symbolic link path elements.");
3303
3304   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3305    [InitBasicFS, Always, TestOutputStruct (
3306       [["touch"; "/a"];
3307        ["ln"; "/a"; "/b"];
3308        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3309    "create a hard link",
3310    "\
3311 This command creates a hard link using the C<ln> command.");
3312
3313   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3314    [InitBasicFS, Always, TestOutputStruct (
3315       [["touch"; "/a"];
3316        ["touch"; "/b"];
3317        ["ln_f"; "/a"; "/b"];
3318        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3319    "create a hard link",
3320    "\
3321 This command creates a hard link using the C<ln -f> command.
3322 The C<-f> option removes the link (C<linkname>) if it exists already.");
3323
3324   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3325    [InitBasicFS, Always, TestOutputStruct (
3326       [["touch"; "/a"];
3327        ["ln_s"; "a"; "/b"];
3328        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3329    "create a symbolic link",
3330    "\
3331 This command creates a symbolic link using the C<ln -s> command.");
3332
3333   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3334    [InitBasicFS, Always, TestOutput (
3335       [["mkdir_p"; "/a/b"];
3336        ["touch"; "/a/b/c"];
3337        ["ln_sf"; "../d"; "/a/b/c"];
3338        ["readlink"; "/a/b/c"]], "../d")],
3339    "create a symbolic link",
3340    "\
3341 This command creates a symbolic link using the C<ln -sf> command,
3342 The C<-f> option removes the link (C<linkname>) if it exists already.");
3343
3344   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3345    [] (* XXX tested above *),
3346    "read the target of a symbolic link",
3347    "\
3348 This command reads the target of a symbolic link.");
3349
3350   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3351    [InitBasicFS, Always, TestOutputStruct (
3352       [["fallocate"; "/a"; "1000000"];
3353        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3354    "preallocate a file in the guest filesystem",
3355    "\
3356 This command preallocates a file (containing zero bytes) named
3357 C<path> of size C<len> bytes.  If the file exists already, it
3358 is overwritten.
3359
3360 Do not confuse this with the guestfish-specific
3361 C<alloc> command which allocates a file in the host and
3362 attaches it as a device.");
3363
3364   ("swapon_device", (RErr, [Device "device"]), 170, [],
3365    [InitPartition, Always, TestRun (
3366       [["mkswap"; "/dev/sda1"];
3367        ["swapon_device"; "/dev/sda1"];
3368        ["swapoff_device"; "/dev/sda1"]])],
3369    "enable swap on device",
3370    "\
3371 This command enables the libguestfs appliance to use the
3372 swap device or partition named C<device>.  The increased
3373 memory is made available for all commands, for example
3374 those run using C<guestfs_command> or C<guestfs_sh>.
3375
3376 Note that you should not swap to existing guest swap
3377 partitions unless you know what you are doing.  They may
3378 contain hibernation information, or other information that
3379 the guest doesn't want you to trash.  You also risk leaking
3380 information about the host to the guest this way.  Instead,
3381 attach a new host device to the guest and swap on that.");
3382
3383   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3384    [], (* XXX tested by swapon_device *)
3385    "disable swap on device",
3386    "\
3387 This command disables the libguestfs appliance swap
3388 device or partition named C<device>.
3389 See C<guestfs_swapon_device>.");
3390
3391   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3392    [InitBasicFS, Always, TestRun (
3393       [["fallocate"; "/swap"; "8388608"];
3394        ["mkswap_file"; "/swap"];
3395        ["swapon_file"; "/swap"];
3396        ["swapoff_file"; "/swap"]])],
3397    "enable swap on file",
3398    "\
3399 This command enables swap to a file.
3400 See C<guestfs_swapon_device> for other notes.");
3401
3402   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3403    [], (* XXX tested by swapon_file *)
3404    "disable swap on file",
3405    "\
3406 This command disables the libguestfs appliance swap on file.");
3407
3408   ("swapon_label", (RErr, [String "label"]), 174, [],
3409    [InitEmpty, Always, TestRun (
3410       [["part_disk"; "/dev/sdb"; "mbr"];
3411        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3412        ["swapon_label"; "swapit"];
3413        ["swapoff_label"; "swapit"];
3414        ["zero"; "/dev/sdb"];
3415        ["blockdev_rereadpt"; "/dev/sdb"]])],
3416    "enable swap on labeled swap partition",
3417    "\
3418 This command enables swap to a labeled swap partition.
3419 See C<guestfs_swapon_device> for other notes.");
3420
3421   ("swapoff_label", (RErr, [String "label"]), 175, [],
3422    [], (* XXX tested by swapon_label *)
3423    "disable swap on labeled swap partition",
3424    "\
3425 This command disables the libguestfs appliance swap on
3426 labeled swap partition.");
3427
3428   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3429    (let uuid = uuidgen () in
3430     [InitEmpty, Always, TestRun (
3431        [["mkswap_U"; uuid; "/dev/sdb"];
3432         ["swapon_uuid"; uuid];
3433         ["swapoff_uuid"; uuid]])]),
3434    "enable swap on swap partition by UUID",
3435    "\
3436 This command enables swap to a swap partition with the given UUID.
3437 See C<guestfs_swapon_device> for other notes.");
3438
3439   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3440    [], (* XXX tested by swapon_uuid *)
3441    "disable swap on swap partition by UUID",
3442    "\
3443 This command disables the libguestfs appliance swap partition
3444 with the given UUID.");
3445
3446   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3447    [InitBasicFS, Always, TestRun (
3448       [["fallocate"; "/swap"; "8388608"];
3449        ["mkswap_file"; "/swap"]])],
3450    "create a swap file",
3451    "\
3452 Create a swap file.
3453
3454 This command just writes a swap file signature to an existing
3455 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3456
3457   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3458    [InitISOFS, Always, TestRun (
3459       [["inotify_init"; "0"]])],
3460    "create an inotify handle",
3461    "\
3462 This command creates a new inotify handle.
3463 The inotify subsystem can be used to notify events which happen to
3464 objects in the guest filesystem.
3465
3466 C<maxevents> is the maximum number of events which will be
3467 queued up between calls to C<guestfs_inotify_read> or
3468 C<guestfs_inotify_files>.
3469 If this is passed as C<0>, then the kernel (or previously set)
3470 default is used.  For Linux 2.6.29 the default was 16384 events.
3471 Beyond this limit, the kernel throws away events, but records
3472 the fact that it threw them away by setting a flag
3473 C<IN_Q_OVERFLOW> in the returned structure list (see
3474 C<guestfs_inotify_read>).
3475
3476 Before any events are generated, you have to add some
3477 watches to the internal watch list.  See:
3478 C<guestfs_inotify_add_watch>,
3479 C<guestfs_inotify_rm_watch> and
3480 C<guestfs_inotify_watch_all>.
3481
3482 Queued up events should be read periodically by calling
3483 C<guestfs_inotify_read>
3484 (or C<guestfs_inotify_files> which is just a helpful
3485 wrapper around C<guestfs_inotify_read>).  If you don't
3486 read the events out often enough then you risk the internal
3487 queue overflowing.
3488
3489 The handle should be closed after use by calling
3490 C<guestfs_inotify_close>.  This also removes any
3491 watches automatically.
3492
3493 See also L<inotify(7)> for an overview of the inotify interface
3494 as exposed by the Linux kernel, which is roughly what we expose
3495 via libguestfs.  Note that there is one global inotify handle
3496 per libguestfs instance.");
3497
3498   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3499    [InitBasicFS, Always, TestOutputList (
3500       [["inotify_init"; "0"];
3501        ["inotify_add_watch"; "/"; "1073741823"];
3502        ["touch"; "/a"];
3503        ["touch"; "/b"];
3504        ["inotify_files"]], ["a"; "b"])],
3505    "add an inotify watch",
3506    "\
3507 Watch C<path> for the events listed in C<mask>.
3508
3509 Note that if C<path> is a directory then events within that
3510 directory are watched, but this does I<not> happen recursively
3511 (in subdirectories).
3512
3513 Note for non-C or non-Linux callers: the inotify events are
3514 defined by the Linux kernel ABI and are listed in
3515 C</usr/include/sys/inotify.h>.");
3516
3517   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3518    [],
3519    "remove an inotify watch",
3520    "\
3521 Remove a previously defined inotify watch.
3522 See C<guestfs_inotify_add_watch>.");
3523
3524   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3525    [],
3526    "return list of inotify events",
3527    "\
3528 Return the complete queue of events that have happened
3529 since the previous read call.
3530
3531 If no events have happened, this returns an empty list.
3532
3533 I<Note>: In order to make sure that all events have been
3534 read, you must call this function repeatedly until it
3535 returns an empty list.  The reason is that the call will
3536 read events up to the maximum appliance-to-host message
3537 size and leave remaining events in the queue.");
3538
3539   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3540    [],
3541    "return list of watched files that had events",
3542    "\
3543 This function is a helpful wrapper around C<guestfs_inotify_read>
3544 which just returns a list of pathnames of objects that were
3545 touched.  The returned pathnames are sorted and deduplicated.");
3546
3547   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3548    [],
3549    "close the inotify handle",
3550    "\
3551 This closes the inotify handle which was previously
3552 opened by inotify_init.  It removes all watches, throws
3553 away any pending events, and deallocates all resources.");
3554
3555   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3556    [],
3557    "set SELinux security context",
3558    "\
3559 This sets the SELinux security context of the daemon
3560 to the string C<context>.
3561
3562 See the documentation about SELINUX in L<guestfs(3)>.");
3563
3564   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3565    [],
3566    "get SELinux security context",
3567    "\
3568 This gets the SELinux security context of the daemon.
3569
3570 See the documentation about SELINUX in L<guestfs(3)>,
3571 and C<guestfs_setcon>");
3572
3573   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3574    [InitEmpty, Always, TestOutput (
3575       [["part_disk"; "/dev/sda"; "mbr"];
3576        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3577        ["mount_options"; ""; "/dev/sda1"; "/"];
3578        ["write_file"; "/new"; "new file contents"; "0"];
3579        ["cat"; "/new"]], "new file contents")],
3580    "make a filesystem with block size",
3581    "\
3582 This call is similar to C<guestfs_mkfs>, but it allows you to
3583 control the block size of the resulting filesystem.  Supported
3584 block sizes depend on the filesystem type, but typically they
3585 are C<1024>, C<2048> or C<4096> only.");
3586
3587   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3588    [InitEmpty, Always, TestOutput (
3589       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3590        ["mke2journal"; "4096"; "/dev/sda1"];
3591        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3592        ["mount_options"; ""; "/dev/sda2"; "/"];
3593        ["write_file"; "/new"; "new file contents"; "0"];
3594        ["cat"; "/new"]], "new file contents")],
3595    "make ext2/3/4 external journal",
3596    "\
3597 This creates an ext2 external journal on C<device>.  It is equivalent
3598 to the command:
3599
3600  mke2fs -O journal_dev -b blocksize device");
3601
3602   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3603    [InitEmpty, Always, TestOutput (
3604       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3605        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3606        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3607        ["mount_options"; ""; "/dev/sda2"; "/"];
3608        ["write_file"; "/new"; "new file contents"; "0"];
3609        ["cat"; "/new"]], "new file contents")],
3610    "make ext2/3/4 external journal with label",
3611    "\
3612 This creates an ext2 external journal on C<device> with label C<label>.");
3613
3614   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3615    (let uuid = uuidgen () in
3616     [InitEmpty, Always, TestOutput (
3617        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3618         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3619         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3620         ["mount_options"; ""; "/dev/sda2"; "/"];
3621         ["write_file"; "/new"; "new file contents"; "0"];
3622         ["cat"; "/new"]], "new file contents")]),
3623    "make ext2/3/4 external journal with UUID",
3624    "\
3625 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3626
3627   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3628    [],
3629    "make ext2/3/4 filesystem with external journal",
3630    "\
3631 This creates an ext2/3/4 filesystem on C<device> with
3632 an external journal on C<journal>.  It is equivalent
3633 to the command:
3634
3635  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3636
3637 See also C<guestfs_mke2journal>.");
3638
3639   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3640    [],
3641    "make ext2/3/4 filesystem with external journal",
3642    "\
3643 This creates an ext2/3/4 filesystem on C<device> with
3644 an external journal on the journal labeled C<label>.
3645
3646 See also C<guestfs_mke2journal_L>.");
3647
3648   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3649    [],
3650    "make ext2/3/4 filesystem with external journal",
3651    "\
3652 This creates an ext2/3/4 filesystem on C<device> with
3653 an external journal on the journal with UUID C<uuid>.
3654
3655 See also C<guestfs_mke2journal_U>.");
3656
3657   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3658    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3659    "load a kernel module",
3660    "\
3661 This loads a kernel module in the appliance.
3662
3663 The kernel module must have been whitelisted when libguestfs
3664 was built (see C<appliance/kmod.whitelist.in> in the source).");
3665
3666   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3667    [InitNone, Always, TestOutput (
3668       [["echo_daemon"; "This is a test"]], "This is a test"
3669     )],
3670    "echo arguments back to the client",
3671    "\
3672 This command concatenate the list of C<words> passed with single spaces between
3673 them and returns the resulting string.
3674
3675 You can use this command to test the connection through to the daemon.
3676
3677 See also C<guestfs_ping_daemon>.");
3678
3679   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3680    [], (* There is a regression test for this. *)
3681    "find all files and directories, returning NUL-separated list",
3682    "\
3683 This command lists out all files and directories, recursively,
3684 starting at C<directory>, placing the resulting list in the
3685 external file called C<files>.
3686
3687 This command works the same way as C<guestfs_find> with the
3688 following exceptions:
3689
3690 =over 4
3691
3692 =item *
3693
3694 The resulting list is written to an external file.
3695
3696 =item *
3697
3698 Items (filenames) in the result are separated
3699 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3700
3701 =item *
3702
3703 This command is not limited in the number of names that it
3704 can return.
3705
3706 =item *
3707
3708 The result list is not sorted.
3709
3710 =back");
3711
3712   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3713    [InitISOFS, Always, TestOutput (
3714       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3715     InitISOFS, Always, TestOutput (
3716       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3717     InitISOFS, Always, TestOutput (
3718       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3719     InitISOFS, Always, TestLastFail (
3720       [["case_sensitive_path"; "/Known-1/"]]);
3721     InitBasicFS, Always, TestOutput (
3722       [["mkdir"; "/a"];
3723        ["mkdir"; "/a/bbb"];
3724        ["touch"; "/a/bbb/c"];
3725        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3726     InitBasicFS, Always, TestOutput (
3727       [["mkdir"; "/a"];
3728        ["mkdir"; "/a/bbb"];
3729        ["touch"; "/a/bbb/c"];
3730        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3731     InitBasicFS, Always, TestLastFail (
3732       [["mkdir"; "/a"];
3733        ["mkdir"; "/a/bbb"];
3734        ["touch"; "/a/bbb/c"];
3735        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3736    "return true path on case-insensitive filesystem",
3737    "\
3738 This can be used to resolve case insensitive paths on
3739 a filesystem which is case sensitive.  The use case is
3740 to resolve paths which you have read from Windows configuration
3741 files or the Windows Registry, to the true path.
3742
3743 The command handles a peculiarity of the Linux ntfs-3g
3744 filesystem driver (and probably others), which is that although
3745 the underlying filesystem is case-insensitive, the driver
3746 exports the filesystem to Linux as case-sensitive.
3747
3748 One consequence of this is that special directories such
3749 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3750 (or other things) depending on the precise details of how
3751 they were created.  In Windows itself this would not be
3752 a problem.
3753
3754 Bug or feature?  You decide:
3755 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3756
3757 This function resolves the true case of each element in the
3758 path and returns the case-sensitive path.
3759
3760 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3761 might return C<\"/WINDOWS/system32\"> (the exact return value
3762 would depend on details of how the directories were originally
3763 created under Windows).
3764
3765 I<Note>:
3766 This function does not handle drive names, backslashes etc.
3767
3768 See also C<guestfs_realpath>.");
3769
3770   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3771    [InitBasicFS, Always, TestOutput (
3772       [["vfs_type"; "/dev/sda1"]], "ext2")],
3773    "get the Linux VFS type corresponding to a mounted device",
3774    "\
3775 This command gets the block device type corresponding to
3776 a mounted device called C<device>.
3777
3778 Usually the result is the name of the Linux VFS module that
3779 is used to mount this device (probably determined automatically
3780 if you used the C<guestfs_mount> call).");
3781
3782   ("truncate", (RErr, [Pathname "path"]), 199, [],
3783    [InitBasicFS, Always, TestOutputStruct (
3784       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3785        ["truncate"; "/test"];
3786        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3787    "truncate a file to zero size",
3788    "\
3789 This command truncates C<path> to a zero-length file.  The
3790 file must exist already.");
3791
3792   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3793    [InitBasicFS, Always, TestOutputStruct (
3794       [["touch"; "/test"];
3795        ["truncate_size"; "/test"; "1000"];
3796        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3797    "truncate a file to a particular size",
3798    "\
3799 This command truncates C<path> to size C<size> bytes.  The file
3800 must exist already.  If the file is smaller than C<size> then
3801 the file is extended to the required size with null bytes.");
3802
3803   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3804    [InitBasicFS, Always, TestOutputStruct (
3805       [["touch"; "/test"];
3806        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3807        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3808    "set timestamp of a file with nanosecond precision",
3809    "\
3810 This command sets the timestamps of a file with nanosecond
3811 precision.
3812
3813 C<atsecs, atnsecs> are the last access time (atime) in secs and
3814 nanoseconds from the epoch.
3815
3816 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3817 secs and nanoseconds from the epoch.
3818
3819 If the C<*nsecs> field contains the special value C<-1> then
3820 the corresponding timestamp is set to the current time.  (The
3821 C<*secs> field is ignored in this case).
3822
3823 If the C<*nsecs> field contains the special value C<-2> then
3824 the corresponding timestamp is left unchanged.  (The
3825 C<*secs> field is ignored in this case).");
3826
3827   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3828    [InitBasicFS, Always, TestOutputStruct (
3829       [["mkdir_mode"; "/test"; "0o111"];
3830        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3831    "create a directory with a particular mode",
3832    "\
3833 This command creates a directory, setting the initial permissions
3834 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3835
3836   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3837    [], (* XXX *)
3838    "change file owner and group",
3839    "\
3840 Change the file owner to C<owner> and group to C<group>.
3841 This is like C<guestfs_chown> but if C<path> is a symlink then
3842 the link itself is changed, not the target.
3843
3844 Only numeric uid and gid are supported.  If you want to use
3845 names, you will need to locate and parse the password file
3846 yourself (Augeas support makes this relatively easy).");
3847
3848   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3849    [], (* XXX *)
3850    "lstat on multiple files",
3851    "\
3852 This call allows you to perform the C<guestfs_lstat> operation
3853 on multiple files, where all files are in the directory C<path>.
3854 C<names> is the list of files from this directory.
3855
3856 On return you get a list of stat structs, with a one-to-one
3857 correspondence to the C<names> list.  If any name did not exist
3858 or could not be lstat'd, then the C<ino> field of that structure
3859 is set to C<-1>.
3860
3861 This call is intended for programs that want to efficiently
3862 list a directory contents without making many round-trips.
3863 See also C<guestfs_lxattrlist> for a similarly efficient call
3864 for getting extended attributes.  Very long directory listings
3865 might cause the protocol message size to be exceeded, causing
3866 this call to fail.  The caller must split up such requests
3867 into smaller groups of names.");
3868
3869   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3870    [], (* XXX *)
3871    "lgetxattr on multiple files",
3872    "\
3873 This call allows you to get the extended attributes
3874 of multiple files, where all files are in the directory C<path>.
3875 C<names> is the list of files from this directory.
3876
3877 On return you get a flat list of xattr structs which must be
3878 interpreted sequentially.  The first xattr struct always has a zero-length
3879 C<attrname>.  C<attrval> in this struct is zero-length
3880 to indicate there was an error doing C<lgetxattr> for this
3881 file, I<or> is a C string which is a decimal number
3882 (the number of following attributes for this file, which could
3883 be C<\"0\">).  Then after the first xattr struct are the
3884 zero or more attributes for the first named file.
3885 This repeats for the second and subsequent files.
3886
3887 This call is intended for programs that want to efficiently
3888 list a directory contents without making many round-trips.
3889 See also C<guestfs_lstatlist> for a similarly efficient call
3890 for getting standard stats.  Very long directory listings
3891 might cause the protocol message size to be exceeded, causing
3892 this call to fail.  The caller must split up such requests
3893 into smaller groups of names.");
3894
3895   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3896    [], (* XXX *)
3897    "readlink on multiple files",
3898    "\
3899 This call allows you to do a C<readlink> operation
3900 on multiple files, where all files are in the directory C<path>.
3901 C<names> is the list of files from this directory.
3902
3903 On return you get a list of strings, with a one-to-one
3904 correspondence to the C<names> list.  Each string is the
3905 value of the symbol link.
3906
3907 If the C<readlink(2)> operation fails on any name, then
3908 the corresponding result string is the empty string C<\"\">.
3909 However the whole operation is completed even if there
3910 were C<readlink(2)> errors, and so you can call this
3911 function with names where you don't know if they are
3912 symbolic links already (albeit slightly less efficient).
3913
3914 This call is intended for programs that want to efficiently
3915 list a directory contents without making many round-trips.
3916 Very long directory listings might cause the protocol
3917 message size to be exceeded, causing
3918 this call to fail.  The caller must split up such requests
3919 into smaller groups of names.");
3920
3921   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3922    [InitISOFS, Always, TestOutputBuffer (
3923       [["pread"; "/known-4"; "1"; "3"]], "\n");
3924     InitISOFS, Always, TestOutputBuffer (
3925       [["pread"; "/empty"; "0"; "100"]], "")],
3926    "read part of a file",
3927    "\
3928 This command lets you read part of a file.  It reads C<count>
3929 bytes of the file, starting at C<offset>, from file C<path>.
3930
3931 This may read fewer bytes than requested.  For further details
3932 see the L<pread(2)> system call.");
3933
3934   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3935    [InitEmpty, Always, TestRun (
3936       [["part_init"; "/dev/sda"; "gpt"]])],
3937    "create an empty partition table",
3938    "\
3939 This creates an empty partition table on C<device> of one of the
3940 partition types listed below.  Usually C<parttype> should be
3941 either C<msdos> or C<gpt> (for large disks).
3942
3943 Initially there are no partitions.  Following this, you should
3944 call C<guestfs_part_add> for each partition required.
3945
3946 Possible values for C<parttype> are:
3947
3948 =over 4
3949
3950 =item B<efi> | B<gpt>
3951
3952 Intel EFI / GPT partition table.
3953
3954 This is recommended for >= 2 TB partitions that will be accessed
3955 from Linux and Intel-based Mac OS X.  It also has limited backwards
3956 compatibility with the C<mbr> format.
3957
3958 =item B<mbr> | B<msdos>
3959
3960 The standard PC \"Master Boot Record\" (MBR) format used
3961 by MS-DOS and Windows.  This partition type will B<only> work
3962 for device sizes up to 2 TB.  For large disks we recommend
3963 using C<gpt>.
3964
3965 =back
3966
3967 Other partition table types that may work but are not
3968 supported include:
3969
3970 =over 4
3971
3972 =item B<aix>
3973
3974 AIX disk labels.
3975
3976 =item B<amiga> | B<rdb>
3977
3978 Amiga \"Rigid Disk Block\" format.
3979
3980 =item B<bsd>
3981
3982 BSD disk labels.
3983
3984 =item B<dasd>
3985
3986 DASD, used on IBM mainframes.
3987
3988 =item B<dvh>
3989
3990 MIPS/SGI volumes.
3991
3992 =item B<mac>
3993
3994 Old Mac partition format.  Modern Macs use C<gpt>.
3995
3996 =item B<pc98>
3997
3998 NEC PC-98 format, common in Japan apparently.
3999
4000 =item B<sun>
4001
4002 Sun disk labels.
4003
4004 =back");
4005
4006   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4007    [InitEmpty, Always, TestRun (
4008       [["part_init"; "/dev/sda"; "mbr"];
4009        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4010     InitEmpty, Always, TestRun (
4011       [["part_init"; "/dev/sda"; "gpt"];
4012        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4013        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4014     InitEmpty, Always, TestRun (
4015       [["part_init"; "/dev/sda"; "mbr"];
4016        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4017        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4018        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4019        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4020    "add a partition to the device",
4021    "\
4022 This command adds a partition to C<device>.  If there is no partition
4023 table on the device, call C<guestfs_part_init> first.
4024
4025 The C<prlogex> parameter is the type of partition.  Normally you
4026 should pass C<p> or C<primary> here, but MBR partition tables also
4027 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4028 types.
4029
4030 C<startsect> and C<endsect> are the start and end of the partition
4031 in I<sectors>.  C<endsect> may be negative, which means it counts
4032 backwards from the end of the disk (C<-1> is the last sector).
4033
4034 Creating a partition which covers the whole disk is not so easy.
4035 Use C<guestfs_part_disk> to do that.");
4036
4037   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4038    [InitEmpty, Always, TestRun (
4039       [["part_disk"; "/dev/sda"; "mbr"]]);
4040     InitEmpty, Always, TestRun (
4041       [["part_disk"; "/dev/sda"; "gpt"]])],
4042    "partition whole disk with a single primary partition",
4043    "\
4044 This command is simply a combination of C<guestfs_part_init>
4045 followed by C<guestfs_part_add> to create a single primary partition
4046 covering the whole disk.
4047
4048 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4049 but other possible values are described in C<guestfs_part_init>.");
4050
4051   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4052    [InitEmpty, Always, TestRun (
4053       [["part_disk"; "/dev/sda"; "mbr"];
4054        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4055    "make a partition bootable",
4056    "\
4057 This sets the bootable flag on partition numbered C<partnum> on
4058 device C<device>.  Note that partitions are numbered from 1.
4059
4060 The bootable flag is used by some PC BIOSes to determine which
4061 partition to boot from.  It is by no means universally recognized,
4062 and in any case if your operating system installed a boot
4063 sector on the device itself, then that takes precedence.");
4064
4065   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4066    [InitEmpty, Always, TestRun (
4067       [["part_disk"; "/dev/sda"; "gpt"];
4068        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4069    "set partition name",
4070    "\
4071 This sets the partition name on partition numbered C<partnum> on
4072 device C<device>.  Note that partitions are numbered from 1.
4073
4074 The partition name can only be set on certain types of partition
4075 table.  This works on C<gpt> but not on C<mbr> partitions.");
4076
4077   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4078    [], (* XXX Add a regression test for this. *)
4079    "list partitions on a device",
4080    "\
4081 This command parses the partition table on C<device> and
4082 returns the list of partitions found.
4083
4084 The fields in the returned structure are:
4085
4086 =over 4
4087
4088 =item B<part_num>
4089
4090 Partition number, counting from 1.
4091
4092 =item B<part_start>
4093
4094 Start of the partition I<in bytes>.  To get sectors you have to
4095 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4096
4097 =item B<part_end>
4098
4099 End of the partition in bytes.
4100
4101 =item B<part_size>
4102
4103 Size of the partition in bytes.
4104
4105 =back");
4106
4107   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4108    [InitEmpty, Always, TestOutput (
4109       [["part_disk"; "/dev/sda"; "gpt"];
4110        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4111    "get the partition table type",
4112    "\
4113 This command examines the partition table on C<device> and
4114 returns the partition table type (format) being used.
4115
4116 Common return values include: C<msdos> (a DOS/Windows style MBR
4117 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4118 values are possible, although unusual.  See C<guestfs_part_init>
4119 for a full list.");
4120
4121   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4122    [InitBasicFS, Always, TestOutputBuffer (
4123       [["fill"; "0x63"; "10"; "/test"];
4124        ["read_file"; "/test"]], "cccccccccc")],
4125    "fill a file with octets",
4126    "\
4127 This command creates a new file called C<path>.  The initial
4128 content of the file is C<len> octets of C<c>, where C<c>
4129 must be a number in the range C<[0..255]>.
4130
4131 To fill a file with zero bytes (sparsely), it is
4132 much more efficient to use C<guestfs_truncate_size>.");
4133
4134   ("available", (RErr, [StringList "groups"]), 216, [],
4135    [InitNone, Always, TestRun [["available"; ""]]],
4136    "test availability of some parts of the API",
4137    "\
4138 This command is used to check the availability of some
4139 groups of functionality in the appliance, which not all builds of
4140 the libguestfs appliance will be able to provide.
4141
4142 The libguestfs groups, and the functions that those
4143 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4144
4145 The argument C<groups> is a list of group names, eg:
4146 C<[\"inotify\", \"augeas\"]> would check for the availability of
4147 the Linux inotify functions and Augeas (configuration file
4148 editing) functions.
4149
4150 The command returns no error if I<all> requested groups are available.
4151
4152 It fails with an error if one or more of the requested
4153 groups is unavailable in the appliance.
4154
4155 If an unknown group name is included in the
4156 list of groups then an error is always returned.
4157
4158 I<Notes:>
4159
4160 =over 4
4161
4162 =item *
4163
4164 You must call C<guestfs_launch> before calling this function.
4165
4166 The reason is because we don't know what groups are
4167 supported by the appliance/daemon until it is running and can
4168 be queried.
4169
4170 =item *
4171
4172 If a group of functions is available, this does not necessarily
4173 mean that they will work.  You still have to check for errors
4174 when calling individual API functions even if they are
4175 available.
4176
4177 =item *
4178
4179 It is usually the job of distro packagers to build
4180 complete functionality into the libguestfs appliance.
4181 Upstream libguestfs, if built from source with all
4182 requirements satisfied, will support everything.
4183
4184 =item *
4185
4186 This call was added in version C<1.0.80>.  In previous
4187 versions of libguestfs all you could do would be to speculatively
4188 execute a command to find out if the daemon implemented it.
4189 See also C<guestfs_version>.
4190
4191 =back");
4192
4193   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4194    [InitBasicFS, Always, TestOutputBuffer (
4195       [["write_file"; "/src"; "hello, world"; "0"];
4196        ["dd"; "/src"; "/dest"];
4197        ["read_file"; "/dest"]], "hello, world")],
4198    "copy from source to destination using dd",
4199    "\
4200 This command copies from one source device or file C<src>
4201 to another destination device or file C<dest>.  Normally you
4202 would use this to copy to or from a device or partition, for
4203 example to duplicate a filesystem.
4204
4205 If the destination is a device, it must be as large or larger
4206 than the source file or device, otherwise the copy will fail.
4207 This command cannot do partial copies.");
4208
4209   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4210    [InitBasicFS, Always, TestOutputInt (
4211       [["write_file"; "/file"; "hello, world"; "0"];
4212        ["filesize"; "/file"]], 12)],
4213    "return the size of the file in bytes",
4214    "\
4215 This command returns the size of C<file> in bytes.
4216
4217 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4218 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4219 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4220
4221   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4222    [InitBasicFSonLVM, Always, TestOutputList (
4223       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4224        ["lvs"]], ["/dev/VG/LV2"])],
4225    "rename an LVM logical volume",
4226    "\
4227 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4228
4229   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4230    [InitBasicFSonLVM, Always, TestOutputList (
4231       [["umount"; "/"];
4232        ["vg_activate"; "false"; "VG"];
4233        ["vgrename"; "VG"; "VG2"];
4234        ["vg_activate"; "true"; "VG2"];
4235        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4236        ["vgs"]], ["VG2"])],
4237    "rename an LVM volume group",
4238    "\
4239 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4240
4241   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [],
4242    [InitISOFS, Always, TestOutputBuffer (
4243       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4244    "list the contents of a single file in an initrd",
4245    "\
4246 This command unpacks the file C<filename> from the initrd file
4247 called C<initrdpath>.  The filename must be given I<without> the
4248 initial C</> character.
4249
4250 For example, in guestfish you could use the following command
4251 to examine the boot script (usually called C</init>)
4252 contained in a Linux initrd or initramfs image:
4253
4254  initrd-cat /boot/initrd-<version>.img init
4255
4256 See also C<guestfs_initrd_list>.");
4257
4258 ]
4259
4260 let all_functions = non_daemon_functions @ daemon_functions
4261
4262 (* In some places we want the functions to be displayed sorted
4263  * alphabetically, so this is useful:
4264  *)
4265 let all_functions_sorted =
4266   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4267                compare n1 n2) all_functions
4268
4269 (* Field types for structures. *)
4270 type field =
4271   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4272   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4273   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4274   | FUInt32
4275   | FInt32
4276   | FUInt64
4277   | FInt64
4278   | FBytes                      (* Any int measure that counts bytes. *)
4279   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4280   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4281
4282 (* Because we generate extra parsing code for LVM command line tools,
4283  * we have to pull out the LVM columns separately here.
4284  *)
4285 let lvm_pv_cols = [
4286   "pv_name", FString;
4287   "pv_uuid", FUUID;
4288   "pv_fmt", FString;
4289   "pv_size", FBytes;
4290   "dev_size", FBytes;
4291   "pv_free", FBytes;
4292   "pv_used", FBytes;
4293   "pv_attr", FString (* XXX *);
4294   "pv_pe_count", FInt64;
4295   "pv_pe_alloc_count", FInt64;
4296   "pv_tags", FString;
4297   "pe_start", FBytes;
4298   "pv_mda_count", FInt64;
4299   "pv_mda_free", FBytes;
4300   (* Not in Fedora 10:
4301      "pv_mda_size", FBytes;
4302   *)
4303 ]
4304 let lvm_vg_cols = [
4305   "vg_name", FString;
4306   "vg_uuid", FUUID;
4307   "vg_fmt", FString;
4308   "vg_attr", FString (* XXX *);
4309   "vg_size", FBytes;
4310   "vg_free", FBytes;
4311   "vg_sysid", FString;
4312   "vg_extent_size", FBytes;
4313   "vg_extent_count", FInt64;
4314   "vg_free_count", FInt64;
4315   "max_lv", FInt64;
4316   "max_pv", FInt64;
4317   "pv_count", FInt64;
4318   "lv_count", FInt64;
4319   "snap_count", FInt64;
4320   "vg_seqno", FInt64;
4321   "vg_tags", FString;
4322   "vg_mda_count", FInt64;
4323   "vg_mda_free", FBytes;
4324   (* Not in Fedora 10:
4325      "vg_mda_size", FBytes;
4326   *)
4327 ]
4328 let lvm_lv_cols = [
4329   "lv_name", FString;
4330   "lv_uuid", FUUID;
4331   "lv_attr", FString (* XXX *);
4332   "lv_major", FInt64;
4333   "lv_minor", FInt64;
4334   "lv_kernel_major", FInt64;
4335   "lv_kernel_minor", FInt64;
4336   "lv_size", FBytes;
4337   "seg_count", FInt64;
4338   "origin", FString;
4339   "snap_percent", FOptPercent;
4340   "copy_percent", FOptPercent;
4341   "move_pv", FString;
4342   "lv_tags", FString;
4343   "mirror_log", FString;
4344   "modules", FString;
4345 ]
4346
4347 (* Names and fields in all structures (in RStruct and RStructList)
4348  * that we support.
4349  *)
4350 let structs = [
4351   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4352    * not use this struct in any new code.
4353    *)
4354   "int_bool", [
4355     "i", FInt32;                (* for historical compatibility *)
4356     "b", FInt32;                (* for historical compatibility *)
4357   ];
4358
4359   (* LVM PVs, VGs, LVs. *)
4360   "lvm_pv", lvm_pv_cols;
4361   "lvm_vg", lvm_vg_cols;
4362   "lvm_lv", lvm_lv_cols;
4363
4364   (* Column names and types from stat structures.
4365    * NB. Can't use things like 'st_atime' because glibc header files
4366    * define some of these as macros.  Ugh.
4367    *)
4368   "stat", [
4369     "dev", FInt64;
4370     "ino", FInt64;
4371     "mode", FInt64;
4372     "nlink", FInt64;
4373     "uid", FInt64;
4374     "gid", FInt64;
4375     "rdev", FInt64;
4376     "size", FInt64;
4377     "blksize", FInt64;
4378     "blocks", FInt64;
4379     "atime", FInt64;
4380     "mtime", FInt64;
4381     "ctime", FInt64;
4382   ];
4383   "statvfs", [
4384     "bsize", FInt64;
4385     "frsize", FInt64;
4386     "blocks", FInt64;
4387     "bfree", FInt64;
4388     "bavail", FInt64;
4389     "files", FInt64;
4390     "ffree", FInt64;
4391     "favail", FInt64;
4392     "fsid", FInt64;
4393     "flag", FInt64;
4394     "namemax", FInt64;
4395   ];
4396
4397   (* Column names in dirent structure. *)
4398   "dirent", [
4399     "ino", FInt64;
4400     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4401     "ftyp", FChar;
4402     "name", FString;
4403   ];
4404
4405   (* Version numbers. *)
4406   "version", [
4407     "major", FInt64;
4408     "minor", FInt64;
4409     "release", FInt64;
4410     "extra", FString;
4411   ];
4412
4413   (* Extended attribute. *)
4414   "xattr", [
4415     "attrname", FString;
4416     "attrval", FBuffer;
4417   ];
4418
4419   (* Inotify events. *)
4420   "inotify_event", [
4421     "in_wd", FInt64;
4422     "in_mask", FUInt32;
4423     "in_cookie", FUInt32;
4424     "in_name", FString;
4425   ];
4426
4427   (* Partition table entry. *)
4428   "partition", [
4429     "part_num", FInt32;
4430     "part_start", FBytes;
4431     "part_end", FBytes;
4432     "part_size", FBytes;
4433   ];
4434 ] (* end of structs *)
4435
4436 (* Ugh, Java has to be different ..
4437  * These names are also used by the Haskell bindings.
4438  *)
4439 let java_structs = [
4440   "int_bool", "IntBool";
4441   "lvm_pv", "PV";
4442   "lvm_vg", "VG";
4443   "lvm_lv", "LV";
4444   "stat", "Stat";
4445   "statvfs", "StatVFS";
4446   "dirent", "Dirent";
4447   "version", "Version";
4448   "xattr", "XAttr";
4449   "inotify_event", "INotifyEvent";
4450   "partition", "Partition";
4451 ]
4452
4453 (* What structs are actually returned. *)
4454 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4455
4456 (* Returns a list of RStruct/RStructList structs that are returned
4457  * by any function.  Each element of returned list is a pair:
4458  *
4459  * (structname, RStructOnly)
4460  *    == there exists function which returns RStruct (_, structname)
4461  * (structname, RStructListOnly)
4462  *    == there exists function which returns RStructList (_, structname)
4463  * (structname, RStructAndList)
4464  *    == there are functions returning both RStruct (_, structname)
4465  *                                      and RStructList (_, structname)
4466  *)
4467 let rstructs_used_by functions =
4468   (* ||| is a "logical OR" for rstructs_used_t *)
4469   let (|||) a b =
4470     match a, b with
4471     | RStructAndList, _
4472     | _, RStructAndList -> RStructAndList
4473     | RStructOnly, RStructListOnly
4474     | RStructListOnly, RStructOnly -> RStructAndList
4475     | RStructOnly, RStructOnly -> RStructOnly
4476     | RStructListOnly, RStructListOnly -> RStructListOnly
4477   in
4478
4479   let h = Hashtbl.create 13 in
4480
4481   (* if elem->oldv exists, update entry using ||| operator,
4482    * else just add elem->newv to the hash
4483    *)
4484   let update elem newv =
4485     try  let oldv = Hashtbl.find h elem in
4486          Hashtbl.replace h elem (newv ||| oldv)
4487     with Not_found -> Hashtbl.add h elem newv
4488   in
4489
4490   List.iter (
4491     fun (_, style, _, _, _, _, _) ->
4492       match fst style with
4493       | RStruct (_, structname) -> update structname RStructOnly
4494       | RStructList (_, structname) -> update structname RStructListOnly
4495       | _ -> ()
4496   ) functions;
4497
4498   (* return key->values as a list of (key,value) *)
4499   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4500
4501 (* Used for testing language bindings. *)
4502 type callt =
4503   | CallString of string
4504   | CallOptString of string option
4505   | CallStringList of string list
4506   | CallInt of int
4507   | CallInt64 of int64
4508   | CallBool of bool
4509
4510 (* Used to memoize the result of pod2text. *)
4511 let pod2text_memo_filename = "src/.pod2text.data"
4512 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4513   try
4514     let chan = open_in pod2text_memo_filename in
4515     let v = input_value chan in
4516     close_in chan;
4517     v
4518   with
4519     _ -> Hashtbl.create 13
4520 let pod2text_memo_updated () =
4521   let chan = open_out pod2text_memo_filename in
4522   output_value chan pod2text_memo;
4523   close_out chan
4524
4525 (* Useful functions.
4526  * Note we don't want to use any external OCaml libraries which
4527  * makes this a bit harder than it should be.
4528  *)
4529 module StringMap = Map.Make (String)
4530
4531 let failwithf fs = ksprintf failwith fs
4532
4533 let unique = let i = ref 0 in fun () -> incr i; !i
4534
4535 let replace_char s c1 c2 =
4536   let s2 = String.copy s in
4537   let r = ref false in
4538   for i = 0 to String.length s2 - 1 do
4539     if String.unsafe_get s2 i = c1 then (
4540       String.unsafe_set s2 i c2;
4541       r := true
4542     )
4543   done;
4544   if not !r then s else s2
4545
4546 let isspace c =
4547   c = ' '
4548   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4549
4550 let triml ?(test = isspace) str =
4551   let i = ref 0 in
4552   let n = ref (String.length str) in
4553   while !n > 0 && test str.[!i]; do
4554     decr n;
4555     incr i
4556   done;
4557   if !i = 0 then str
4558   else String.sub str !i !n
4559
4560 let trimr ?(test = isspace) str =
4561   let n = ref (String.length str) in
4562   while !n > 0 && test str.[!n-1]; do
4563     decr n
4564   done;
4565   if !n = String.length str then str
4566   else String.sub str 0 !n
4567
4568 let trim ?(test = isspace) str =
4569   trimr ~test (triml ~test str)
4570
4571 let rec find s sub =
4572   let len = String.length s in
4573   let sublen = String.length sub in
4574   let rec loop i =
4575     if i <= len-sublen then (
4576       let rec loop2 j =
4577         if j < sublen then (
4578           if s.[i+j] = sub.[j] then loop2 (j+1)
4579           else -1
4580         ) else
4581           i (* found *)
4582       in
4583       let r = loop2 0 in
4584       if r = -1 then loop (i+1) else r
4585     ) else
4586       -1 (* not found *)
4587   in
4588   loop 0
4589
4590 let rec replace_str s s1 s2 =
4591   let len = String.length s in
4592   let sublen = String.length s1 in
4593   let i = find s s1 in
4594   if i = -1 then s
4595   else (
4596     let s' = String.sub s 0 i in
4597     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4598     s' ^ s2 ^ replace_str s'' s1 s2
4599   )
4600
4601 let rec string_split sep str =
4602   let len = String.length str in
4603   let seplen = String.length sep in
4604   let i = find str sep in
4605   if i = -1 then [str]
4606   else (
4607     let s' = String.sub str 0 i in
4608     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4609     s' :: string_split sep s''
4610   )
4611
4612 let files_equal n1 n2 =
4613   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4614   match Sys.command cmd with
4615   | 0 -> true
4616   | 1 -> false
4617   | i -> failwithf "%s: failed with error code %d" cmd i
4618
4619 let rec filter_map f = function
4620   | [] -> []
4621   | x :: xs ->
4622       match f x with
4623       | Some y -> y :: filter_map f xs
4624       | None -> filter_map f xs
4625
4626 let rec find_map f = function
4627   | [] -> raise Not_found
4628   | x :: xs ->
4629       match f x with
4630       | Some y -> y
4631       | None -> find_map f xs
4632
4633 let iteri f xs =
4634   let rec loop i = function
4635     | [] -> ()
4636     | x :: xs -> f i x; loop (i+1) xs
4637   in
4638   loop 0 xs
4639
4640 let mapi f xs =
4641   let rec loop i = function
4642     | [] -> []
4643     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4644   in
4645   loop 0 xs
4646
4647 let count_chars c str =
4648   let count = ref 0 in
4649   for i = 0 to String.length str - 1 do
4650     if c = String.unsafe_get str i then incr count
4651   done;
4652   !count
4653
4654 let name_of_argt = function
4655   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4656   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4657   | FileIn n | FileOut n -> n
4658
4659 let java_name_of_struct typ =
4660   try List.assoc typ java_structs
4661   with Not_found ->
4662     failwithf
4663       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4664
4665 let cols_of_struct typ =
4666   try List.assoc typ structs
4667   with Not_found ->
4668     failwithf "cols_of_struct: unknown struct %s" typ
4669
4670 let seq_of_test = function
4671   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4672   | TestOutputListOfDevices (s, _)
4673   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4674   | TestOutputTrue s | TestOutputFalse s
4675   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4676   | TestOutputStruct (s, _)
4677   | TestLastFail s -> s
4678
4679 (* Handling for function flags. *)
4680 let protocol_limit_warning =
4681   "Because of the message protocol, there is a transfer limit
4682 of somewhere between 2MB and 4MB.  To transfer large files you should use
4683 FTP."
4684
4685 let danger_will_robinson =
4686   "B<This command is dangerous.  Without careful use you
4687 can easily destroy all your data>."
4688
4689 let deprecation_notice flags =
4690   try
4691     let alt =
4692       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4693     let txt =
4694       sprintf "This function is deprecated.
4695 In new code, use the C<%s> call instead.
4696
4697 Deprecated functions will not be removed from the API, but the
4698 fact that they are deprecated indicates that there are problems
4699 with correct use of these functions." alt in
4700     Some txt
4701   with
4702     Not_found -> None
4703
4704 (* Create list of optional groups. *)
4705 let optgroups =
4706   let h = Hashtbl.create 13 in
4707   List.iter (
4708     fun (name, _, _, flags, _, _, _) ->
4709       List.iter (
4710         function
4711         | Optional group ->
4712             let names = try Hashtbl.find h group with Not_found -> [] in
4713             Hashtbl.replace h group (name :: names)
4714         | _ -> ()
4715       ) flags
4716   ) daemon_functions;
4717   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4718   let groups =
4719     List.map (
4720       fun group -> group, List.sort compare (Hashtbl.find h group)
4721     ) groups in
4722   List.sort (fun x y -> compare (fst x) (fst y)) groups
4723
4724 (* Check function names etc. for consistency. *)
4725 let check_functions () =
4726   let contains_uppercase str =
4727     let len = String.length str in
4728     let rec loop i =
4729       if i >= len then false
4730       else (
4731         let c = str.[i] in
4732         if c >= 'A' && c <= 'Z' then true
4733         else loop (i+1)
4734       )
4735     in
4736     loop 0
4737   in
4738
4739   (* Check function names. *)
4740   List.iter (
4741     fun (name, _, _, _, _, _, _) ->
4742       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4743         failwithf "function name %s does not need 'guestfs' prefix" name;
4744       if name = "" then
4745         failwithf "function name is empty";
4746       if name.[0] < 'a' || name.[0] > 'z' then
4747         failwithf "function name %s must start with lowercase a-z" name;
4748       if String.contains name '-' then
4749         failwithf "function name %s should not contain '-', use '_' instead."
4750           name
4751   ) all_functions;
4752
4753   (* Check function parameter/return names. *)
4754   List.iter (
4755     fun (name, style, _, _, _, _, _) ->
4756       let check_arg_ret_name n =
4757         if contains_uppercase n then
4758           failwithf "%s param/ret %s should not contain uppercase chars"
4759             name n;
4760         if String.contains n '-' || String.contains n '_' then
4761           failwithf "%s param/ret %s should not contain '-' or '_'"
4762             name n;
4763         if n = "value" then
4764           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;
4765         if n = "int" || n = "char" || n = "short" || n = "long" then
4766           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4767         if n = "i" || n = "n" then
4768           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4769         if n = "argv" || n = "args" then
4770           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4771
4772         (* List Haskell, OCaml and C keywords here.
4773          * http://www.haskell.org/haskellwiki/Keywords
4774          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4775          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4776          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4777          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4778          * Omitting _-containing words, since they're handled above.
4779          * Omitting the OCaml reserved word, "val", is ok,
4780          * and saves us from renaming several parameters.
4781          *)
4782         let reserved = [
4783           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4784           "char"; "class"; "const"; "constraint"; "continue"; "data";
4785           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4786           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4787           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4788           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4789           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4790           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4791           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4792           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4793           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4794           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4795           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4796           "volatile"; "when"; "where"; "while";
4797           ] in
4798         if List.mem n reserved then
4799           failwithf "%s has param/ret using reserved word %s" name n;
4800       in
4801
4802       (match fst style with
4803        | RErr -> ()
4804        | RInt n | RInt64 n | RBool n
4805        | RConstString n | RConstOptString n | RString n
4806        | RStringList n | RStruct (n, _) | RStructList (n, _)
4807        | RHashtable n | RBufferOut n ->
4808            check_arg_ret_name n
4809       );
4810       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4811   ) all_functions;
4812
4813   (* Check short descriptions. *)
4814   List.iter (
4815     fun (name, _, _, _, _, shortdesc, _) ->
4816       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4817         failwithf "short description of %s should begin with lowercase." name;
4818       let c = shortdesc.[String.length shortdesc-1] in
4819       if c = '\n' || c = '.' then
4820         failwithf "short description of %s should not end with . or \\n." name
4821   ) all_functions;
4822
4823   (* Check long dscriptions. *)
4824   List.iter (
4825     fun (name, _, _, _, _, _, longdesc) ->
4826       if longdesc.[String.length longdesc-1] = '\n' then
4827         failwithf "long description of %s should not end with \\n." name
4828   ) all_functions;
4829
4830   (* Check proc_nrs. *)
4831   List.iter (
4832     fun (name, _, proc_nr, _, _, _, _) ->
4833       if proc_nr <= 0 then
4834         failwithf "daemon function %s should have proc_nr > 0" name
4835   ) daemon_functions;
4836
4837   List.iter (
4838     fun (name, _, proc_nr, _, _, _, _) ->
4839       if proc_nr <> -1 then
4840         failwithf "non-daemon function %s should have proc_nr -1" name
4841   ) non_daemon_functions;
4842
4843   let proc_nrs =
4844     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4845       daemon_functions in
4846   let proc_nrs =
4847     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4848   let rec loop = function
4849     | [] -> ()
4850     | [_] -> ()
4851     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4852         loop rest
4853     | (name1,nr1) :: (name2,nr2) :: _ ->
4854         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4855           name1 name2 nr1 nr2
4856   in
4857   loop proc_nrs;
4858
4859   (* Check tests. *)
4860   List.iter (
4861     function
4862       (* Ignore functions that have no tests.  We generate a
4863        * warning when the user does 'make check' instead.
4864        *)
4865     | name, _, _, _, [], _, _ -> ()
4866     | name, _, _, _, tests, _, _ ->
4867         let funcs =
4868           List.map (
4869             fun (_, _, test) ->
4870               match seq_of_test test with
4871               | [] ->
4872                   failwithf "%s has a test containing an empty sequence" name
4873               | cmds -> List.map List.hd cmds
4874           ) tests in
4875         let funcs = List.flatten funcs in
4876
4877         let tested = List.mem name funcs in
4878
4879         if not tested then
4880           failwithf "function %s has tests but does not test itself" name
4881   ) all_functions
4882
4883 (* 'pr' prints to the current output file. *)
4884 let chan = ref Pervasives.stdout
4885 let lines = ref 0
4886 let pr fs =
4887   ksprintf
4888     (fun str ->
4889        let i = count_chars '\n' str in
4890        lines := !lines + i;
4891        output_string !chan str
4892     ) fs
4893
4894 let copyright_years =
4895   let this_year = 1900 + (localtime (time ())).tm_year in
4896   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4897
4898 (* Generate a header block in a number of standard styles. *)
4899 type comment_style =
4900     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4901 type license = GPLv2plus | LGPLv2plus
4902
4903 let generate_header ?(extra_inputs = []) comment license =
4904   let inputs = "src/generator.ml" :: extra_inputs in
4905   let c = match comment with
4906     | CStyle ->         pr "/* "; " *"
4907     | CPlusPlusStyle -> pr "// "; "//"
4908     | HashStyle ->      pr "# ";  "#"
4909     | OCamlStyle ->     pr "(* "; " *"
4910     | HaskellStyle ->   pr "{- "; "  " in
4911   pr "libguestfs generated file\n";
4912   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4913   List.iter (pr "%s   %s\n" c) inputs;
4914   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4915   pr "%s\n" c;
4916   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4917   pr "%s\n" c;
4918   (match license with
4919    | GPLv2plus ->
4920        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4921        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4922        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4923        pr "%s (at your option) any later version.\n" c;
4924        pr "%s\n" c;
4925        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4926        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4927        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4928        pr "%s GNU General Public License for more details.\n" c;
4929        pr "%s\n" c;
4930        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4931        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4932        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4933
4934    | LGPLv2plus ->
4935        pr "%s This library is free software; you can redistribute it and/or\n" c;
4936        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4937        pr "%s License as published by the Free Software Foundation; either\n" c;
4938        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4939        pr "%s\n" c;
4940        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4941        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4942        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4943        pr "%s Lesser General Public License for more details.\n" c;
4944        pr "%s\n" c;
4945        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4946        pr "%s License along with this library; if not, write to the Free Software\n" c;
4947        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4948   );
4949   (match comment with
4950    | CStyle -> pr " */\n"
4951    | CPlusPlusStyle
4952    | HashStyle -> ()
4953    | OCamlStyle -> pr " *)\n"
4954    | HaskellStyle -> pr "-}\n"
4955   );
4956   pr "\n"
4957
4958 (* Start of main code generation functions below this line. *)
4959
4960 (* Generate the pod documentation for the C API. *)
4961 let rec generate_actions_pod () =
4962   List.iter (
4963     fun (shortname, style, _, flags, _, _, longdesc) ->
4964       if not (List.mem NotInDocs flags) then (
4965         let name = "guestfs_" ^ shortname in
4966         pr "=head2 %s\n\n" name;
4967         pr " ";
4968         generate_prototype ~extern:false ~handle:"handle" name style;
4969         pr "\n\n";
4970         pr "%s\n\n" longdesc;
4971         (match fst style with
4972          | RErr ->
4973              pr "This function returns 0 on success or -1 on error.\n\n"
4974          | RInt _ ->
4975              pr "On error this function returns -1.\n\n"
4976          | RInt64 _ ->
4977              pr "On error this function returns -1.\n\n"
4978          | RBool _ ->
4979              pr "This function returns a C truth value on success or -1 on error.\n\n"
4980          | RConstString _ ->
4981              pr "This function returns a string, or NULL on error.
4982 The string is owned by the guest handle and must I<not> be freed.\n\n"
4983          | RConstOptString _ ->
4984              pr "This function returns a string which may be NULL.
4985 There is way to return an error from this function.
4986 The string is owned by the guest handle and must I<not> be freed.\n\n"
4987          | RString _ ->
4988              pr "This function returns a string, or NULL on error.
4989 I<The caller must free the returned string after use>.\n\n"
4990          | RStringList _ ->
4991              pr "This function returns a NULL-terminated array of strings
4992 (like L<environ(3)>), or NULL if there was an error.
4993 I<The caller must free the strings and the array after use>.\n\n"
4994          | RStruct (_, typ) ->
4995              pr "This function returns a C<struct guestfs_%s *>,
4996 or NULL if there was an error.
4997 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4998          | RStructList (_, typ) ->
4999              pr "This function returns a C<struct guestfs_%s_list *>
5000 (see E<lt>guestfs-structs.hE<gt>),
5001 or NULL if there was an error.
5002 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5003          | RHashtable _ ->
5004              pr "This function returns a NULL-terminated array of
5005 strings, or NULL if there was an error.
5006 The array of strings will always have length C<2n+1>, where
5007 C<n> keys and values alternate, followed by the trailing NULL entry.
5008 I<The caller must free the strings and the array after use>.\n\n"
5009          | RBufferOut _ ->
5010              pr "This function returns a buffer, or NULL on error.
5011 The size of the returned buffer is written to C<*size_r>.
5012 I<The caller must free the returned buffer after use>.\n\n"
5013         );
5014         if List.mem ProtocolLimitWarning flags then
5015           pr "%s\n\n" protocol_limit_warning;
5016         if List.mem DangerWillRobinson flags then
5017           pr "%s\n\n" danger_will_robinson;
5018         match deprecation_notice flags with
5019         | None -> ()
5020         | Some txt -> pr "%s\n\n" txt
5021       )
5022   ) all_functions_sorted
5023
5024 and generate_structs_pod () =
5025   (* Structs documentation. *)
5026   List.iter (
5027     fun (typ, cols) ->
5028       pr "=head2 guestfs_%s\n" typ;
5029       pr "\n";
5030       pr " struct guestfs_%s {\n" typ;
5031       List.iter (
5032         function
5033         | name, FChar -> pr "   char %s;\n" name
5034         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5035         | name, FInt32 -> pr "   int32_t %s;\n" name
5036         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5037         | name, FInt64 -> pr "   int64_t %s;\n" name
5038         | name, FString -> pr "   char *%s;\n" name
5039         | name, FBuffer ->
5040             pr "   /* The next two fields describe a byte array. */\n";
5041             pr "   uint32_t %s_len;\n" name;
5042             pr "   char *%s;\n" name
5043         | name, FUUID ->
5044             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5045             pr "   char %s[32];\n" name
5046         | name, FOptPercent ->
5047             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5048             pr "   float %s;\n" name
5049       ) cols;
5050       pr " };\n";
5051       pr " \n";
5052       pr " struct guestfs_%s_list {\n" typ;
5053       pr "   uint32_t len; /* Number of elements in list. */\n";
5054       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5055       pr " };\n";
5056       pr " \n";
5057       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5058       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5059         typ typ;
5060       pr "\n"
5061   ) structs
5062
5063 and generate_availability_pod () =
5064   (* Availability documentation. *)
5065   pr "=over 4\n";
5066   pr "\n";
5067   List.iter (
5068     fun (group, functions) ->
5069       pr "=item B<%s>\n" group;
5070       pr "\n";
5071       pr "The following functions:\n";
5072       List.iter (pr "L</guestfs_%s>\n") functions;
5073       pr "\n"
5074   ) optgroups;
5075   pr "=back\n";
5076   pr "\n"
5077
5078 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5079  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5080  *
5081  * We have to use an underscore instead of a dash because otherwise
5082  * rpcgen generates incorrect code.
5083  *
5084  * This header is NOT exported to clients, but see also generate_structs_h.
5085  *)
5086 and generate_xdr () =
5087   generate_header CStyle LGPLv2plus;
5088
5089   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5090   pr "typedef string str<>;\n";
5091   pr "\n";
5092
5093   (* Internal structures. *)
5094   List.iter (
5095     function
5096     | typ, cols ->
5097         pr "struct guestfs_int_%s {\n" typ;
5098         List.iter (function
5099                    | name, FChar -> pr "  char %s;\n" name
5100                    | name, FString -> pr "  string %s<>;\n" name
5101                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5102                    | name, FUUID -> pr "  opaque %s[32];\n" name
5103                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5104                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5105                    | name, FOptPercent -> pr "  float %s;\n" name
5106                   ) cols;
5107         pr "};\n";
5108         pr "\n";
5109         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5110         pr "\n";
5111   ) structs;
5112
5113   List.iter (
5114     fun (shortname, style, _, _, _, _, _) ->
5115       let name = "guestfs_" ^ shortname in
5116
5117       (match snd style with
5118        | [] -> ()
5119        | args ->
5120            pr "struct %s_args {\n" name;
5121            List.iter (
5122              function
5123              | Pathname n | Device n | Dev_or_Path n | String n ->
5124                  pr "  string %s<>;\n" n
5125              | OptString n -> pr "  str *%s;\n" n
5126              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5127              | Bool n -> pr "  bool %s;\n" n
5128              | Int n -> pr "  int %s;\n" n
5129              | Int64 n -> pr "  hyper %s;\n" n
5130              | FileIn _ | FileOut _ -> ()
5131            ) args;
5132            pr "};\n\n"
5133       );
5134       (match fst style with
5135        | RErr -> ()
5136        | RInt n ->
5137            pr "struct %s_ret {\n" name;
5138            pr "  int %s;\n" n;
5139            pr "};\n\n"
5140        | RInt64 n ->
5141            pr "struct %s_ret {\n" name;
5142            pr "  hyper %s;\n" n;
5143            pr "};\n\n"
5144        | RBool n ->
5145            pr "struct %s_ret {\n" name;
5146            pr "  bool %s;\n" n;
5147            pr "};\n\n"
5148        | RConstString _ | RConstOptString _ ->
5149            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5150        | RString n ->
5151            pr "struct %s_ret {\n" name;
5152            pr "  string %s<>;\n" n;
5153            pr "};\n\n"
5154        | RStringList n ->
5155            pr "struct %s_ret {\n" name;
5156            pr "  str %s<>;\n" n;
5157            pr "};\n\n"
5158        | RStruct (n, typ) ->
5159            pr "struct %s_ret {\n" name;
5160            pr "  guestfs_int_%s %s;\n" typ n;
5161            pr "};\n\n"
5162        | RStructList (n, typ) ->
5163            pr "struct %s_ret {\n" name;
5164            pr "  guestfs_int_%s_list %s;\n" typ n;
5165            pr "};\n\n"
5166        | RHashtable n ->
5167            pr "struct %s_ret {\n" name;
5168            pr "  str %s<>;\n" n;
5169            pr "};\n\n"
5170        | RBufferOut n ->
5171            pr "struct %s_ret {\n" name;
5172            pr "  opaque %s<>;\n" n;
5173            pr "};\n\n"
5174       );
5175   ) daemon_functions;
5176
5177   (* Table of procedure numbers. *)
5178   pr "enum guestfs_procedure {\n";
5179   List.iter (
5180     fun (shortname, _, proc_nr, _, _, _, _) ->
5181       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5182   ) daemon_functions;
5183   pr "  GUESTFS_PROC_NR_PROCS\n";
5184   pr "};\n";
5185   pr "\n";
5186
5187   (* Having to choose a maximum message size is annoying for several
5188    * reasons (it limits what we can do in the API), but it (a) makes
5189    * the protocol a lot simpler, and (b) provides a bound on the size
5190    * of the daemon which operates in limited memory space.  For large
5191    * file transfers you should use FTP.
5192    *)
5193   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5194   pr "\n";
5195
5196   (* Message header, etc. *)
5197   pr "\
5198 /* The communication protocol is now documented in the guestfs(3)
5199  * manpage.
5200  */
5201
5202 const GUESTFS_PROGRAM = 0x2000F5F5;
5203 const GUESTFS_PROTOCOL_VERSION = 1;
5204
5205 /* These constants must be larger than any possible message length. */
5206 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5207 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5208
5209 enum guestfs_message_direction {
5210   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5211   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5212 };
5213
5214 enum guestfs_message_status {
5215   GUESTFS_STATUS_OK = 0,
5216   GUESTFS_STATUS_ERROR = 1
5217 };
5218
5219 const GUESTFS_ERROR_LEN = 256;
5220
5221 struct guestfs_message_error {
5222   string error_message<GUESTFS_ERROR_LEN>;
5223 };
5224
5225 struct guestfs_message_header {
5226   unsigned prog;                     /* GUESTFS_PROGRAM */
5227   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5228   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5229   guestfs_message_direction direction;
5230   unsigned serial;                   /* message serial number */
5231   guestfs_message_status status;
5232 };
5233
5234 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5235
5236 struct guestfs_chunk {
5237   int cancel;                        /* if non-zero, transfer is cancelled */
5238   /* data size is 0 bytes if the transfer has finished successfully */
5239   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5240 };
5241 "
5242
5243 (* Generate the guestfs-structs.h file. *)
5244 and generate_structs_h () =
5245   generate_header CStyle LGPLv2plus;
5246
5247   (* This is a public exported header file containing various
5248    * structures.  The structures are carefully written to have
5249    * exactly the same in-memory format as the XDR structures that
5250    * we use on the wire to the daemon.  The reason for creating
5251    * copies of these structures here is just so we don't have to
5252    * export the whole of guestfs_protocol.h (which includes much
5253    * unrelated and XDR-dependent stuff that we don't want to be
5254    * public, or required by clients).
5255    *
5256    * To reiterate, we will pass these structures to and from the
5257    * client with a simple assignment or memcpy, so the format
5258    * must be identical to what rpcgen / the RFC defines.
5259    *)
5260
5261   (* Public structures. *)
5262   List.iter (
5263     fun (typ, cols) ->
5264       pr "struct guestfs_%s {\n" typ;
5265       List.iter (
5266         function
5267         | name, FChar -> pr "  char %s;\n" name
5268         | name, FString -> pr "  char *%s;\n" name
5269         | name, FBuffer ->
5270             pr "  uint32_t %s_len;\n" name;
5271             pr "  char *%s;\n" name
5272         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5273         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5274         | name, FInt32 -> pr "  int32_t %s;\n" name
5275         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5276         | name, FInt64 -> pr "  int64_t %s;\n" name
5277         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5278       ) cols;
5279       pr "};\n";
5280       pr "\n";
5281       pr "struct guestfs_%s_list {\n" typ;
5282       pr "  uint32_t len;\n";
5283       pr "  struct guestfs_%s *val;\n" typ;
5284       pr "};\n";
5285       pr "\n";
5286       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5287       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5288       pr "\n"
5289   ) structs
5290
5291 (* Generate the guestfs-actions.h file. *)
5292 and generate_actions_h () =
5293   generate_header CStyle LGPLv2plus;
5294   List.iter (
5295     fun (shortname, style, _, _, _, _, _) ->
5296       let name = "guestfs_" ^ shortname in
5297       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5298         name style
5299   ) all_functions
5300
5301 (* Generate the guestfs-internal-actions.h file. *)
5302 and generate_internal_actions_h () =
5303   generate_header CStyle LGPLv2plus;
5304   List.iter (
5305     fun (shortname, style, _, _, _, _, _) ->
5306       let name = "guestfs__" ^ shortname in
5307       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5308         name style
5309   ) non_daemon_functions
5310
5311 (* Generate the client-side dispatch stubs. *)
5312 and generate_client_actions () =
5313   generate_header CStyle LGPLv2plus;
5314
5315   pr "\
5316 #include <stdio.h>
5317 #include <stdlib.h>
5318 #include <stdint.h>
5319 #include <inttypes.h>
5320
5321 #include \"guestfs.h\"
5322 #include \"guestfs-internal.h\"
5323 #include \"guestfs-internal-actions.h\"
5324 #include \"guestfs_protocol.h\"
5325
5326 #define error guestfs_error
5327 //#define perrorf guestfs_perrorf
5328 #define safe_malloc guestfs_safe_malloc
5329 #define safe_realloc guestfs_safe_realloc
5330 //#define safe_strdup guestfs_safe_strdup
5331 #define safe_memdup guestfs_safe_memdup
5332
5333 /* Check the return message from a call for validity. */
5334 static int
5335 check_reply_header (guestfs_h *g,
5336                     const struct guestfs_message_header *hdr,
5337                     unsigned int proc_nr, unsigned int serial)
5338 {
5339   if (hdr->prog != GUESTFS_PROGRAM) {
5340     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5341     return -1;
5342   }
5343   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5344     error (g, \"wrong protocol version (%%d/%%d)\",
5345            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5346     return -1;
5347   }
5348   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5349     error (g, \"unexpected message direction (%%d/%%d)\",
5350            hdr->direction, GUESTFS_DIRECTION_REPLY);
5351     return -1;
5352   }
5353   if (hdr->proc != proc_nr) {
5354     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5355     return -1;
5356   }
5357   if (hdr->serial != serial) {
5358     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5359     return -1;
5360   }
5361
5362   return 0;
5363 }
5364
5365 /* Check we are in the right state to run a high-level action. */
5366 static int
5367 check_state (guestfs_h *g, const char *caller)
5368 {
5369   if (!guestfs__is_ready (g)) {
5370     if (guestfs__is_config (g) || guestfs__is_launching (g))
5371       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5372         caller);
5373     else
5374       error (g, \"%%s called from the wrong state, %%d != READY\",
5375         caller, guestfs__get_state (g));
5376     return -1;
5377   }
5378   return 0;
5379 }
5380
5381 ";
5382
5383   (* Generate code to generate guestfish call traces. *)
5384   let trace_call shortname style =
5385     pr "  if (guestfs__get_trace (g)) {\n";
5386
5387     let needs_i =
5388       List.exists (function
5389                    | StringList _ | DeviceList _ -> true
5390                    | _ -> false) (snd style) in
5391     if needs_i then (
5392       pr "    int i;\n";
5393       pr "\n"
5394     );
5395
5396     pr "    printf (\"%s\");\n" shortname;
5397     List.iter (
5398       function
5399       | String n                        (* strings *)
5400       | Device n
5401       | Pathname n
5402       | Dev_or_Path n
5403       | FileIn n
5404       | FileOut n ->
5405           (* guestfish doesn't support string escaping, so neither do we *)
5406           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5407       | OptString n ->                  (* string option *)
5408           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5409           pr "    else printf (\" null\");\n"
5410       | StringList n
5411       | DeviceList n ->                 (* string list *)
5412           pr "    putchar (' ');\n";
5413           pr "    putchar ('\"');\n";
5414           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5415           pr "      if (i > 0) putchar (' ');\n";
5416           pr "      fputs (%s[i], stdout);\n" n;
5417           pr "    }\n";
5418           pr "    putchar ('\"');\n";
5419       | Bool n ->                       (* boolean *)
5420           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5421       | Int n ->                        (* int *)
5422           pr "    printf (\" %%d\", %s);\n" n
5423       | Int64 n ->
5424           pr "    printf (\" %%\" PRIi64, %s);\n" n
5425     ) (snd style);
5426     pr "    putchar ('\\n');\n";
5427     pr "  }\n";
5428     pr "\n";
5429   in
5430
5431   (* For non-daemon functions, generate a wrapper around each function. *)
5432   List.iter (
5433     fun (shortname, style, _, _, _, _, _) ->
5434       let name = "guestfs_" ^ shortname in
5435
5436       generate_prototype ~extern:false ~semicolon:false ~newline:true
5437         ~handle:"g" name style;
5438       pr "{\n";
5439       trace_call shortname style;
5440       pr "  return guestfs__%s " shortname;
5441       generate_c_call_args ~handle:"g" style;
5442       pr ";\n";
5443       pr "}\n";
5444       pr "\n"
5445   ) non_daemon_functions;
5446
5447   (* Client-side stubs for each function. *)
5448   List.iter (
5449     fun (shortname, style, _, _, _, _, _) ->
5450       let name = "guestfs_" ^ shortname in
5451
5452       (* Generate the action stub. *)
5453       generate_prototype ~extern:false ~semicolon:false ~newline:true
5454         ~handle:"g" name style;
5455
5456       let error_code =
5457         match fst style with
5458         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5459         | RConstString _ | RConstOptString _ ->
5460             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5461         | RString _ | RStringList _
5462         | RStruct _ | RStructList _
5463         | RHashtable _ | RBufferOut _ ->
5464             "NULL" in
5465
5466       pr "{\n";
5467
5468       (match snd style with
5469        | [] -> ()
5470        | _ -> pr "  struct %s_args args;\n" name
5471       );
5472
5473       pr "  guestfs_message_header hdr;\n";
5474       pr "  guestfs_message_error err;\n";
5475       let has_ret =
5476         match fst style with
5477         | RErr -> false
5478         | RConstString _ | RConstOptString _ ->
5479             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5480         | RInt _ | RInt64 _
5481         | RBool _ | RString _ | RStringList _
5482         | RStruct _ | RStructList _
5483         | RHashtable _ | RBufferOut _ ->
5484             pr "  struct %s_ret ret;\n" name;
5485             true in
5486
5487       pr "  int serial;\n";
5488       pr "  int r;\n";
5489       pr "\n";
5490       trace_call shortname style;
5491       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5492       pr "  guestfs___set_busy (g);\n";
5493       pr "\n";
5494
5495       (* Send the main header and arguments. *)
5496       (match snd style with
5497        | [] ->
5498            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5499              (String.uppercase shortname)
5500        | args ->
5501            List.iter (
5502              function
5503              | Pathname n | Device n | Dev_or_Path n | String n ->
5504                  pr "  args.%s = (char *) %s;\n" n n
5505              | OptString n ->
5506                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5507              | StringList n | DeviceList n ->
5508                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5509                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5510              | Bool n ->
5511                  pr "  args.%s = %s;\n" n n
5512              | Int n ->
5513                  pr "  args.%s = %s;\n" n n
5514              | Int64 n ->
5515                  pr "  args.%s = %s;\n" n n
5516              | FileIn _ | FileOut _ -> ()
5517            ) args;
5518            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5519              (String.uppercase shortname);
5520            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5521              name;
5522       );
5523       pr "  if (serial == -1) {\n";
5524       pr "    guestfs___end_busy (g);\n";
5525       pr "    return %s;\n" error_code;
5526       pr "  }\n";
5527       pr "\n";
5528
5529       (* Send any additional files (FileIn) requested. *)
5530       let need_read_reply_label = ref false in
5531       List.iter (
5532         function
5533         | FileIn n ->
5534             pr "  r = guestfs___send_file (g, %s);\n" n;
5535             pr "  if (r == -1) {\n";
5536             pr "    guestfs___end_busy (g);\n";
5537             pr "    return %s;\n" error_code;
5538             pr "  }\n";
5539             pr "  if (r == -2) /* daemon cancelled */\n";
5540             pr "    goto read_reply;\n";
5541             need_read_reply_label := true;
5542             pr "\n";
5543         | _ -> ()
5544       ) (snd style);
5545
5546       (* Wait for the reply from the remote end. *)
5547       if !need_read_reply_label then pr " read_reply:\n";
5548       pr "  memset (&hdr, 0, sizeof hdr);\n";
5549       pr "  memset (&err, 0, sizeof err);\n";
5550       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5551       pr "\n";
5552       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5553       if not has_ret then
5554         pr "NULL, NULL"
5555       else
5556         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5557       pr ");\n";
5558
5559       pr "  if (r == -1) {\n";
5560       pr "    guestfs___end_busy (g);\n";
5561       pr "    return %s;\n" error_code;
5562       pr "  }\n";
5563       pr "\n";
5564
5565       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5566         (String.uppercase shortname);
5567       pr "    guestfs___end_busy (g);\n";
5568       pr "    return %s;\n" error_code;
5569       pr "  }\n";
5570       pr "\n";
5571
5572       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5573       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5574       pr "    free (err.error_message);\n";
5575       pr "    guestfs___end_busy (g);\n";
5576       pr "    return %s;\n" error_code;
5577       pr "  }\n";
5578       pr "\n";
5579
5580       (* Expecting to receive further files (FileOut)? *)
5581       List.iter (
5582         function
5583         | FileOut n ->
5584             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5585             pr "    guestfs___end_busy (g);\n";
5586             pr "    return %s;\n" error_code;
5587             pr "  }\n";
5588             pr "\n";
5589         | _ -> ()
5590       ) (snd style);
5591
5592       pr "  guestfs___end_busy (g);\n";
5593
5594       (match fst style with
5595        | RErr -> pr "  return 0;\n"
5596        | RInt n | RInt64 n | RBool n ->
5597            pr "  return ret.%s;\n" n
5598        | RConstString _ | RConstOptString _ ->
5599            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5600        | RString n ->
5601            pr "  return ret.%s; /* caller will free */\n" n
5602        | RStringList n | RHashtable n ->
5603            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5604            pr "  ret.%s.%s_val =\n" n n;
5605            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5606            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5607              n n;
5608            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5609            pr "  return ret.%s.%s_val;\n" n n
5610        | RStruct (n, _) ->
5611            pr "  /* caller will free this */\n";
5612            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5613        | RStructList (n, _) ->
5614            pr "  /* caller will free this */\n";
5615            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5616        | RBufferOut n ->
5617            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5618            pr "   * _val might be NULL here.  To make the API saner for\n";
5619            pr "   * callers, we turn this case into a unique pointer (using\n";
5620            pr "   * malloc(1)).\n";
5621            pr "   */\n";
5622            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5623            pr "    *size_r = ret.%s.%s_len;\n" n n;
5624            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5625            pr "  } else {\n";
5626            pr "    free (ret.%s.%s_val);\n" n n;
5627            pr "    char *p = safe_malloc (g, 1);\n";
5628            pr "    *size_r = ret.%s.%s_len;\n" n n;
5629            pr "    return p;\n";
5630            pr "  }\n";
5631       );
5632
5633       pr "}\n\n"
5634   ) daemon_functions;
5635
5636   (* Functions to free structures. *)
5637   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5638   pr " * structure format is identical to the XDR format.  See note in\n";
5639   pr " * generator.ml.\n";
5640   pr " */\n";
5641   pr "\n";
5642
5643   List.iter (
5644     fun (typ, _) ->
5645       pr "void\n";
5646       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5647       pr "{\n";
5648       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5649       pr "  free (x);\n";
5650       pr "}\n";
5651       pr "\n";
5652
5653       pr "void\n";
5654       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5655       pr "{\n";
5656       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5657       pr "  free (x);\n";
5658       pr "}\n";
5659       pr "\n";
5660
5661   ) structs;
5662
5663 (* Generate daemon/actions.h. *)
5664 and generate_daemon_actions_h () =
5665   generate_header CStyle GPLv2plus;
5666
5667   pr "#include \"../src/guestfs_protocol.h\"\n";
5668   pr "\n";
5669
5670   List.iter (
5671     fun (name, style, _, _, _, _, _) ->
5672       generate_prototype
5673         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5674         name style;
5675   ) daemon_functions
5676
5677 (* Generate the linker script which controls the visibility of
5678  * symbols in the public ABI and ensures no other symbols get
5679  * exported accidentally.
5680  *)
5681 and generate_linker_script () =
5682   generate_header HashStyle GPLv2plus;
5683
5684   let globals = [
5685     "guestfs_create";
5686     "guestfs_close";
5687     "guestfs_get_error_handler";
5688     "guestfs_get_out_of_memory_handler";
5689     "guestfs_last_error";
5690     "guestfs_set_error_handler";
5691     "guestfs_set_launch_done_callback";
5692     "guestfs_set_log_message_callback";
5693     "guestfs_set_out_of_memory_handler";
5694     "guestfs_set_subprocess_quit_callback";
5695
5696     (* Unofficial parts of the API: the bindings code use these
5697      * functions, so it is useful to export them.
5698      *)
5699     "guestfs_safe_calloc";
5700     "guestfs_safe_malloc";
5701   ] in
5702   let functions =
5703     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5704       all_functions in
5705   let structs =
5706     List.concat (
5707       List.map (fun (typ, _) ->
5708                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5709         structs
5710     ) in
5711   let globals = List.sort compare (globals @ functions @ structs) in
5712
5713   pr "{\n";
5714   pr "    global:\n";
5715   List.iter (pr "        %s;\n") globals;
5716   pr "\n";
5717
5718   pr "    local:\n";
5719   pr "        *;\n";
5720   pr "};\n"
5721
5722 (* Generate the server-side stubs. *)
5723 and generate_daemon_actions () =
5724   generate_header CStyle GPLv2plus;
5725
5726   pr "#include <config.h>\n";
5727   pr "\n";
5728   pr "#include <stdio.h>\n";
5729   pr "#include <stdlib.h>\n";
5730   pr "#include <string.h>\n";
5731   pr "#include <inttypes.h>\n";
5732   pr "#include <rpc/types.h>\n";
5733   pr "#include <rpc/xdr.h>\n";
5734   pr "\n";
5735   pr "#include \"daemon.h\"\n";
5736   pr "#include \"c-ctype.h\"\n";
5737   pr "#include \"../src/guestfs_protocol.h\"\n";
5738   pr "#include \"actions.h\"\n";
5739   pr "\n";
5740
5741   List.iter (
5742     fun (name, style, _, _, _, _, _) ->
5743       (* Generate server-side stubs. *)
5744       pr "static void %s_stub (XDR *xdr_in)\n" name;
5745       pr "{\n";
5746       let error_code =
5747         match fst style with
5748         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5749         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5750         | RBool _ -> pr "  int r;\n"; "-1"
5751         | RConstString _ | RConstOptString _ ->
5752             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5753         | RString _ -> pr "  char *r;\n"; "NULL"
5754         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5755         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5756         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5757         | RBufferOut _ ->
5758             pr "  size_t size = 1;\n";
5759             pr "  char *r;\n";
5760             "NULL" in
5761
5762       (match snd style with
5763        | [] -> ()
5764        | args ->
5765            pr "  struct guestfs_%s_args args;\n" name;
5766            List.iter (
5767              function
5768              | Device n | Dev_or_Path n
5769              | Pathname n
5770              | String n -> ()
5771              | OptString n -> pr "  char *%s;\n" n
5772              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5773              | Bool n -> pr "  int %s;\n" n
5774              | Int n -> pr "  int %s;\n" n
5775              | Int64 n -> pr "  int64_t %s;\n" n
5776              | FileIn _ | FileOut _ -> ()
5777            ) args
5778       );
5779       pr "\n";
5780
5781       (match snd style with
5782        | [] -> ()
5783        | args ->
5784            pr "  memset (&args, 0, sizeof args);\n";
5785            pr "\n";
5786            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5787            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5788            pr "    return;\n";
5789            pr "  }\n";
5790            let pr_args n =
5791              pr "  char *%s = args.%s;\n" n n
5792            in
5793            let pr_list_handling_code n =
5794              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5795              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5796              pr "  if (%s == NULL) {\n" n;
5797              pr "    reply_with_perror (\"realloc\");\n";
5798              pr "    goto done;\n";
5799              pr "  }\n";
5800              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5801              pr "  args.%s.%s_val = %s;\n" n n n;
5802            in
5803            List.iter (
5804              function
5805              | Pathname n ->
5806                  pr_args n;
5807                  pr "  ABS_PATH (%s, goto done);\n" n;
5808              | Device n ->
5809                  pr_args n;
5810                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5811              | Dev_or_Path n ->
5812                  pr_args n;
5813                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5814              | String n -> pr_args n
5815              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5816              | StringList n ->
5817                  pr_list_handling_code n;
5818              | DeviceList n ->
5819                  pr_list_handling_code n;
5820                  pr "  /* Ensure that each is a device,\n";
5821                  pr "   * and perform device name translation. */\n";
5822                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5823                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5824                  pr "  }\n";
5825              | Bool n -> pr "  %s = args.%s;\n" n n
5826              | Int n -> pr "  %s = args.%s;\n" n n
5827              | Int64 n -> pr "  %s = args.%s;\n" n n
5828              | FileIn _ | FileOut _ -> ()
5829            ) args;
5830            pr "\n"
5831       );
5832
5833
5834       (* this is used at least for do_equal *)
5835       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5836         (* Emit NEED_ROOT just once, even when there are two or
5837            more Pathname args *)
5838         pr "  NEED_ROOT (goto done);\n";
5839       );
5840
5841       (* Don't want to call the impl with any FileIn or FileOut
5842        * parameters, since these go "outside" the RPC protocol.
5843        *)
5844       let args' =
5845         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5846           (snd style) in
5847       pr "  r = do_%s " name;
5848       generate_c_call_args (fst style, args');
5849       pr ";\n";
5850
5851       (match fst style with
5852        | RErr | RInt _ | RInt64 _ | RBool _
5853        | RConstString _ | RConstOptString _
5854        | RString _ | RStringList _ | RHashtable _
5855        | RStruct (_, _) | RStructList (_, _) ->
5856            pr "  if (r == %s)\n" error_code;
5857            pr "    /* do_%s has already called reply_with_error */\n" name;
5858            pr "    goto done;\n";
5859            pr "\n"
5860        | RBufferOut _ ->
5861            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5862            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5863            pr "   */\n";
5864            pr "  if (size == 1 && r == %s)\n" error_code;
5865            pr "    /* do_%s has already called reply_with_error */\n" name;
5866            pr "    goto done;\n";
5867            pr "\n"
5868       );
5869
5870       (* If there are any FileOut parameters, then the impl must
5871        * send its own reply.
5872        *)
5873       let no_reply =
5874         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5875       if no_reply then
5876         pr "  /* do_%s has already sent a reply */\n" name
5877       else (
5878         match fst style with
5879         | RErr -> pr "  reply (NULL, NULL);\n"
5880         | RInt n | RInt64 n | RBool n ->
5881             pr "  struct guestfs_%s_ret ret;\n" name;
5882             pr "  ret.%s = r;\n" n;
5883             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5884               name
5885         | RConstString _ | RConstOptString _ ->
5886             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5887         | RString n ->
5888             pr "  struct guestfs_%s_ret ret;\n" name;
5889             pr "  ret.%s = r;\n" n;
5890             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5891               name;
5892             pr "  free (r);\n"
5893         | RStringList n | RHashtable n ->
5894             pr "  struct guestfs_%s_ret ret;\n" name;
5895             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5896             pr "  ret.%s.%s_val = r;\n" n n;
5897             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5898               name;
5899             pr "  free_strings (r);\n"
5900         | RStruct (n, _) ->
5901             pr "  struct guestfs_%s_ret ret;\n" name;
5902             pr "  ret.%s = *r;\n" n;
5903             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5904               name;
5905             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5906               name
5907         | RStructList (n, _) ->
5908             pr "  struct guestfs_%s_ret ret;\n" name;
5909             pr "  ret.%s = *r;\n" n;
5910             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5911               name;
5912             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5913               name
5914         | RBufferOut n ->
5915             pr "  struct guestfs_%s_ret ret;\n" name;
5916             pr "  ret.%s.%s_val = r;\n" n n;
5917             pr "  ret.%s.%s_len = size;\n" n n;
5918             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5919               name;
5920             pr "  free (r);\n"
5921       );
5922
5923       (* Free the args. *)
5924       (match snd style with
5925        | [] ->
5926            pr "done: ;\n";
5927        | _ ->
5928            pr "done:\n";
5929            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5930              name
5931       );
5932
5933       pr "}\n\n";
5934   ) daemon_functions;
5935
5936   (* Dispatch function. *)
5937   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5938   pr "{\n";
5939   pr "  switch (proc_nr) {\n";
5940
5941   List.iter (
5942     fun (name, style, _, _, _, _, _) ->
5943       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5944       pr "      %s_stub (xdr_in);\n" name;
5945       pr "      break;\n"
5946   ) daemon_functions;
5947
5948   pr "    default:\n";
5949   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";
5950   pr "  }\n";
5951   pr "}\n";
5952   pr "\n";
5953
5954   (* LVM columns and tokenization functions. *)
5955   (* XXX This generates crap code.  We should rethink how we
5956    * do this parsing.
5957    *)
5958   List.iter (
5959     function
5960     | typ, cols ->
5961         pr "static const char *lvm_%s_cols = \"%s\";\n"
5962           typ (String.concat "," (List.map fst cols));
5963         pr "\n";
5964
5965         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5966         pr "{\n";
5967         pr "  char *tok, *p, *next;\n";
5968         pr "  int i, j;\n";
5969         pr "\n";
5970         (*
5971           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5972           pr "\n";
5973         *)
5974         pr "  if (!str) {\n";
5975         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5976         pr "    return -1;\n";
5977         pr "  }\n";
5978         pr "  if (!*str || c_isspace (*str)) {\n";
5979         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5980         pr "    return -1;\n";
5981         pr "  }\n";
5982         pr "  tok = str;\n";
5983         List.iter (
5984           fun (name, coltype) ->
5985             pr "  if (!tok) {\n";
5986             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5987             pr "    return -1;\n";
5988             pr "  }\n";
5989             pr "  p = strchrnul (tok, ',');\n";
5990             pr "  if (*p) next = p+1; else next = NULL;\n";
5991             pr "  *p = '\\0';\n";
5992             (match coltype with
5993              | FString ->
5994                  pr "  r->%s = strdup (tok);\n" name;
5995                  pr "  if (r->%s == NULL) {\n" name;
5996                  pr "    perror (\"strdup\");\n";
5997                  pr "    return -1;\n";
5998                  pr "  }\n"
5999              | FUUID ->
6000                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6001                  pr "    if (tok[j] == '\\0') {\n";
6002                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6003                  pr "      return -1;\n";
6004                  pr "    } else if (tok[j] != '-')\n";
6005                  pr "      r->%s[i++] = tok[j];\n" name;
6006                  pr "  }\n";
6007              | FBytes ->
6008                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6009                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6010                  pr "    return -1;\n";
6011                  pr "  }\n";
6012              | FInt64 ->
6013                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6014                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6015                  pr "    return -1;\n";
6016                  pr "  }\n";
6017              | FOptPercent ->
6018                  pr "  if (tok[0] == '\\0')\n";
6019                  pr "    r->%s = -1;\n" name;
6020                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6021                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6022                  pr "    return -1;\n";
6023                  pr "  }\n";
6024              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6025                  assert false (* can never be an LVM column *)
6026             );
6027             pr "  tok = next;\n";
6028         ) cols;
6029
6030         pr "  if (tok != NULL) {\n";
6031         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6032         pr "    return -1;\n";
6033         pr "  }\n";
6034         pr "  return 0;\n";
6035         pr "}\n";
6036         pr "\n";
6037
6038         pr "guestfs_int_lvm_%s_list *\n" typ;
6039         pr "parse_command_line_%ss (void)\n" typ;
6040         pr "{\n";
6041         pr "  char *out, *err;\n";
6042         pr "  char *p, *pend;\n";
6043         pr "  int r, i;\n";
6044         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6045         pr "  void *newp;\n";
6046         pr "\n";
6047         pr "  ret = malloc (sizeof *ret);\n";
6048         pr "  if (!ret) {\n";
6049         pr "    reply_with_perror (\"malloc\");\n";
6050         pr "    return NULL;\n";
6051         pr "  }\n";
6052         pr "\n";
6053         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6054         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6055         pr "\n";
6056         pr "  r = command (&out, &err,\n";
6057         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
6058         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6059         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6060         pr "  if (r == -1) {\n";
6061         pr "    reply_with_error (\"%%s\", err);\n";
6062         pr "    free (out);\n";
6063         pr "    free (err);\n";
6064         pr "    free (ret);\n";
6065         pr "    return NULL;\n";
6066         pr "  }\n";
6067         pr "\n";
6068         pr "  free (err);\n";
6069         pr "\n";
6070         pr "  /* Tokenize each line of the output. */\n";
6071         pr "  p = out;\n";
6072         pr "  i = 0;\n";
6073         pr "  while (p) {\n";
6074         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6075         pr "    if (pend) {\n";
6076         pr "      *pend = '\\0';\n";
6077         pr "      pend++;\n";
6078         pr "    }\n";
6079         pr "\n";
6080         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6081         pr "      p++;\n";
6082         pr "\n";
6083         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6084         pr "      p = pend;\n";
6085         pr "      continue;\n";
6086         pr "    }\n";
6087         pr "\n";
6088         pr "    /* Allocate some space to store this next entry. */\n";
6089         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6090         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6091         pr "    if (newp == NULL) {\n";
6092         pr "      reply_with_perror (\"realloc\");\n";
6093         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6094         pr "      free (ret);\n";
6095         pr "      free (out);\n";
6096         pr "      return NULL;\n";
6097         pr "    }\n";
6098         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6099         pr "\n";
6100         pr "    /* Tokenize the next entry. */\n";
6101         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6102         pr "    if (r == -1) {\n";
6103         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6104         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6105         pr "      free (ret);\n";
6106         pr "      free (out);\n";
6107         pr "      return NULL;\n";
6108         pr "    }\n";
6109         pr "\n";
6110         pr "    ++i;\n";
6111         pr "    p = pend;\n";
6112         pr "  }\n";
6113         pr "\n";
6114         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6115         pr "\n";
6116         pr "  free (out);\n";
6117         pr "  return ret;\n";
6118         pr "}\n"
6119
6120   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6121
6122 (* Generate a list of function names, for debugging in the daemon.. *)
6123 and generate_daemon_names () =
6124   generate_header CStyle GPLv2plus;
6125
6126   pr "#include <config.h>\n";
6127   pr "\n";
6128   pr "#include \"daemon.h\"\n";
6129   pr "\n";
6130
6131   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6132   pr "const char *function_names[] = {\n";
6133   List.iter (
6134     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6135   ) daemon_functions;
6136   pr "};\n";
6137
6138 (* Generate the optional groups for the daemon to implement
6139  * guestfs_available.
6140  *)
6141 and generate_daemon_optgroups_c () =
6142   generate_header CStyle GPLv2plus;
6143
6144   pr "#include <config.h>\n";
6145   pr "\n";
6146   pr "#include \"daemon.h\"\n";
6147   pr "#include \"optgroups.h\"\n";
6148   pr "\n";
6149
6150   pr "struct optgroup optgroups[] = {\n";
6151   List.iter (
6152     fun (group, _) ->
6153       pr "  { \"%s\", optgroup_%s_available },\n" group group
6154   ) optgroups;
6155   pr "  { NULL, NULL }\n";
6156   pr "};\n"
6157
6158 and generate_daemon_optgroups_h () =
6159   generate_header CStyle GPLv2plus;
6160
6161   List.iter (
6162     fun (group, _) ->
6163       pr "extern int optgroup_%s_available (void);\n" group
6164   ) optgroups
6165
6166 (* Generate the tests. *)
6167 and generate_tests () =
6168   generate_header CStyle GPLv2plus;
6169
6170   pr "\
6171 #include <stdio.h>
6172 #include <stdlib.h>
6173 #include <string.h>
6174 #include <unistd.h>
6175 #include <sys/types.h>
6176 #include <fcntl.h>
6177
6178 #include \"guestfs.h\"
6179 #include \"guestfs-internal.h\"
6180
6181 static guestfs_h *g;
6182 static int suppress_error = 0;
6183
6184 static void print_error (guestfs_h *g, void *data, const char *msg)
6185 {
6186   if (!suppress_error)
6187     fprintf (stderr, \"%%s\\n\", msg);
6188 }
6189
6190 /* FIXME: nearly identical code appears in fish.c */
6191 static void print_strings (char *const *argv)
6192 {
6193   int argc;
6194
6195   for (argc = 0; argv[argc] != NULL; ++argc)
6196     printf (\"\\t%%s\\n\", argv[argc]);
6197 }
6198
6199 /*
6200 static void print_table (char const *const *argv)
6201 {
6202   int i;
6203
6204   for (i = 0; argv[i] != NULL; i += 2)
6205     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6206 }
6207 */
6208
6209 ";
6210
6211   (* Generate a list of commands which are not tested anywhere. *)
6212   pr "static void no_test_warnings (void)\n";
6213   pr "{\n";
6214
6215   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6216   List.iter (
6217     fun (_, _, _, _, tests, _, _) ->
6218       let tests = filter_map (
6219         function
6220         | (_, (Always|If _|Unless _), test) -> Some test
6221         | (_, Disabled, _) -> None
6222       ) tests in
6223       let seq = List.concat (List.map seq_of_test tests) in
6224       let cmds_tested = List.map List.hd seq in
6225       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6226   ) all_functions;
6227
6228   List.iter (
6229     fun (name, _, _, _, _, _, _) ->
6230       if not (Hashtbl.mem hash name) then
6231         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6232   ) all_functions;
6233
6234   pr "}\n";
6235   pr "\n";
6236
6237   (* Generate the actual tests.  Note that we generate the tests
6238    * in reverse order, deliberately, so that (in general) the
6239    * newest tests run first.  This makes it quicker and easier to
6240    * debug them.
6241    *)
6242   let test_names =
6243     List.map (
6244       fun (name, _, _, flags, tests, _, _) ->
6245         mapi (generate_one_test name flags) tests
6246     ) (List.rev all_functions) in
6247   let test_names = List.concat test_names in
6248   let nr_tests = List.length test_names in
6249
6250   pr "\
6251 int main (int argc, char *argv[])
6252 {
6253   char c = 0;
6254   unsigned long int n_failed = 0;
6255   const char *filename;
6256   int fd;
6257   int nr_tests, test_num = 0;
6258
6259   setbuf (stdout, NULL);
6260
6261   no_test_warnings ();
6262
6263   g = guestfs_create ();
6264   if (g == NULL) {
6265     printf (\"guestfs_create FAILED\\n\");
6266     exit (EXIT_FAILURE);
6267   }
6268
6269   guestfs_set_error_handler (g, print_error, NULL);
6270
6271   guestfs_set_path (g, \"../appliance\");
6272
6273   filename = \"test1.img\";
6274   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6275   if (fd == -1) {
6276     perror (filename);
6277     exit (EXIT_FAILURE);
6278   }
6279   if (lseek (fd, %d, SEEK_SET) == -1) {
6280     perror (\"lseek\");
6281     close (fd);
6282     unlink (filename);
6283     exit (EXIT_FAILURE);
6284   }
6285   if (write (fd, &c, 1) == -1) {
6286     perror (\"write\");
6287     close (fd);
6288     unlink (filename);
6289     exit (EXIT_FAILURE);
6290   }
6291   if (close (fd) == -1) {
6292     perror (filename);
6293     unlink (filename);
6294     exit (EXIT_FAILURE);
6295   }
6296   if (guestfs_add_drive (g, filename) == -1) {
6297     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6298     exit (EXIT_FAILURE);
6299   }
6300
6301   filename = \"test2.img\";
6302   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6303   if (fd == -1) {
6304     perror (filename);
6305     exit (EXIT_FAILURE);
6306   }
6307   if (lseek (fd, %d, SEEK_SET) == -1) {
6308     perror (\"lseek\");
6309     close (fd);
6310     unlink (filename);
6311     exit (EXIT_FAILURE);
6312   }
6313   if (write (fd, &c, 1) == -1) {
6314     perror (\"write\");
6315     close (fd);
6316     unlink (filename);
6317     exit (EXIT_FAILURE);
6318   }
6319   if (close (fd) == -1) {
6320     perror (filename);
6321     unlink (filename);
6322     exit (EXIT_FAILURE);
6323   }
6324   if (guestfs_add_drive (g, filename) == -1) {
6325     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6326     exit (EXIT_FAILURE);
6327   }
6328
6329   filename = \"test3.img\";
6330   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6331   if (fd == -1) {
6332     perror (filename);
6333     exit (EXIT_FAILURE);
6334   }
6335   if (lseek (fd, %d, SEEK_SET) == -1) {
6336     perror (\"lseek\");
6337     close (fd);
6338     unlink (filename);
6339     exit (EXIT_FAILURE);
6340   }
6341   if (write (fd, &c, 1) == -1) {
6342     perror (\"write\");
6343     close (fd);
6344     unlink (filename);
6345     exit (EXIT_FAILURE);
6346   }
6347   if (close (fd) == -1) {
6348     perror (filename);
6349     unlink (filename);
6350     exit (EXIT_FAILURE);
6351   }
6352   if (guestfs_add_drive (g, filename) == -1) {
6353     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6354     exit (EXIT_FAILURE);
6355   }
6356
6357   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6358     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6359     exit (EXIT_FAILURE);
6360   }
6361
6362   if (guestfs_launch (g) == -1) {
6363     printf (\"guestfs_launch FAILED\\n\");
6364     exit (EXIT_FAILURE);
6365   }
6366
6367   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6368   alarm (600);
6369
6370   /* Cancel previous alarm. */
6371   alarm (0);
6372
6373   nr_tests = %d;
6374
6375 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6376
6377   iteri (
6378     fun i test_name ->
6379       pr "  test_num++;\n";
6380       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6381       pr "  if (%s () == -1) {\n" test_name;
6382       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6383       pr "    n_failed++;\n";
6384       pr "  }\n";
6385   ) test_names;
6386   pr "\n";
6387
6388   pr "  guestfs_close (g);\n";
6389   pr "  unlink (\"test1.img\");\n";
6390   pr "  unlink (\"test2.img\");\n";
6391   pr "  unlink (\"test3.img\");\n";
6392   pr "\n";
6393
6394   pr "  if (n_failed > 0) {\n";
6395   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6396   pr "    exit (EXIT_FAILURE);\n";
6397   pr "  }\n";
6398   pr "\n";
6399
6400   pr "  exit (EXIT_SUCCESS);\n";
6401   pr "}\n"
6402
6403 and generate_one_test name flags i (init, prereq, test) =
6404   let test_name = sprintf "test_%s_%d" name i in
6405
6406   pr "\
6407 static int %s_skip (void)
6408 {
6409   const char *str;
6410
6411   str = getenv (\"TEST_ONLY\");
6412   if (str)
6413     return strstr (str, \"%s\") == NULL;
6414   str = getenv (\"SKIP_%s\");
6415   if (str && STREQ (str, \"1\")) return 1;
6416   str = getenv (\"SKIP_TEST_%s\");
6417   if (str && STREQ (str, \"1\")) return 1;
6418   return 0;
6419 }
6420
6421 " test_name name (String.uppercase test_name) (String.uppercase name);
6422
6423   (match prereq with
6424    | Disabled | Always -> ()
6425    | If code | Unless code ->
6426        pr "static int %s_prereq (void)\n" test_name;
6427        pr "{\n";
6428        pr "  %s\n" code;
6429        pr "}\n";
6430        pr "\n";
6431   );
6432
6433   pr "\
6434 static int %s (void)
6435 {
6436   if (%s_skip ()) {
6437     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6438     return 0;
6439   }
6440
6441 " test_name test_name test_name;
6442
6443   (* Optional functions should only be tested if the relevant
6444    * support is available in the daemon.
6445    *)
6446   List.iter (
6447     function
6448     | Optional group ->
6449         pr "  {\n";
6450         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6451         pr "    int r;\n";
6452         pr "    suppress_error = 1;\n";
6453         pr "    r = guestfs_available (g, (char **) groups);\n";
6454         pr "    suppress_error = 0;\n";
6455         pr "    if (r == -1) {\n";
6456         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6457         pr "      return 0;\n";
6458         pr "    }\n";
6459         pr "  }\n";
6460     | _ -> ()
6461   ) flags;
6462
6463   (match prereq with
6464    | Disabled ->
6465        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6466    | If _ ->
6467        pr "  if (! %s_prereq ()) {\n" test_name;
6468        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6469        pr "    return 0;\n";
6470        pr "  }\n";
6471        pr "\n";
6472        generate_one_test_body name i test_name init test;
6473    | Unless _ ->
6474        pr "  if (%s_prereq ()) {\n" test_name;
6475        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6476        pr "    return 0;\n";
6477        pr "  }\n";
6478        pr "\n";
6479        generate_one_test_body name i test_name init test;
6480    | Always ->
6481        generate_one_test_body name i test_name init test
6482   );
6483
6484   pr "  return 0;\n";
6485   pr "}\n";
6486   pr "\n";
6487   test_name
6488
6489 and generate_one_test_body name i test_name init test =
6490   (match init with
6491    | InitNone (* XXX at some point, InitNone and InitEmpty became
6492                * folded together as the same thing.  Really we should
6493                * make InitNone do nothing at all, but the tests may
6494                * need to be checked to make sure this is OK.
6495                *)
6496    | InitEmpty ->
6497        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6498        List.iter (generate_test_command_call test_name)
6499          [["blockdev_setrw"; "/dev/sda"];
6500           ["umount_all"];
6501           ["lvm_remove_all"]]
6502    | InitPartition ->
6503        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6504        List.iter (generate_test_command_call test_name)
6505          [["blockdev_setrw"; "/dev/sda"];
6506           ["umount_all"];
6507           ["lvm_remove_all"];
6508           ["part_disk"; "/dev/sda"; "mbr"]]
6509    | InitBasicFS ->
6510        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6511        List.iter (generate_test_command_call test_name)
6512          [["blockdev_setrw"; "/dev/sda"];
6513           ["umount_all"];
6514           ["lvm_remove_all"];
6515           ["part_disk"; "/dev/sda"; "mbr"];
6516           ["mkfs"; "ext2"; "/dev/sda1"];
6517           ["mount_options"; ""; "/dev/sda1"; "/"]]
6518    | InitBasicFSonLVM ->
6519        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6520          test_name;
6521        List.iter (generate_test_command_call test_name)
6522          [["blockdev_setrw"; "/dev/sda"];
6523           ["umount_all"];
6524           ["lvm_remove_all"];
6525           ["part_disk"; "/dev/sda"; "mbr"];
6526           ["pvcreate"; "/dev/sda1"];
6527           ["vgcreate"; "VG"; "/dev/sda1"];
6528           ["lvcreate"; "LV"; "VG"; "8"];
6529           ["mkfs"; "ext2"; "/dev/VG/LV"];
6530           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6531    | InitISOFS ->
6532        pr "  /* InitISOFS for %s */\n" test_name;
6533        List.iter (generate_test_command_call test_name)
6534          [["blockdev_setrw"; "/dev/sda"];
6535           ["umount_all"];
6536           ["lvm_remove_all"];
6537           ["mount_ro"; "/dev/sdd"; "/"]]
6538   );
6539
6540   let get_seq_last = function
6541     | [] ->
6542         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6543           test_name
6544     | seq ->
6545         let seq = List.rev seq in
6546         List.rev (List.tl seq), List.hd seq
6547   in
6548
6549   match test with
6550   | TestRun seq ->
6551       pr "  /* TestRun for %s (%d) */\n" name i;
6552       List.iter (generate_test_command_call test_name) seq
6553   | TestOutput (seq, expected) ->
6554       pr "  /* TestOutput for %s (%d) */\n" name i;
6555       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6556       let seq, last = get_seq_last seq in
6557       let test () =
6558         pr "    if (STRNEQ (r, expected)) {\n";
6559         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6560         pr "      return -1;\n";
6561         pr "    }\n"
6562       in
6563       List.iter (generate_test_command_call test_name) seq;
6564       generate_test_command_call ~test test_name last
6565   | TestOutputList (seq, expected) ->
6566       pr "  /* TestOutputList for %s (%d) */\n" name i;
6567       let seq, last = get_seq_last seq in
6568       let test () =
6569         iteri (
6570           fun i str ->
6571             pr "    if (!r[%d]) {\n" i;
6572             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6573             pr "      print_strings (r);\n";
6574             pr "      return -1;\n";
6575             pr "    }\n";
6576             pr "    {\n";
6577             pr "      const char *expected = \"%s\";\n" (c_quote str);
6578             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6579             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6580             pr "        return -1;\n";
6581             pr "      }\n";
6582             pr "    }\n"
6583         ) expected;
6584         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6585         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6586           test_name;
6587         pr "      print_strings (r);\n";
6588         pr "      return -1;\n";
6589         pr "    }\n"
6590       in
6591       List.iter (generate_test_command_call test_name) seq;
6592       generate_test_command_call ~test test_name last
6593   | TestOutputListOfDevices (seq, expected) ->
6594       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6595       let seq, last = get_seq_last seq in
6596       let test () =
6597         iteri (
6598           fun i str ->
6599             pr "    if (!r[%d]) {\n" i;
6600             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6601             pr "      print_strings (r);\n";
6602             pr "      return -1;\n";
6603             pr "    }\n";
6604             pr "    {\n";
6605             pr "      const char *expected = \"%s\";\n" (c_quote str);
6606             pr "      r[%d][5] = 's';\n" i;
6607             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6608             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6609             pr "        return -1;\n";
6610             pr "      }\n";
6611             pr "    }\n"
6612         ) expected;
6613         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6614         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6615           test_name;
6616         pr "      print_strings (r);\n";
6617         pr "      return -1;\n";
6618         pr "    }\n"
6619       in
6620       List.iter (generate_test_command_call test_name) seq;
6621       generate_test_command_call ~test test_name last
6622   | TestOutputInt (seq, expected) ->
6623       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6624       let seq, last = get_seq_last seq in
6625       let test () =
6626         pr "    if (r != %d) {\n" expected;
6627         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6628           test_name expected;
6629         pr "               (int) r);\n";
6630         pr "      return -1;\n";
6631         pr "    }\n"
6632       in
6633       List.iter (generate_test_command_call test_name) seq;
6634       generate_test_command_call ~test test_name last
6635   | TestOutputIntOp (seq, op, expected) ->
6636       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6637       let seq, last = get_seq_last seq in
6638       let test () =
6639         pr "    if (! (r %s %d)) {\n" op expected;
6640         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6641           test_name op expected;
6642         pr "               (int) r);\n";
6643         pr "      return -1;\n";
6644         pr "    }\n"
6645       in
6646       List.iter (generate_test_command_call test_name) seq;
6647       generate_test_command_call ~test test_name last
6648   | TestOutputTrue seq ->
6649       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6650       let seq, last = get_seq_last seq in
6651       let test () =
6652         pr "    if (!r) {\n";
6653         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6654           test_name;
6655         pr "      return -1;\n";
6656         pr "    }\n"
6657       in
6658       List.iter (generate_test_command_call test_name) seq;
6659       generate_test_command_call ~test test_name last
6660   | TestOutputFalse seq ->
6661       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6662       let seq, last = get_seq_last seq in
6663       let test () =
6664         pr "    if (r) {\n";
6665         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6666           test_name;
6667         pr "      return -1;\n";
6668         pr "    }\n"
6669       in
6670       List.iter (generate_test_command_call test_name) seq;
6671       generate_test_command_call ~test test_name last
6672   | TestOutputLength (seq, expected) ->
6673       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6674       let seq, last = get_seq_last seq in
6675       let test () =
6676         pr "    int j;\n";
6677         pr "    for (j = 0; j < %d; ++j)\n" expected;
6678         pr "      if (r[j] == NULL) {\n";
6679         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6680           test_name;
6681         pr "        print_strings (r);\n";
6682         pr "        return -1;\n";
6683         pr "      }\n";
6684         pr "    if (r[j] != NULL) {\n";
6685         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6686           test_name;
6687         pr "      print_strings (r);\n";
6688         pr "      return -1;\n";
6689         pr "    }\n"
6690       in
6691       List.iter (generate_test_command_call test_name) seq;
6692       generate_test_command_call ~test test_name last
6693   | TestOutputBuffer (seq, expected) ->
6694       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6695       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6696       let seq, last = get_seq_last seq in
6697       let len = String.length expected in
6698       let test () =
6699         pr "    if (size != %d) {\n" len;
6700         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6701         pr "      return -1;\n";
6702         pr "    }\n";
6703         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6704         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6705         pr "      return -1;\n";
6706         pr "    }\n"
6707       in
6708       List.iter (generate_test_command_call test_name) seq;
6709       generate_test_command_call ~test test_name last
6710   | TestOutputStruct (seq, checks) ->
6711       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6712       let seq, last = get_seq_last seq in
6713       let test () =
6714         List.iter (
6715           function
6716           | CompareWithInt (field, expected) ->
6717               pr "    if (r->%s != %d) {\n" field expected;
6718               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6719                 test_name field expected;
6720               pr "               (int) r->%s);\n" field;
6721               pr "      return -1;\n";
6722               pr "    }\n"
6723           | CompareWithIntOp (field, op, expected) ->
6724               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6725               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6726                 test_name field op expected;
6727               pr "               (int) r->%s);\n" field;
6728               pr "      return -1;\n";
6729               pr "    }\n"
6730           | CompareWithString (field, expected) ->
6731               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6732               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6733                 test_name field expected;
6734               pr "               r->%s);\n" field;
6735               pr "      return -1;\n";
6736               pr "    }\n"
6737           | CompareFieldsIntEq (field1, field2) ->
6738               pr "    if (r->%s != r->%s) {\n" field1 field2;
6739               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6740                 test_name field1 field2;
6741               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6742               pr "      return -1;\n";
6743               pr "    }\n"
6744           | CompareFieldsStrEq (field1, field2) ->
6745               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6746               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6747                 test_name field1 field2;
6748               pr "               r->%s, r->%s);\n" field1 field2;
6749               pr "      return -1;\n";
6750               pr "    }\n"
6751         ) checks
6752       in
6753       List.iter (generate_test_command_call test_name) seq;
6754       generate_test_command_call ~test test_name last
6755   | TestLastFail seq ->
6756       pr "  /* TestLastFail for %s (%d) */\n" name i;
6757       let seq, last = get_seq_last seq in
6758       List.iter (generate_test_command_call test_name) seq;
6759       generate_test_command_call test_name ~expect_error:true last
6760
6761 (* Generate the code to run a command, leaving the result in 'r'.
6762  * If you expect to get an error then you should set expect_error:true.
6763  *)
6764 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6765   match cmd with
6766   | [] -> assert false
6767   | name :: args ->
6768       (* Look up the command to find out what args/ret it has. *)
6769       let style =
6770         try
6771           let _, style, _, _, _, _, _ =
6772             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6773           style
6774         with Not_found ->
6775           failwithf "%s: in test, command %s was not found" test_name name in
6776
6777       if List.length (snd style) <> List.length args then
6778         failwithf "%s: in test, wrong number of args given to %s"
6779           test_name name;
6780
6781       pr "  {\n";
6782
6783       List.iter (
6784         function
6785         | OptString n, "NULL" -> ()
6786         | Pathname n, arg
6787         | Device n, arg
6788         | Dev_or_Path n, arg
6789         | String n, arg
6790         | OptString n, arg ->
6791             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6792         | Int _, _
6793         | Int64 _, _
6794         | Bool _, _
6795         | FileIn _, _ | FileOut _, _ -> ()
6796         | StringList n, "" | DeviceList n, "" ->
6797             pr "    const char *const %s[1] = { NULL };\n" n
6798         | StringList n, arg | DeviceList n, arg ->
6799             let strs = string_split " " arg in
6800             iteri (
6801               fun i str ->
6802                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6803             ) strs;
6804             pr "    const char *const %s[] = {\n" n;
6805             iteri (
6806               fun i _ -> pr "      %s_%d,\n" n i
6807             ) strs;
6808             pr "      NULL\n";
6809             pr "    };\n";
6810       ) (List.combine (snd style) args);
6811
6812       let error_code =
6813         match fst style with
6814         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6815         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6816         | RConstString _ | RConstOptString _ ->
6817             pr "    const char *r;\n"; "NULL"
6818         | RString _ -> pr "    char *r;\n"; "NULL"
6819         | RStringList _ | RHashtable _ ->
6820             pr "    char **r;\n";
6821             pr "    int i;\n";
6822             "NULL"
6823         | RStruct (_, typ) ->
6824             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6825         | RStructList (_, typ) ->
6826             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6827         | RBufferOut _ ->
6828             pr "    char *r;\n";
6829             pr "    size_t size;\n";
6830             "NULL" in
6831
6832       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6833       pr "    r = guestfs_%s (g" name;
6834
6835       (* Generate the parameters. *)
6836       List.iter (
6837         function
6838         | OptString _, "NULL" -> pr ", NULL"
6839         | Pathname n, _
6840         | Device n, _ | Dev_or_Path n, _
6841         | String n, _
6842         | OptString n, _ ->
6843             pr ", %s" n
6844         | FileIn _, arg | FileOut _, arg ->
6845             pr ", \"%s\"" (c_quote arg)
6846         | StringList n, _ | DeviceList n, _ ->
6847             pr ", (char **) %s" n
6848         | Int _, arg ->
6849             let i =
6850               try int_of_string arg
6851               with Failure "int_of_string" ->
6852                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6853             pr ", %d" i
6854         | Int64 _, arg ->
6855             let i =
6856               try Int64.of_string arg
6857               with Failure "int_of_string" ->
6858                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6859             pr ", %Ld" i
6860         | Bool _, arg ->
6861             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6862       ) (List.combine (snd style) args);
6863
6864       (match fst style with
6865        | RBufferOut _ -> pr ", &size"
6866        | _ -> ()
6867       );
6868
6869       pr ");\n";
6870
6871       if not expect_error then
6872         pr "    if (r == %s)\n" error_code
6873       else
6874         pr "    if (r != %s)\n" error_code;
6875       pr "      return -1;\n";
6876
6877       (* Insert the test code. *)
6878       (match test with
6879        | None -> ()
6880        | Some f -> f ()
6881       );
6882
6883       (match fst style with
6884        | RErr | RInt _ | RInt64 _ | RBool _
6885        | RConstString _ | RConstOptString _ -> ()
6886        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6887        | RStringList _ | RHashtable _ ->
6888            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6889            pr "      free (r[i]);\n";
6890            pr "    free (r);\n"
6891        | RStruct (_, typ) ->
6892            pr "    guestfs_free_%s (r);\n" typ
6893        | RStructList (_, typ) ->
6894            pr "    guestfs_free_%s_list (r);\n" typ
6895       );
6896
6897       pr "  }\n"
6898
6899 and c_quote str =
6900   let str = replace_str str "\r" "\\r" in
6901   let str = replace_str str "\n" "\\n" in
6902   let str = replace_str str "\t" "\\t" in
6903   let str = replace_str str "\000" "\\0" in
6904   str
6905
6906 (* Generate a lot of different functions for guestfish. *)
6907 and generate_fish_cmds () =
6908   generate_header CStyle GPLv2plus;
6909
6910   let all_functions =
6911     List.filter (
6912       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6913     ) all_functions in
6914   let all_functions_sorted =
6915     List.filter (
6916       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6917     ) all_functions_sorted in
6918
6919   pr "#include <config.h>\n";
6920   pr "\n";
6921   pr "#include <stdio.h>\n";
6922   pr "#include <stdlib.h>\n";
6923   pr "#include <string.h>\n";
6924   pr "#include <inttypes.h>\n";
6925   pr "\n";
6926   pr "#include <guestfs.h>\n";
6927   pr "#include \"c-ctype.h\"\n";
6928   pr "#include \"full-write.h\"\n";
6929   pr "#include \"xstrtol.h\"\n";
6930   pr "#include \"fish.h\"\n";
6931   pr "\n";
6932
6933   (* list_commands function, which implements guestfish -h *)
6934   pr "void list_commands (void)\n";
6935   pr "{\n";
6936   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6937   pr "  list_builtin_commands ();\n";
6938   List.iter (
6939     fun (name, _, _, flags, _, shortdesc, _) ->
6940       let name = replace_char name '_' '-' in
6941       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6942         name shortdesc
6943   ) all_functions_sorted;
6944   pr "  printf (\"    %%s\\n\",";
6945   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6946   pr "}\n";
6947   pr "\n";
6948
6949   (* display_command function, which implements guestfish -h cmd *)
6950   pr "void display_command (const char *cmd)\n";
6951   pr "{\n";
6952   List.iter (
6953     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6954       let name2 = replace_char name '_' '-' in
6955       let alias =
6956         try find_map (function FishAlias n -> Some n | _ -> None) flags
6957         with Not_found -> name in
6958       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6959       let synopsis =
6960         match snd style with
6961         | [] -> name2
6962         | args ->
6963             sprintf "%s %s"
6964               name2 (String.concat " " (List.map name_of_argt args)) in
6965
6966       let warnings =
6967         if List.mem ProtocolLimitWarning flags then
6968           ("\n\n" ^ protocol_limit_warning)
6969         else "" in
6970
6971       (* For DangerWillRobinson commands, we should probably have
6972        * guestfish prompt before allowing you to use them (especially
6973        * in interactive mode). XXX
6974        *)
6975       let warnings =
6976         warnings ^
6977           if List.mem DangerWillRobinson flags then
6978             ("\n\n" ^ danger_will_robinson)
6979           else "" in
6980
6981       let warnings =
6982         warnings ^
6983           match deprecation_notice flags with
6984           | None -> ""
6985           | Some txt -> "\n\n" ^ txt in
6986
6987       let describe_alias =
6988         if name <> alias then
6989           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6990         else "" in
6991
6992       pr "  if (";
6993       pr "STRCASEEQ (cmd, \"%s\")" name;
6994       if name <> name2 then
6995         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6996       if name <> alias then
6997         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6998       pr ")\n";
6999       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7000         name2 shortdesc
7001         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7002          "=head1 DESCRIPTION\n\n" ^
7003          longdesc ^ warnings ^ describe_alias);
7004       pr "  else\n"
7005   ) all_functions;
7006   pr "    display_builtin_command (cmd);\n";
7007   pr "}\n";
7008   pr "\n";
7009
7010   let emit_print_list_function typ =
7011     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7012       typ typ typ;
7013     pr "{\n";
7014     pr "  unsigned int i;\n";
7015     pr "\n";
7016     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7017     pr "    printf (\"[%%d] = {\\n\", i);\n";
7018     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7019     pr "    printf (\"}\\n\");\n";
7020     pr "  }\n";
7021     pr "}\n";
7022     pr "\n";
7023   in
7024
7025   (* print_* functions *)
7026   List.iter (
7027     fun (typ, cols) ->
7028       let needs_i =
7029         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7030
7031       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7032       pr "{\n";
7033       if needs_i then (
7034         pr "  unsigned int i;\n";
7035         pr "\n"
7036       );
7037       List.iter (
7038         function
7039         | name, FString ->
7040             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7041         | name, FUUID ->
7042             pr "  printf (\"%%s%s: \", indent);\n" name;
7043             pr "  for (i = 0; i < 32; ++i)\n";
7044             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7045             pr "  printf (\"\\n\");\n"
7046         | name, FBuffer ->
7047             pr "  printf (\"%%s%s: \", indent);\n" name;
7048             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7049             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7050             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7051             pr "    else\n";
7052             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7053             pr "  printf (\"\\n\");\n"
7054         | name, (FUInt64|FBytes) ->
7055             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7056               name typ name
7057         | name, FInt64 ->
7058             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7059               name typ name
7060         | name, FUInt32 ->
7061             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7062               name typ name
7063         | name, FInt32 ->
7064             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7065               name typ name
7066         | name, FChar ->
7067             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7068               name typ name
7069         | name, FOptPercent ->
7070             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7071               typ name name typ name;
7072             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7073       ) cols;
7074       pr "}\n";
7075       pr "\n";
7076   ) structs;
7077
7078   (* Emit a print_TYPE_list function definition only if that function is used. *)
7079   List.iter (
7080     function
7081     | typ, (RStructListOnly | RStructAndList) ->
7082         (* generate the function for typ *)
7083         emit_print_list_function typ
7084     | typ, _ -> () (* empty *)
7085   ) (rstructs_used_by all_functions);
7086
7087   (* Emit a print_TYPE function definition only if that function is used. *)
7088   List.iter (
7089     function
7090     | typ, (RStructOnly | RStructAndList) ->
7091         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7092         pr "{\n";
7093         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7094         pr "}\n";
7095         pr "\n";
7096     | typ, _ -> () (* empty *)
7097   ) (rstructs_used_by all_functions);
7098
7099   (* run_<action> actions *)
7100   List.iter (
7101     fun (name, style, _, flags, _, _, _) ->
7102       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7103       pr "{\n";
7104       (match fst style with
7105        | RErr
7106        | RInt _
7107        | RBool _ -> pr "  int r;\n"
7108        | RInt64 _ -> pr "  int64_t r;\n"
7109        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7110        | RString _ -> pr "  char *r;\n"
7111        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7112        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7113        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7114        | RBufferOut _ ->
7115            pr "  char *r;\n";
7116            pr "  size_t size;\n";
7117       );
7118       List.iter (
7119         function
7120         | Device n
7121         | String n
7122         | OptString n
7123         | FileIn n
7124         | FileOut n -> pr "  const char *%s;\n" n
7125         | Pathname n
7126         | Dev_or_Path n -> pr "  char *%s;\n" n
7127         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7128         | Bool n -> pr "  int %s;\n" n
7129         | Int n -> pr "  int %s;\n" n
7130         | Int64 n -> pr "  int64_t %s;\n" n
7131       ) (snd style);
7132
7133       (* Check and convert parameters. *)
7134       let argc_expected = List.length (snd style) in
7135       pr "  if (argc != %d) {\n" argc_expected;
7136       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7137         argc_expected;
7138       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7139       pr "    return -1;\n";
7140       pr "  }\n";
7141
7142       let parse_integer fn fntyp rtyp range name i =
7143         pr "  {\n";
7144         pr "    strtol_error xerr;\n";
7145         pr "    %s r;\n" fntyp;
7146         pr "\n";
7147         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7148         pr "    if (xerr != LONGINT_OK) {\n";
7149         pr "      fprintf (stderr,\n";
7150         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7151         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7152         pr "      return -1;\n";
7153         pr "    }\n";
7154         (match range with
7155          | None -> ()
7156          | Some (min, max, comment) ->
7157              pr "    /* %s */\n" comment;
7158              pr "    if (r < %s || r > %s) {\n" min max;
7159              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7160                name;
7161              pr "      return -1;\n";
7162              pr "    }\n";
7163              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7164         );
7165         pr "    %s = r;\n" name;
7166         pr "  }\n";
7167       in
7168
7169       iteri (
7170         fun i ->
7171           function
7172           | Device name
7173           | String name ->
7174               pr "  %s = argv[%d];\n" name i
7175           | Pathname name
7176           | Dev_or_Path name ->
7177               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7178               pr "  if (%s == NULL) return -1;\n" name
7179           | OptString name ->
7180               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7181                 name i i
7182           | FileIn name ->
7183               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7184                 name i i
7185           | FileOut name ->
7186               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7187                 name i i
7188           | StringList name | DeviceList name ->
7189               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7190               pr "  if (%s == NULL) return -1;\n" name;
7191           | Bool name ->
7192               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7193           | Int name ->
7194               let range =
7195                 let min = "(-(2LL<<30))"
7196                 and max = "((2LL<<30)-1)"
7197                 and comment =
7198                   "The Int type in the generator is a signed 31 bit int." in
7199                 Some (min, max, comment) in
7200               parse_integer "xstrtol" "long" "int" range name i
7201           | Int64 name ->
7202               parse_integer "xstrtoll" "long long" "int64_t" None name i
7203       ) (snd style);
7204
7205       (* Call C API function. *)
7206       let fn =
7207         try find_map (function FishAction n -> Some n | _ -> None) flags
7208         with Not_found -> sprintf "guestfs_%s" name in
7209       pr "  r = %s " fn;
7210       generate_c_call_args ~handle:"g" style;
7211       pr ";\n";
7212
7213       List.iter (
7214         function
7215         | Device name | String name
7216         | OptString name | FileIn name | FileOut name | Bool name
7217         | Int name | Int64 name -> ()
7218         | Pathname name | Dev_or_Path name ->
7219             pr "  free (%s);\n" name
7220         | StringList name | DeviceList name ->
7221             pr "  free_strings (%s);\n" name
7222       ) (snd style);
7223
7224       (* Check return value for errors and display command results. *)
7225       (match fst style with
7226        | RErr -> pr "  return r;\n"
7227        | RInt _ ->
7228            pr "  if (r == -1) return -1;\n";
7229            pr "  printf (\"%%d\\n\", r);\n";
7230            pr "  return 0;\n"
7231        | RInt64 _ ->
7232            pr "  if (r == -1) return -1;\n";
7233            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7234            pr "  return 0;\n"
7235        | RBool _ ->
7236            pr "  if (r == -1) return -1;\n";
7237            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7238            pr "  return 0;\n"
7239        | RConstString _ ->
7240            pr "  if (r == NULL) return -1;\n";
7241            pr "  printf (\"%%s\\n\", r);\n";
7242            pr "  return 0;\n"
7243        | RConstOptString _ ->
7244            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7245            pr "  return 0;\n"
7246        | RString _ ->
7247            pr "  if (r == NULL) return -1;\n";
7248            pr "  printf (\"%%s\\n\", r);\n";
7249            pr "  free (r);\n";
7250            pr "  return 0;\n"
7251        | RStringList _ ->
7252            pr "  if (r == NULL) return -1;\n";
7253            pr "  print_strings (r);\n";
7254            pr "  free_strings (r);\n";
7255            pr "  return 0;\n"
7256        | RStruct (_, typ) ->
7257            pr "  if (r == NULL) return -1;\n";
7258            pr "  print_%s (r);\n" typ;
7259            pr "  guestfs_free_%s (r);\n" typ;
7260            pr "  return 0;\n"
7261        | RStructList (_, typ) ->
7262            pr "  if (r == NULL) return -1;\n";
7263            pr "  print_%s_list (r);\n" typ;
7264            pr "  guestfs_free_%s_list (r);\n" typ;
7265            pr "  return 0;\n"
7266        | RHashtable _ ->
7267            pr "  if (r == NULL) return -1;\n";
7268            pr "  print_table (r);\n";
7269            pr "  free_strings (r);\n";
7270            pr "  return 0;\n"
7271        | RBufferOut _ ->
7272            pr "  if (r == NULL) return -1;\n";
7273            pr "  if (full_write (1, r, size) != size) {\n";
7274            pr "    perror (\"write\");\n";
7275            pr "    free (r);\n";
7276            pr "    return -1;\n";
7277            pr "  }\n";
7278            pr "  free (r);\n";
7279            pr "  return 0;\n"
7280       );
7281       pr "}\n";
7282       pr "\n"
7283   ) all_functions;
7284
7285   (* run_action function *)
7286   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7287   pr "{\n";
7288   List.iter (
7289     fun (name, _, _, flags, _, _, _) ->
7290       let name2 = replace_char name '_' '-' in
7291       let alias =
7292         try find_map (function FishAlias n -> Some n | _ -> None) flags
7293         with Not_found -> name in
7294       pr "  if (";
7295       pr "STRCASEEQ (cmd, \"%s\")" name;
7296       if name <> name2 then
7297         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7298       if name <> alias then
7299         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7300       pr ")\n";
7301       pr "    return run_%s (cmd, argc, argv);\n" name;
7302       pr "  else\n";
7303   ) all_functions;
7304   pr "    {\n";
7305   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7306   pr "      return -1;\n";
7307   pr "    }\n";
7308   pr "  return 0;\n";
7309   pr "}\n";
7310   pr "\n"
7311
7312 (* Readline completion for guestfish. *)
7313 and generate_fish_completion () =
7314   generate_header CStyle GPLv2plus;
7315
7316   let all_functions =
7317     List.filter (
7318       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7319     ) all_functions in
7320
7321   pr "\
7322 #include <config.h>
7323
7324 #include <stdio.h>
7325 #include <stdlib.h>
7326 #include <string.h>
7327
7328 #ifdef HAVE_LIBREADLINE
7329 #include <readline/readline.h>
7330 #endif
7331
7332 #include \"fish.h\"
7333
7334 #ifdef HAVE_LIBREADLINE
7335
7336 static const char *const commands[] = {
7337   BUILTIN_COMMANDS_FOR_COMPLETION,
7338 ";
7339
7340   (* Get the commands, including the aliases.  They don't need to be
7341    * sorted - the generator() function just does a dumb linear search.
7342    *)
7343   let commands =
7344     List.map (
7345       fun (name, _, _, flags, _, _, _) ->
7346         let name2 = replace_char name '_' '-' in
7347         let alias =
7348           try find_map (function FishAlias n -> Some n | _ -> None) flags
7349           with Not_found -> name in
7350
7351         if name <> alias then [name2; alias] else [name2]
7352     ) all_functions in
7353   let commands = List.flatten commands in
7354
7355   List.iter (pr "  \"%s\",\n") commands;
7356
7357   pr "  NULL
7358 };
7359
7360 static char *
7361 generator (const char *text, int state)
7362 {
7363   static int index, len;
7364   const char *name;
7365
7366   if (!state) {
7367     index = 0;
7368     len = strlen (text);
7369   }
7370
7371   rl_attempted_completion_over = 1;
7372
7373   while ((name = commands[index]) != NULL) {
7374     index++;
7375     if (STRCASEEQLEN (name, text, len))
7376       return strdup (name);
7377   }
7378
7379   return NULL;
7380 }
7381
7382 #endif /* HAVE_LIBREADLINE */
7383
7384 char **do_completion (const char *text, int start, int end)
7385 {
7386   char **matches = NULL;
7387
7388 #ifdef HAVE_LIBREADLINE
7389   rl_completion_append_character = ' ';
7390
7391   if (start == 0)
7392     matches = rl_completion_matches (text, generator);
7393   else if (complete_dest_paths)
7394     matches = rl_completion_matches (text, complete_dest_paths_generator);
7395 #endif
7396
7397   return matches;
7398 }
7399 ";
7400
7401 (* Generate the POD documentation for guestfish. *)
7402 and generate_fish_actions_pod () =
7403   let all_functions_sorted =
7404     List.filter (
7405       fun (_, _, _, flags, _, _, _) ->
7406         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7407     ) all_functions_sorted in
7408
7409   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7410
7411   List.iter (
7412     fun (name, style, _, flags, _, _, longdesc) ->
7413       let longdesc =
7414         Str.global_substitute rex (
7415           fun s ->
7416             let sub =
7417               try Str.matched_group 1 s
7418               with Not_found ->
7419                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7420             "C<" ^ replace_char sub '_' '-' ^ ">"
7421         ) longdesc in
7422       let name = 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       pr "=head2 %s" name;
7428       if name <> alias then
7429         pr " | %s" alias;
7430       pr "\n";
7431       pr "\n";
7432       pr " %s" name;
7433       List.iter (
7434         function
7435         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7436         | OptString n -> pr " %s" n
7437         | StringList n | DeviceList n -> pr " '%s ...'" n
7438         | Bool _ -> pr " true|false"
7439         | Int n -> pr " %s" n
7440         | Int64 n -> pr " %s" n
7441         | FileIn n | FileOut n -> pr " (%s|-)" n
7442       ) (snd style);
7443       pr "\n";
7444       pr "\n";
7445       pr "%s\n\n" longdesc;
7446
7447       if List.exists (function FileIn _ | FileOut _ -> true
7448                       | _ -> false) (snd style) then
7449         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7450
7451       if List.mem ProtocolLimitWarning flags then
7452         pr "%s\n\n" protocol_limit_warning;
7453
7454       if List.mem DangerWillRobinson flags then
7455         pr "%s\n\n" danger_will_robinson;
7456
7457       match deprecation_notice flags with
7458       | None -> ()
7459       | Some txt -> pr "%s\n\n" txt
7460   ) all_functions_sorted
7461
7462 (* Generate a C function prototype. *)
7463 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7464     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7465     ?(prefix = "")
7466     ?handle name style =
7467   if extern then pr "extern ";
7468   if static then pr "static ";
7469   (match fst style with
7470    | RErr -> pr "int "
7471    | RInt _ -> pr "int "
7472    | RInt64 _ -> pr "int64_t "
7473    | RBool _ -> pr "int "
7474    | RConstString _ | RConstOptString _ -> pr "const char *"
7475    | RString _ | RBufferOut _ -> pr "char *"
7476    | RStringList _ | RHashtable _ -> pr "char **"
7477    | RStruct (_, typ) ->
7478        if not in_daemon then pr "struct guestfs_%s *" typ
7479        else pr "guestfs_int_%s *" typ
7480    | RStructList (_, typ) ->
7481        if not in_daemon then pr "struct guestfs_%s_list *" typ
7482        else pr "guestfs_int_%s_list *" typ
7483   );
7484   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7485   pr "%s%s (" prefix name;
7486   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7487     pr "void"
7488   else (
7489     let comma = ref false in
7490     (match handle with
7491      | None -> ()
7492      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7493     );
7494     let next () =
7495       if !comma then (
7496         if single_line then pr ", " else pr ",\n\t\t"
7497       );
7498       comma := true
7499     in
7500     List.iter (
7501       function
7502       | Pathname n
7503       | Device n | Dev_or_Path n
7504       | String n
7505       | OptString n ->
7506           next ();
7507           pr "const char *%s" n
7508       | StringList n | DeviceList n ->
7509           next ();
7510           pr "char *const *%s" n
7511       | Bool n -> next (); pr "int %s" n
7512       | Int n -> next (); pr "int %s" n
7513       | Int64 n -> next (); pr "int64_t %s" n
7514       | FileIn n
7515       | FileOut n ->
7516           if not in_daemon then (next (); pr "const char *%s" n)
7517     ) (snd style);
7518     if is_RBufferOut then (next (); pr "size_t *size_r");
7519   );
7520   pr ")";
7521   if semicolon then pr ";";
7522   if newline then pr "\n"
7523
7524 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7525 and generate_c_call_args ?handle ?(decl = false) style =
7526   pr "(";
7527   let comma = ref false in
7528   let next () =
7529     if !comma then pr ", ";
7530     comma := true
7531   in
7532   (match handle with
7533    | None -> ()
7534    | Some handle -> pr "%s" handle; comma := true
7535   );
7536   List.iter (
7537     fun arg ->
7538       next ();
7539       pr "%s" (name_of_argt arg)
7540   ) (snd style);
7541   (* For RBufferOut calls, add implicit &size parameter. *)
7542   if not decl then (
7543     match fst style with
7544     | RBufferOut _ ->
7545         next ();
7546         pr "&size"
7547     | _ -> ()
7548   );
7549   pr ")"
7550
7551 (* Generate the OCaml bindings interface. *)
7552 and generate_ocaml_mli () =
7553   generate_header OCamlStyle LGPLv2plus;
7554
7555   pr "\
7556 (** For API documentation you should refer to the C API
7557     in the guestfs(3) manual page.  The OCaml API uses almost
7558     exactly the same calls. *)
7559
7560 type t
7561 (** A [guestfs_h] handle. *)
7562
7563 exception Error of string
7564 (** This exception is raised when there is an error. *)
7565
7566 exception Handle_closed of string
7567 (** This exception is raised if you use a {!Guestfs.t} handle
7568     after calling {!close} on it.  The string is the name of
7569     the function. *)
7570
7571 val create : unit -> t
7572 (** Create a {!Guestfs.t} handle. *)
7573
7574 val close : t -> unit
7575 (** Close the {!Guestfs.t} handle and free up all resources used
7576     by it immediately.
7577
7578     Handles are closed by the garbage collector when they become
7579     unreferenced, but callers can call this in order to provide
7580     predictable cleanup. *)
7581
7582 ";
7583   generate_ocaml_structure_decls ();
7584
7585   (* The actions. *)
7586   List.iter (
7587     fun (name, style, _, _, _, shortdesc, _) ->
7588       generate_ocaml_prototype name style;
7589       pr "(** %s *)\n" shortdesc;
7590       pr "\n"
7591   ) all_functions_sorted
7592
7593 (* Generate the OCaml bindings implementation. *)
7594 and generate_ocaml_ml () =
7595   generate_header OCamlStyle LGPLv2plus;
7596
7597   pr "\
7598 type t
7599
7600 exception Error of string
7601 exception Handle_closed of string
7602
7603 external create : unit -> t = \"ocaml_guestfs_create\"
7604 external close : t -> unit = \"ocaml_guestfs_close\"
7605
7606 (* Give the exceptions names, so they can be raised from the C code. *)
7607 let () =
7608   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7609   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7610
7611 ";
7612
7613   generate_ocaml_structure_decls ();
7614
7615   (* The actions. *)
7616   List.iter (
7617     fun (name, style, _, _, _, shortdesc, _) ->
7618       generate_ocaml_prototype ~is_external:true name style;
7619   ) all_functions_sorted
7620
7621 (* Generate the OCaml bindings C implementation. *)
7622 and generate_ocaml_c () =
7623   generate_header CStyle LGPLv2plus;
7624
7625   pr "\
7626 #include <stdio.h>
7627 #include <stdlib.h>
7628 #include <string.h>
7629
7630 #include <caml/config.h>
7631 #include <caml/alloc.h>
7632 #include <caml/callback.h>
7633 #include <caml/fail.h>
7634 #include <caml/memory.h>
7635 #include <caml/mlvalues.h>
7636 #include <caml/signals.h>
7637
7638 #include <guestfs.h>
7639
7640 #include \"guestfs_c.h\"
7641
7642 /* Copy a hashtable of string pairs into an assoc-list.  We return
7643  * the list in reverse order, but hashtables aren't supposed to be
7644  * ordered anyway.
7645  */
7646 static CAMLprim value
7647 copy_table (char * const * argv)
7648 {
7649   CAMLparam0 ();
7650   CAMLlocal5 (rv, pairv, kv, vv, cons);
7651   int i;
7652
7653   rv = Val_int (0);
7654   for (i = 0; argv[i] != NULL; i += 2) {
7655     kv = caml_copy_string (argv[i]);
7656     vv = caml_copy_string (argv[i+1]);
7657     pairv = caml_alloc (2, 0);
7658     Store_field (pairv, 0, kv);
7659     Store_field (pairv, 1, vv);
7660     cons = caml_alloc (2, 0);
7661     Store_field (cons, 1, rv);
7662     rv = cons;
7663     Store_field (cons, 0, pairv);
7664   }
7665
7666   CAMLreturn (rv);
7667 }
7668
7669 ";
7670
7671   (* Struct copy functions. *)
7672
7673   let emit_ocaml_copy_list_function typ =
7674     pr "static CAMLprim value\n";
7675     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7676     pr "{\n";
7677     pr "  CAMLparam0 ();\n";
7678     pr "  CAMLlocal2 (rv, v);\n";
7679     pr "  unsigned int i;\n";
7680     pr "\n";
7681     pr "  if (%ss->len == 0)\n" typ;
7682     pr "    CAMLreturn (Atom (0));\n";
7683     pr "  else {\n";
7684     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7685     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7686     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7687     pr "      caml_modify (&Field (rv, i), v);\n";
7688     pr "    }\n";
7689     pr "    CAMLreturn (rv);\n";
7690     pr "  }\n";
7691     pr "}\n";
7692     pr "\n";
7693   in
7694
7695   List.iter (
7696     fun (typ, cols) ->
7697       let has_optpercent_col =
7698         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7699
7700       pr "static CAMLprim value\n";
7701       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7702       pr "{\n";
7703       pr "  CAMLparam0 ();\n";
7704       if has_optpercent_col then
7705         pr "  CAMLlocal3 (rv, v, v2);\n"
7706       else
7707         pr "  CAMLlocal2 (rv, v);\n";
7708       pr "\n";
7709       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7710       iteri (
7711         fun i col ->
7712           (match col with
7713            | name, FString ->
7714                pr "  v = caml_copy_string (%s->%s);\n" typ name
7715            | name, FBuffer ->
7716                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7717                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7718                  typ name typ name
7719            | name, FUUID ->
7720                pr "  v = caml_alloc_string (32);\n";
7721                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7722            | name, (FBytes|FInt64|FUInt64) ->
7723                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7724            | name, (FInt32|FUInt32) ->
7725                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7726            | name, FOptPercent ->
7727                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7728                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7729                pr "    v = caml_alloc (1, 0);\n";
7730                pr "    Store_field (v, 0, v2);\n";
7731                pr "  } else /* None */\n";
7732                pr "    v = Val_int (0);\n";
7733            | name, FChar ->
7734                pr "  v = Val_int (%s->%s);\n" typ name
7735           );
7736           pr "  Store_field (rv, %d, v);\n" i
7737       ) cols;
7738       pr "  CAMLreturn (rv);\n";
7739       pr "}\n";
7740       pr "\n";
7741   ) structs;
7742
7743   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7744   List.iter (
7745     function
7746     | typ, (RStructListOnly | RStructAndList) ->
7747         (* generate the function for typ *)
7748         emit_ocaml_copy_list_function typ
7749     | typ, _ -> () (* empty *)
7750   ) (rstructs_used_by all_functions);
7751
7752   (* The wrappers. *)
7753   List.iter (
7754     fun (name, style, _, _, _, _, _) ->
7755       pr "/* Automatically generated wrapper for function\n";
7756       pr " * ";
7757       generate_ocaml_prototype name style;
7758       pr " */\n";
7759       pr "\n";
7760
7761       let params =
7762         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7763
7764       let needs_extra_vs =
7765         match fst style with RConstOptString _ -> true | _ -> false in
7766
7767       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7768       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7769       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7770       pr "\n";
7771
7772       pr "CAMLprim value\n";
7773       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7774       List.iter (pr ", value %s") (List.tl params);
7775       pr ")\n";
7776       pr "{\n";
7777
7778       (match params with
7779        | [p1; p2; p3; p4; p5] ->
7780            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7781        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7782            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7783            pr "  CAMLxparam%d (%s);\n"
7784              (List.length rest) (String.concat ", " rest)
7785        | ps ->
7786            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7787       );
7788       if not needs_extra_vs then
7789         pr "  CAMLlocal1 (rv);\n"
7790       else
7791         pr "  CAMLlocal3 (rv, v, v2);\n";
7792       pr "\n";
7793
7794       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7795       pr "  if (g == NULL)\n";
7796       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7797       pr "\n";
7798
7799       List.iter (
7800         function
7801         | Pathname n
7802         | Device n | Dev_or_Path n
7803         | String n
7804         | FileIn n
7805         | FileOut n ->
7806             pr "  const char *%s = String_val (%sv);\n" n n
7807         | OptString n ->
7808             pr "  const char *%s =\n" n;
7809             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7810               n n
7811         | StringList n | DeviceList n ->
7812             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7813         | Bool n ->
7814             pr "  int %s = Bool_val (%sv);\n" n n
7815         | Int n ->
7816             pr "  int %s = Int_val (%sv);\n" n n
7817         | Int64 n ->
7818             pr "  int64_t %s = Int64_val (%sv);\n" n n
7819       ) (snd style);
7820       let error_code =
7821         match fst style with
7822         | RErr -> pr "  int r;\n"; "-1"
7823         | RInt _ -> pr "  int r;\n"; "-1"
7824         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7825         | RBool _ -> pr "  int r;\n"; "-1"
7826         | RConstString _ | RConstOptString _ ->
7827             pr "  const char *r;\n"; "NULL"
7828         | RString _ -> pr "  char *r;\n"; "NULL"
7829         | RStringList _ ->
7830             pr "  int i;\n";
7831             pr "  char **r;\n";
7832             "NULL"
7833         | RStruct (_, typ) ->
7834             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7835         | RStructList (_, typ) ->
7836             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7837         | RHashtable _ ->
7838             pr "  int i;\n";
7839             pr "  char **r;\n";
7840             "NULL"
7841         | RBufferOut _ ->
7842             pr "  char *r;\n";
7843             pr "  size_t size;\n";
7844             "NULL" in
7845       pr "\n";
7846
7847       pr "  caml_enter_blocking_section ();\n";
7848       pr "  r = guestfs_%s " name;
7849       generate_c_call_args ~handle:"g" style;
7850       pr ";\n";
7851       pr "  caml_leave_blocking_section ();\n";
7852
7853       List.iter (
7854         function
7855         | StringList n | DeviceList n ->
7856             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7857         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7858         | Bool _ | Int _ | Int64 _
7859         | FileIn _ | FileOut _ -> ()
7860       ) (snd style);
7861
7862       pr "  if (r == %s)\n" error_code;
7863       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7864       pr "\n";
7865
7866       (match fst style with
7867        | RErr -> pr "  rv = Val_unit;\n"
7868        | RInt _ -> pr "  rv = Val_int (r);\n"
7869        | RInt64 _ ->
7870            pr "  rv = caml_copy_int64 (r);\n"
7871        | RBool _ -> pr "  rv = Val_bool (r);\n"
7872        | RConstString _ ->
7873            pr "  rv = caml_copy_string (r);\n"
7874        | RConstOptString _ ->
7875            pr "  if (r) { /* Some string */\n";
7876            pr "    v = caml_alloc (1, 0);\n";
7877            pr "    v2 = caml_copy_string (r);\n";
7878            pr "    Store_field (v, 0, v2);\n";
7879            pr "  } else /* None */\n";
7880            pr "    v = Val_int (0);\n";
7881        | RString _ ->
7882            pr "  rv = caml_copy_string (r);\n";
7883            pr "  free (r);\n"
7884        | RStringList _ ->
7885            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7886            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7887            pr "  free (r);\n"
7888        | RStruct (_, typ) ->
7889            pr "  rv = copy_%s (r);\n" typ;
7890            pr "  guestfs_free_%s (r);\n" typ;
7891        | RStructList (_, typ) ->
7892            pr "  rv = copy_%s_list (r);\n" typ;
7893            pr "  guestfs_free_%s_list (r);\n" typ;
7894        | RHashtable _ ->
7895            pr "  rv = copy_table (r);\n";
7896            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7897            pr "  free (r);\n";
7898        | RBufferOut _ ->
7899            pr "  rv = caml_alloc_string (size);\n";
7900            pr "  memcpy (String_val (rv), r, size);\n";
7901       );
7902
7903       pr "  CAMLreturn (rv);\n";
7904       pr "}\n";
7905       pr "\n";
7906
7907       if List.length params > 5 then (
7908         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7909         pr "CAMLprim value ";
7910         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7911         pr "CAMLprim value\n";
7912         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7913         pr "{\n";
7914         pr "  return ocaml_guestfs_%s (argv[0]" name;
7915         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7916         pr ");\n";
7917         pr "}\n";
7918         pr "\n"
7919       )
7920   ) all_functions_sorted
7921
7922 and generate_ocaml_structure_decls () =
7923   List.iter (
7924     fun (typ, cols) ->
7925       pr "type %s = {\n" typ;
7926       List.iter (
7927         function
7928         | name, FString -> pr "  %s : string;\n" name
7929         | name, FBuffer -> pr "  %s : string;\n" name
7930         | name, FUUID -> pr "  %s : string;\n" name
7931         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7932         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7933         | name, FChar -> pr "  %s : char;\n" name
7934         | name, FOptPercent -> pr "  %s : float option;\n" name
7935       ) cols;
7936       pr "}\n";
7937       pr "\n"
7938   ) structs
7939
7940 and generate_ocaml_prototype ?(is_external = false) name style =
7941   if is_external then pr "external " else pr "val ";
7942   pr "%s : t -> " name;
7943   List.iter (
7944     function
7945     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7946     | OptString _ -> pr "string option -> "
7947     | StringList _ | DeviceList _ -> pr "string array -> "
7948     | Bool _ -> pr "bool -> "
7949     | Int _ -> pr "int -> "
7950     | Int64 _ -> pr "int64 -> "
7951   ) (snd style);
7952   (match fst style with
7953    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7954    | RInt _ -> pr "int"
7955    | RInt64 _ -> pr "int64"
7956    | RBool _ -> pr "bool"
7957    | RConstString _ -> pr "string"
7958    | RConstOptString _ -> pr "string option"
7959    | RString _ | RBufferOut _ -> pr "string"
7960    | RStringList _ -> pr "string array"
7961    | RStruct (_, typ) -> pr "%s" typ
7962    | RStructList (_, typ) -> pr "%s array" typ
7963    | RHashtable _ -> pr "(string * string) list"
7964   );
7965   if is_external then (
7966     pr " = ";
7967     if List.length (snd style) + 1 > 5 then
7968       pr "\"ocaml_guestfs_%s_byte\" " name;
7969     pr "\"ocaml_guestfs_%s\"" name
7970   );
7971   pr "\n"
7972
7973 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7974 and generate_perl_xs () =
7975   generate_header CStyle LGPLv2plus;
7976
7977   pr "\
7978 #include \"EXTERN.h\"
7979 #include \"perl.h\"
7980 #include \"XSUB.h\"
7981
7982 #include <guestfs.h>
7983
7984 #ifndef PRId64
7985 #define PRId64 \"lld\"
7986 #endif
7987
7988 static SV *
7989 my_newSVll(long long val) {
7990 #ifdef USE_64_BIT_ALL
7991   return newSViv(val);
7992 #else
7993   char buf[100];
7994   int len;
7995   len = snprintf(buf, 100, \"%%\" PRId64, val);
7996   return newSVpv(buf, len);
7997 #endif
7998 }
7999
8000 #ifndef PRIu64
8001 #define PRIu64 \"llu\"
8002 #endif
8003
8004 static SV *
8005 my_newSVull(unsigned long long val) {
8006 #ifdef USE_64_BIT_ALL
8007   return newSVuv(val);
8008 #else
8009   char buf[100];
8010   int len;
8011   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8012   return newSVpv(buf, len);
8013 #endif
8014 }
8015
8016 /* http://www.perlmonks.org/?node_id=680842 */
8017 static char **
8018 XS_unpack_charPtrPtr (SV *arg) {
8019   char **ret;
8020   AV *av;
8021   I32 i;
8022
8023   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8024     croak (\"array reference expected\");
8025
8026   av = (AV *)SvRV (arg);
8027   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8028   if (!ret)
8029     croak (\"malloc failed\");
8030
8031   for (i = 0; i <= av_len (av); i++) {
8032     SV **elem = av_fetch (av, i, 0);
8033
8034     if (!elem || !*elem)
8035       croak (\"missing element in list\");
8036
8037     ret[i] = SvPV_nolen (*elem);
8038   }
8039
8040   ret[i] = NULL;
8041
8042   return ret;
8043 }
8044
8045 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8046
8047 PROTOTYPES: ENABLE
8048
8049 guestfs_h *
8050 _create ()
8051    CODE:
8052       RETVAL = guestfs_create ();
8053       if (!RETVAL)
8054         croak (\"could not create guestfs handle\");
8055       guestfs_set_error_handler (RETVAL, NULL, NULL);
8056  OUTPUT:
8057       RETVAL
8058
8059 void
8060 DESTROY (g)
8061       guestfs_h *g;
8062  PPCODE:
8063       guestfs_close (g);
8064
8065 ";
8066
8067   List.iter (
8068     fun (name, style, _, _, _, _, _) ->
8069       (match fst style with
8070        | RErr -> pr "void\n"
8071        | RInt _ -> pr "SV *\n"
8072        | RInt64 _ -> pr "SV *\n"
8073        | RBool _ -> pr "SV *\n"
8074        | RConstString _ -> pr "SV *\n"
8075        | RConstOptString _ -> pr "SV *\n"
8076        | RString _ -> pr "SV *\n"
8077        | RBufferOut _ -> pr "SV *\n"
8078        | RStringList _
8079        | RStruct _ | RStructList _
8080        | RHashtable _ ->
8081            pr "void\n" (* all lists returned implictly on the stack *)
8082       );
8083       (* Call and arguments. *)
8084       pr "%s " name;
8085       generate_c_call_args ~handle:"g" ~decl:true style;
8086       pr "\n";
8087       pr "      guestfs_h *g;\n";
8088       iteri (
8089         fun i ->
8090           function
8091           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8092               pr "      char *%s;\n" n
8093           | OptString n ->
8094               (* http://www.perlmonks.org/?node_id=554277
8095                * Note that the implicit handle argument means we have
8096                * to add 1 to the ST(x) operator.
8097                *)
8098               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8099           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8100           | Bool n -> pr "      int %s;\n" n
8101           | Int n -> pr "      int %s;\n" n
8102           | Int64 n -> pr "      int64_t %s;\n" n
8103       ) (snd style);
8104
8105       let do_cleanups () =
8106         List.iter (
8107           function
8108           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8109           | Bool _ | Int _ | Int64 _
8110           | FileIn _ | FileOut _ -> ()
8111           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8112         ) (snd style)
8113       in
8114
8115       (* Code. *)
8116       (match fst style with
8117        | RErr ->
8118            pr "PREINIT:\n";
8119            pr "      int r;\n";
8120            pr " PPCODE:\n";
8121            pr "      r = guestfs_%s " name;
8122            generate_c_call_args ~handle:"g" style;
8123            pr ";\n";
8124            do_cleanups ();
8125            pr "      if (r == -1)\n";
8126            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8127        | RInt n
8128        | RBool n ->
8129            pr "PREINIT:\n";
8130            pr "      int %s;\n" n;
8131            pr "   CODE:\n";
8132            pr "      %s = guestfs_%s " n name;
8133            generate_c_call_args ~handle:"g" style;
8134            pr ";\n";
8135            do_cleanups ();
8136            pr "      if (%s == -1)\n" n;
8137            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8138            pr "      RETVAL = newSViv (%s);\n" n;
8139            pr " OUTPUT:\n";
8140            pr "      RETVAL\n"
8141        | RInt64 n ->
8142            pr "PREINIT:\n";
8143            pr "      int64_t %s;\n" n;
8144            pr "   CODE:\n";
8145            pr "      %s = guestfs_%s " n name;
8146            generate_c_call_args ~handle:"g" style;
8147            pr ";\n";
8148            do_cleanups ();
8149            pr "      if (%s == -1)\n" n;
8150            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8151            pr "      RETVAL = my_newSVll (%s);\n" n;
8152            pr " OUTPUT:\n";
8153            pr "      RETVAL\n"
8154        | RConstString n ->
8155            pr "PREINIT:\n";
8156            pr "      const char *%s;\n" n;
8157            pr "   CODE:\n";
8158            pr "      %s = guestfs_%s " n name;
8159            generate_c_call_args ~handle:"g" style;
8160            pr ";\n";
8161            do_cleanups ();
8162            pr "      if (%s == NULL)\n" n;
8163            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8164            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8165            pr " OUTPUT:\n";
8166            pr "      RETVAL\n"
8167        | RConstOptString n ->
8168            pr "PREINIT:\n";
8169            pr "      const char *%s;\n" n;
8170            pr "   CODE:\n";
8171            pr "      %s = guestfs_%s " n name;
8172            generate_c_call_args ~handle:"g" style;
8173            pr ";\n";
8174            do_cleanups ();
8175            pr "      if (%s == NULL)\n" n;
8176            pr "        RETVAL = &PL_sv_undef;\n";
8177            pr "      else\n";
8178            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8179            pr " OUTPUT:\n";
8180            pr "      RETVAL\n"
8181        | RString n ->
8182            pr "PREINIT:\n";
8183            pr "      char *%s;\n" n;
8184            pr "   CODE:\n";
8185            pr "      %s = guestfs_%s " n name;
8186            generate_c_call_args ~handle:"g" style;
8187            pr ";\n";
8188            do_cleanups ();
8189            pr "      if (%s == NULL)\n" n;
8190            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8191            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8192            pr "      free (%s);\n" n;
8193            pr " OUTPUT:\n";
8194            pr "      RETVAL\n"
8195        | RStringList n | RHashtable n ->
8196            pr "PREINIT:\n";
8197            pr "      char **%s;\n" n;
8198            pr "      int i, n;\n";
8199            pr " PPCODE:\n";
8200            pr "      %s = guestfs_%s " n name;
8201            generate_c_call_args ~handle:"g" style;
8202            pr ";\n";
8203            do_cleanups ();
8204            pr "      if (%s == NULL)\n" n;
8205            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8206            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8207            pr "      EXTEND (SP, n);\n";
8208            pr "      for (i = 0; i < n; ++i) {\n";
8209            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8210            pr "        free (%s[i]);\n" n;
8211            pr "      }\n";
8212            pr "      free (%s);\n" n;
8213        | RStruct (n, typ) ->
8214            let cols = cols_of_struct typ in
8215            generate_perl_struct_code typ cols name style n do_cleanups
8216        | RStructList (n, typ) ->
8217            let cols = cols_of_struct typ in
8218            generate_perl_struct_list_code typ cols name style n do_cleanups
8219        | RBufferOut n ->
8220            pr "PREINIT:\n";
8221            pr "      char *%s;\n" n;
8222            pr "      size_t size;\n";
8223            pr "   CODE:\n";
8224            pr "      %s = guestfs_%s " n name;
8225            generate_c_call_args ~handle:"g" style;
8226            pr ";\n";
8227            do_cleanups ();
8228            pr "      if (%s == NULL)\n" n;
8229            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8230            pr "      RETVAL = newSVpv (%s, size);\n" n;
8231            pr "      free (%s);\n" n;
8232            pr " OUTPUT:\n";
8233            pr "      RETVAL\n"
8234       );
8235
8236       pr "\n"
8237   ) all_functions
8238
8239 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8240   pr "PREINIT:\n";
8241   pr "      struct guestfs_%s_list *%s;\n" typ n;
8242   pr "      int i;\n";
8243   pr "      HV *hv;\n";
8244   pr " PPCODE:\n";
8245   pr "      %s = guestfs_%s " n name;
8246   generate_c_call_args ~handle:"g" style;
8247   pr ";\n";
8248   do_cleanups ();
8249   pr "      if (%s == NULL)\n" n;
8250   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8251   pr "      EXTEND (SP, %s->len);\n" n;
8252   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8253   pr "        hv = newHV ();\n";
8254   List.iter (
8255     function
8256     | name, FString ->
8257         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8258           name (String.length name) n name
8259     | name, FUUID ->
8260         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8261           name (String.length name) n name
8262     | name, FBuffer ->
8263         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8264           name (String.length name) n name n name
8265     | name, (FBytes|FUInt64) ->
8266         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8267           name (String.length name) n name
8268     | name, FInt64 ->
8269         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8270           name (String.length name) n name
8271     | name, (FInt32|FUInt32) ->
8272         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8273           name (String.length name) n name
8274     | name, FChar ->
8275         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8276           name (String.length name) n name
8277     | name, FOptPercent ->
8278         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8279           name (String.length name) n name
8280   ) cols;
8281   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8282   pr "      }\n";
8283   pr "      guestfs_free_%s_list (%s);\n" typ n
8284
8285 and generate_perl_struct_code typ cols name style n do_cleanups =
8286   pr "PREINIT:\n";
8287   pr "      struct guestfs_%s *%s;\n" typ n;
8288   pr " PPCODE:\n";
8289   pr "      %s = guestfs_%s " n name;
8290   generate_c_call_args ~handle:"g" style;
8291   pr ";\n";
8292   do_cleanups ();
8293   pr "      if (%s == NULL)\n" n;
8294   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8295   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8296   List.iter (
8297     fun ((name, _) as col) ->
8298       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8299
8300       match col with
8301       | name, FString ->
8302           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8303             n name
8304       | name, FBuffer ->
8305           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8306             n name n name
8307       | name, FUUID ->
8308           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8309             n name
8310       | name, (FBytes|FUInt64) ->
8311           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8312             n name
8313       | name, FInt64 ->
8314           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8315             n name
8316       | name, (FInt32|FUInt32) ->
8317           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8318             n name
8319       | name, FChar ->
8320           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8321             n name
8322       | name, FOptPercent ->
8323           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8324             n name
8325   ) cols;
8326   pr "      free (%s);\n" n
8327
8328 (* Generate Sys/Guestfs.pm. *)
8329 and generate_perl_pm () =
8330   generate_header HashStyle LGPLv2plus;
8331
8332   pr "\
8333 =pod
8334
8335 =head1 NAME
8336
8337 Sys::Guestfs - Perl bindings for libguestfs
8338
8339 =head1 SYNOPSIS
8340
8341  use Sys::Guestfs;
8342
8343  my $h = Sys::Guestfs->new ();
8344  $h->add_drive ('guest.img');
8345  $h->launch ();
8346  $h->mount ('/dev/sda1', '/');
8347  $h->touch ('/hello');
8348  $h->sync ();
8349
8350 =head1 DESCRIPTION
8351
8352 The C<Sys::Guestfs> module provides a Perl XS binding to the
8353 libguestfs API for examining and modifying virtual machine
8354 disk images.
8355
8356 Amongst the things this is good for: making batch configuration
8357 changes to guests, getting disk used/free statistics (see also:
8358 virt-df), migrating between virtualization systems (see also:
8359 virt-p2v), performing partial backups, performing partial guest
8360 clones, cloning guests and changing registry/UUID/hostname info, and
8361 much else besides.
8362
8363 Libguestfs uses Linux kernel and qemu code, and can access any type of
8364 guest filesystem that Linux and qemu can, including but not limited
8365 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8366 schemes, qcow, qcow2, vmdk.
8367
8368 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8369 LVs, what filesystem is in each LV, etc.).  It can also run commands
8370 in the context of the guest.  Also you can access filesystems over FTP.
8371
8372 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8373 functions for using libguestfs from Perl, including integration
8374 with libvirt.
8375
8376 =head1 ERRORS
8377
8378 All errors turn into calls to C<croak> (see L<Carp(3)>).
8379
8380 =head1 METHODS
8381
8382 =over 4
8383
8384 =cut
8385
8386 package Sys::Guestfs;
8387
8388 use strict;
8389 use warnings;
8390
8391 require XSLoader;
8392 XSLoader::load ('Sys::Guestfs');
8393
8394 =item $h = Sys::Guestfs->new ();
8395
8396 Create a new guestfs handle.
8397
8398 =cut
8399
8400 sub new {
8401   my $proto = shift;
8402   my $class = ref ($proto) || $proto;
8403
8404   my $self = Sys::Guestfs::_create ();
8405   bless $self, $class;
8406   return $self;
8407 }
8408
8409 ";
8410
8411   (* Actions.  We only need to print documentation for these as
8412    * they are pulled in from the XS code automatically.
8413    *)
8414   List.iter (
8415     fun (name, style, _, flags, _, _, longdesc) ->
8416       if not (List.mem NotInDocs flags) then (
8417         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8418         pr "=item ";
8419         generate_perl_prototype name style;
8420         pr "\n\n";
8421         pr "%s\n\n" longdesc;
8422         if List.mem ProtocolLimitWarning flags then
8423           pr "%s\n\n" protocol_limit_warning;
8424         if List.mem DangerWillRobinson flags then
8425           pr "%s\n\n" danger_will_robinson;
8426         match deprecation_notice flags with
8427         | None -> ()
8428         | Some txt -> pr "%s\n\n" txt
8429       )
8430   ) all_functions_sorted;
8431
8432   (* End of file. *)
8433   pr "\
8434 =cut
8435
8436 1;
8437
8438 =back
8439
8440 =head1 COPYRIGHT
8441
8442 Copyright (C) %s Red Hat Inc.
8443
8444 =head1 LICENSE
8445
8446 Please see the file COPYING.LIB for the full license.
8447
8448 =head1 SEE ALSO
8449
8450 L<guestfs(3)>,
8451 L<guestfish(1)>,
8452 L<http://libguestfs.org>,
8453 L<Sys::Guestfs::Lib(3)>.
8454
8455 =cut
8456 " copyright_years
8457
8458 and generate_perl_prototype name style =
8459   (match fst style with
8460    | RErr -> ()
8461    | RBool n
8462    | RInt n
8463    | RInt64 n
8464    | RConstString n
8465    | RConstOptString n
8466    | RString n
8467    | RBufferOut n -> pr "$%s = " n
8468    | RStruct (n,_)
8469    | RHashtable n -> pr "%%%s = " n
8470    | RStringList n
8471    | RStructList (n,_) -> pr "@%s = " n
8472   );
8473   pr "$h->%s (" name;
8474   let comma = ref false in
8475   List.iter (
8476     fun arg ->
8477       if !comma then pr ", ";
8478       comma := true;
8479       match arg with
8480       | Pathname n | Device n | Dev_or_Path n | String n
8481       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8482           pr "$%s" n
8483       | StringList n | DeviceList n ->
8484           pr "\\@%s" n
8485   ) (snd style);
8486   pr ");"
8487
8488 (* Generate Python C module. *)
8489 and generate_python_c () =
8490   generate_header CStyle LGPLv2plus;
8491
8492   pr "\
8493 #include <Python.h>
8494
8495 #include <stdio.h>
8496 #include <stdlib.h>
8497 #include <assert.h>
8498
8499 #include \"guestfs.h\"
8500
8501 typedef struct {
8502   PyObject_HEAD
8503   guestfs_h *g;
8504 } Pyguestfs_Object;
8505
8506 static guestfs_h *
8507 get_handle (PyObject *obj)
8508 {
8509   assert (obj);
8510   assert (obj != Py_None);
8511   return ((Pyguestfs_Object *) obj)->g;
8512 }
8513
8514 static PyObject *
8515 put_handle (guestfs_h *g)
8516 {
8517   assert (g);
8518   return
8519     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8520 }
8521
8522 /* This list should be freed (but not the strings) after use. */
8523 static char **
8524 get_string_list (PyObject *obj)
8525 {
8526   int i, len;
8527   char **r;
8528
8529   assert (obj);
8530
8531   if (!PyList_Check (obj)) {
8532     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8533     return NULL;
8534   }
8535
8536   len = PyList_Size (obj);
8537   r = malloc (sizeof (char *) * (len+1));
8538   if (r == NULL) {
8539     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8540     return NULL;
8541   }
8542
8543   for (i = 0; i < len; ++i)
8544     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8545   r[len] = NULL;
8546
8547   return r;
8548 }
8549
8550 static PyObject *
8551 put_string_list (char * const * const argv)
8552 {
8553   PyObject *list;
8554   int argc, i;
8555
8556   for (argc = 0; argv[argc] != NULL; ++argc)
8557     ;
8558
8559   list = PyList_New (argc);
8560   for (i = 0; i < argc; ++i)
8561     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8562
8563   return list;
8564 }
8565
8566 static PyObject *
8567 put_table (char * const * const argv)
8568 {
8569   PyObject *list, *item;
8570   int argc, i;
8571
8572   for (argc = 0; argv[argc] != NULL; ++argc)
8573     ;
8574
8575   list = PyList_New (argc >> 1);
8576   for (i = 0; i < argc; i += 2) {
8577     item = PyTuple_New (2);
8578     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8579     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8580     PyList_SetItem (list, i >> 1, item);
8581   }
8582
8583   return list;
8584 }
8585
8586 static void
8587 free_strings (char **argv)
8588 {
8589   int argc;
8590
8591   for (argc = 0; argv[argc] != NULL; ++argc)
8592     free (argv[argc]);
8593   free (argv);
8594 }
8595
8596 static PyObject *
8597 py_guestfs_create (PyObject *self, PyObject *args)
8598 {
8599   guestfs_h *g;
8600
8601   g = guestfs_create ();
8602   if (g == NULL) {
8603     PyErr_SetString (PyExc_RuntimeError,
8604                      \"guestfs.create: failed to allocate handle\");
8605     return NULL;
8606   }
8607   guestfs_set_error_handler (g, NULL, NULL);
8608   return put_handle (g);
8609 }
8610
8611 static PyObject *
8612 py_guestfs_close (PyObject *self, PyObject *args)
8613 {
8614   PyObject *py_g;
8615   guestfs_h *g;
8616
8617   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8618     return NULL;
8619   g = get_handle (py_g);
8620
8621   guestfs_close (g);
8622
8623   Py_INCREF (Py_None);
8624   return Py_None;
8625 }
8626
8627 ";
8628
8629   let emit_put_list_function typ =
8630     pr "static PyObject *\n";
8631     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8632     pr "{\n";
8633     pr "  PyObject *list;\n";
8634     pr "  int i;\n";
8635     pr "\n";
8636     pr "  list = PyList_New (%ss->len);\n" typ;
8637     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8638     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8639     pr "  return list;\n";
8640     pr "};\n";
8641     pr "\n"
8642   in
8643
8644   (* Structures, turned into Python dictionaries. *)
8645   List.iter (
8646     fun (typ, cols) ->
8647       pr "static PyObject *\n";
8648       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8649       pr "{\n";
8650       pr "  PyObject *dict;\n";
8651       pr "\n";
8652       pr "  dict = PyDict_New ();\n";
8653       List.iter (
8654         function
8655         | name, FString ->
8656             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8657             pr "                        PyString_FromString (%s->%s));\n"
8658               typ name
8659         | name, FBuffer ->
8660             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8661             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8662               typ name typ name
8663         | name, FUUID ->
8664             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8665             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8666               typ name
8667         | name, (FBytes|FUInt64) ->
8668             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8669             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8670               typ name
8671         | name, FInt64 ->
8672             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8673             pr "                        PyLong_FromLongLong (%s->%s));\n"
8674               typ name
8675         | name, FUInt32 ->
8676             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8677             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8678               typ name
8679         | name, FInt32 ->
8680             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8681             pr "                        PyLong_FromLong (%s->%s));\n"
8682               typ name
8683         | name, FOptPercent ->
8684             pr "  if (%s->%s >= 0)\n" typ name;
8685             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8686             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8687               typ name;
8688             pr "  else {\n";
8689             pr "    Py_INCREF (Py_None);\n";
8690             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8691             pr "  }\n"
8692         | name, FChar ->
8693             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8694             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8695       ) cols;
8696       pr "  return dict;\n";
8697       pr "};\n";
8698       pr "\n";
8699
8700   ) structs;
8701
8702   (* Emit a put_TYPE_list function definition only if that function is used. *)
8703   List.iter (
8704     function
8705     | typ, (RStructListOnly | RStructAndList) ->
8706         (* generate the function for typ *)
8707         emit_put_list_function typ
8708     | typ, _ -> () (* empty *)
8709   ) (rstructs_used_by all_functions);
8710
8711   (* Python wrapper functions. *)
8712   List.iter (
8713     fun (name, style, _, _, _, _, _) ->
8714       pr "static PyObject *\n";
8715       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8716       pr "{\n";
8717
8718       pr "  PyObject *py_g;\n";
8719       pr "  guestfs_h *g;\n";
8720       pr "  PyObject *py_r;\n";
8721
8722       let error_code =
8723         match fst style with
8724         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8725         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8726         | RConstString _ | RConstOptString _ ->
8727             pr "  const char *r;\n"; "NULL"
8728         | RString _ -> pr "  char *r;\n"; "NULL"
8729         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8730         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8731         | RStructList (_, typ) ->
8732             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8733         | RBufferOut _ ->
8734             pr "  char *r;\n";
8735             pr "  size_t size;\n";
8736             "NULL" in
8737
8738       List.iter (
8739         function
8740         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8741             pr "  const char *%s;\n" n
8742         | OptString n -> pr "  const char *%s;\n" n
8743         | StringList n | DeviceList n ->
8744             pr "  PyObject *py_%s;\n" n;
8745             pr "  char **%s;\n" n
8746         | Bool n -> pr "  int %s;\n" n
8747         | Int n -> pr "  int %s;\n" n
8748         | Int64 n -> pr "  long long %s;\n" n
8749       ) (snd style);
8750
8751       pr "\n";
8752
8753       (* Convert the parameters. *)
8754       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8755       List.iter (
8756         function
8757         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8758         | OptString _ -> pr "z"
8759         | StringList _ | DeviceList _ -> pr "O"
8760         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8761         | Int _ -> pr "i"
8762         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8763                              * emulate C's int/long/long long in Python?
8764                              *)
8765       ) (snd style);
8766       pr ":guestfs_%s\",\n" name;
8767       pr "                         &py_g";
8768       List.iter (
8769         function
8770         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8771         | OptString n -> pr ", &%s" n
8772         | StringList n | DeviceList n -> pr ", &py_%s" n
8773         | Bool n -> pr ", &%s" n
8774         | Int n -> pr ", &%s" n
8775         | Int64 n -> pr ", &%s" n
8776       ) (snd style);
8777
8778       pr "))\n";
8779       pr "    return NULL;\n";
8780
8781       pr "  g = get_handle (py_g);\n";
8782       List.iter (
8783         function
8784         | Pathname _ | Device _ | Dev_or_Path _ | String _
8785         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8786         | StringList n | DeviceList n ->
8787             pr "  %s = get_string_list (py_%s);\n" n n;
8788             pr "  if (!%s) return NULL;\n" n
8789       ) (snd style);
8790
8791       pr "\n";
8792
8793       pr "  r = guestfs_%s " name;
8794       generate_c_call_args ~handle:"g" style;
8795       pr ";\n";
8796
8797       List.iter (
8798         function
8799         | Pathname _ | Device _ | Dev_or_Path _ | String _
8800         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8801         | StringList n | DeviceList n ->
8802             pr "  free (%s);\n" n
8803       ) (snd style);
8804
8805       pr "  if (r == %s) {\n" error_code;
8806       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8807       pr "    return NULL;\n";
8808       pr "  }\n";
8809       pr "\n";
8810
8811       (match fst style with
8812        | RErr ->
8813            pr "  Py_INCREF (Py_None);\n";
8814            pr "  py_r = Py_None;\n"
8815        | RInt _
8816        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8817        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8818        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8819        | RConstOptString _ ->
8820            pr "  if (r)\n";
8821            pr "    py_r = PyString_FromString (r);\n";
8822            pr "  else {\n";
8823            pr "    Py_INCREF (Py_None);\n";
8824            pr "    py_r = Py_None;\n";
8825            pr "  }\n"
8826        | RString _ ->
8827            pr "  py_r = PyString_FromString (r);\n";
8828            pr "  free (r);\n"
8829        | RStringList _ ->
8830            pr "  py_r = put_string_list (r);\n";
8831            pr "  free_strings (r);\n"
8832        | RStruct (_, typ) ->
8833            pr "  py_r = put_%s (r);\n" typ;
8834            pr "  guestfs_free_%s (r);\n" typ
8835        | RStructList (_, typ) ->
8836            pr "  py_r = put_%s_list (r);\n" typ;
8837            pr "  guestfs_free_%s_list (r);\n" typ
8838        | RHashtable n ->
8839            pr "  py_r = put_table (r);\n";
8840            pr "  free_strings (r);\n"
8841        | RBufferOut _ ->
8842            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8843            pr "  free (r);\n"
8844       );
8845
8846       pr "  return py_r;\n";
8847       pr "}\n";
8848       pr "\n"
8849   ) all_functions;
8850
8851   (* Table of functions. *)
8852   pr "static PyMethodDef methods[] = {\n";
8853   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8854   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8855   List.iter (
8856     fun (name, _, _, _, _, _, _) ->
8857       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8858         name name
8859   ) all_functions;
8860   pr "  { NULL, NULL, 0, NULL }\n";
8861   pr "};\n";
8862   pr "\n";
8863
8864   (* Init function. *)
8865   pr "\
8866 void
8867 initlibguestfsmod (void)
8868 {
8869   static int initialized = 0;
8870
8871   if (initialized) return;
8872   Py_InitModule ((char *) \"libguestfsmod\", methods);
8873   initialized = 1;
8874 }
8875 "
8876
8877 (* Generate Python module. *)
8878 and generate_python_py () =
8879   generate_header HashStyle LGPLv2plus;
8880
8881   pr "\
8882 u\"\"\"Python bindings for libguestfs
8883
8884 import guestfs
8885 g = guestfs.GuestFS ()
8886 g.add_drive (\"guest.img\")
8887 g.launch ()
8888 parts = g.list_partitions ()
8889
8890 The guestfs module provides a Python binding to the libguestfs API
8891 for examining and modifying virtual machine disk images.
8892
8893 Amongst the things this is good for: making batch configuration
8894 changes to guests, getting disk used/free statistics (see also:
8895 virt-df), migrating between virtualization systems (see also:
8896 virt-p2v), performing partial backups, performing partial guest
8897 clones, cloning guests and changing registry/UUID/hostname info, and
8898 much else besides.
8899
8900 Libguestfs uses Linux kernel and qemu code, and can access any type of
8901 guest filesystem that Linux and qemu can, including but not limited
8902 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8903 schemes, qcow, qcow2, vmdk.
8904
8905 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8906 LVs, what filesystem is in each LV, etc.).  It can also run commands
8907 in the context of the guest.  Also you can access filesystems over FTP.
8908
8909 Errors which happen while using the API are turned into Python
8910 RuntimeError exceptions.
8911
8912 To create a guestfs handle you usually have to perform the following
8913 sequence of calls:
8914
8915 # Create the handle, call add_drive at least once, and possibly
8916 # several times if the guest has multiple block devices:
8917 g = guestfs.GuestFS ()
8918 g.add_drive (\"guest.img\")
8919
8920 # Launch the qemu subprocess and wait for it to become ready:
8921 g.launch ()
8922
8923 # Now you can issue commands, for example:
8924 logvols = g.lvs ()
8925
8926 \"\"\"
8927
8928 import libguestfsmod
8929
8930 class GuestFS:
8931     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8932
8933     def __init__ (self):
8934         \"\"\"Create a new libguestfs handle.\"\"\"
8935         self._o = libguestfsmod.create ()
8936
8937     def __del__ (self):
8938         libguestfsmod.close (self._o)
8939
8940 ";
8941
8942   List.iter (
8943     fun (name, style, _, flags, _, _, longdesc) ->
8944       pr "    def %s " name;
8945       generate_py_call_args ~handle:"self" (snd style);
8946       pr ":\n";
8947
8948       if not (List.mem NotInDocs flags) then (
8949         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8950         let doc =
8951           match fst style with
8952           | RErr | RInt _ | RInt64 _ | RBool _
8953           | RConstOptString _ | RConstString _
8954           | RString _ | RBufferOut _ -> doc
8955           | RStringList _ ->
8956               doc ^ "\n\nThis function returns a list of strings."
8957           | RStruct (_, typ) ->
8958               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8959           | RStructList (_, typ) ->
8960               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8961           | RHashtable _ ->
8962               doc ^ "\n\nThis function returns a dictionary." in
8963         let doc =
8964           if List.mem ProtocolLimitWarning flags then
8965             doc ^ "\n\n" ^ protocol_limit_warning
8966           else doc in
8967         let doc =
8968           if List.mem DangerWillRobinson flags then
8969             doc ^ "\n\n" ^ danger_will_robinson
8970           else doc in
8971         let doc =
8972           match deprecation_notice flags with
8973           | None -> doc
8974           | Some txt -> doc ^ "\n\n" ^ txt in
8975         let doc = pod2text ~width:60 name doc in
8976         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8977         let doc = String.concat "\n        " doc in
8978         pr "        u\"\"\"%s\"\"\"\n" doc;
8979       );
8980       pr "        return libguestfsmod.%s " name;
8981       generate_py_call_args ~handle:"self._o" (snd style);
8982       pr "\n";
8983       pr "\n";
8984   ) all_functions
8985
8986 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8987 and generate_py_call_args ~handle args =
8988   pr "(%s" handle;
8989   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8990   pr ")"
8991
8992 (* Useful if you need the longdesc POD text as plain text.  Returns a
8993  * list of lines.
8994  *
8995  * Because this is very slow (the slowest part of autogeneration),
8996  * we memoize the results.
8997  *)
8998 and pod2text ~width name longdesc =
8999   let key = width, name, longdesc in
9000   try Hashtbl.find pod2text_memo key
9001   with Not_found ->
9002     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9003     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9004     close_out chan;
9005     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9006     let chan = open_process_in cmd in
9007     let lines = ref [] in
9008     let rec loop i =
9009       let line = input_line chan in
9010       if i = 1 then             (* discard the first line of output *)
9011         loop (i+1)
9012       else (
9013         let line = triml line in
9014         lines := line :: !lines;
9015         loop (i+1)
9016       ) in
9017     let lines = try loop 1 with End_of_file -> List.rev !lines in
9018     unlink filename;
9019     (match close_process_in chan with
9020      | WEXITED 0 -> ()
9021      | WEXITED i ->
9022          failwithf "pod2text: process exited with non-zero status (%d)" i
9023      | WSIGNALED i | WSTOPPED i ->
9024          failwithf "pod2text: process signalled or stopped by signal %d" i
9025     );
9026     Hashtbl.add pod2text_memo key lines;
9027     pod2text_memo_updated ();
9028     lines
9029
9030 (* Generate ruby bindings. *)
9031 and generate_ruby_c () =
9032   generate_header CStyle LGPLv2plus;
9033
9034   pr "\
9035 #include <stdio.h>
9036 #include <stdlib.h>
9037
9038 #include <ruby.h>
9039
9040 #include \"guestfs.h\"
9041
9042 #include \"extconf.h\"
9043
9044 /* For Ruby < 1.9 */
9045 #ifndef RARRAY_LEN
9046 #define RARRAY_LEN(r) (RARRAY((r))->len)
9047 #endif
9048
9049 static VALUE m_guestfs;                 /* guestfs module */
9050 static VALUE c_guestfs;                 /* guestfs_h handle */
9051 static VALUE e_Error;                   /* used for all errors */
9052
9053 static void ruby_guestfs_free (void *p)
9054 {
9055   if (!p) return;
9056   guestfs_close ((guestfs_h *) p);
9057 }
9058
9059 static VALUE ruby_guestfs_create (VALUE m)
9060 {
9061   guestfs_h *g;
9062
9063   g = guestfs_create ();
9064   if (!g)
9065     rb_raise (e_Error, \"failed to create guestfs handle\");
9066
9067   /* Don't print error messages to stderr by default. */
9068   guestfs_set_error_handler (g, NULL, NULL);
9069
9070   /* Wrap it, and make sure the close function is called when the
9071    * handle goes away.
9072    */
9073   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9074 }
9075
9076 static VALUE ruby_guestfs_close (VALUE gv)
9077 {
9078   guestfs_h *g;
9079   Data_Get_Struct (gv, guestfs_h, g);
9080
9081   ruby_guestfs_free (g);
9082   DATA_PTR (gv) = NULL;
9083
9084   return Qnil;
9085 }
9086
9087 ";
9088
9089   List.iter (
9090     fun (name, style, _, _, _, _, _) ->
9091       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9092       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9093       pr ")\n";
9094       pr "{\n";
9095       pr "  guestfs_h *g;\n";
9096       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9097       pr "  if (!g)\n";
9098       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9099         name;
9100       pr "\n";
9101
9102       List.iter (
9103         function
9104         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9105             pr "  Check_Type (%sv, T_STRING);\n" n;
9106             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9107             pr "  if (!%s)\n" n;
9108             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9109             pr "              \"%s\", \"%s\");\n" n name
9110         | OptString n ->
9111             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9112         | StringList n | DeviceList n ->
9113             pr "  char **%s;\n" n;
9114             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9115             pr "  {\n";
9116             pr "    int i, len;\n";
9117             pr "    len = RARRAY_LEN (%sv);\n" n;
9118             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9119               n;
9120             pr "    for (i = 0; i < len; ++i) {\n";
9121             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9122             pr "      %s[i] = StringValueCStr (v);\n" n;
9123             pr "    }\n";
9124             pr "    %s[len] = NULL;\n" n;
9125             pr "  }\n";
9126         | Bool n ->
9127             pr "  int %s = RTEST (%sv);\n" n n
9128         | Int n ->
9129             pr "  int %s = NUM2INT (%sv);\n" n n
9130         | Int64 n ->
9131             pr "  long long %s = NUM2LL (%sv);\n" n n
9132       ) (snd style);
9133       pr "\n";
9134
9135       let error_code =
9136         match fst style with
9137         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9138         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9139         | RConstString _ | RConstOptString _ ->
9140             pr "  const char *r;\n"; "NULL"
9141         | RString _ -> pr "  char *r;\n"; "NULL"
9142         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9143         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9144         | RStructList (_, typ) ->
9145             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9146         | RBufferOut _ ->
9147             pr "  char *r;\n";
9148             pr "  size_t size;\n";
9149             "NULL" in
9150       pr "\n";
9151
9152       pr "  r = guestfs_%s " name;
9153       generate_c_call_args ~handle:"g" style;
9154       pr ";\n";
9155
9156       List.iter (
9157         function
9158         | Pathname _ | Device _ | Dev_or_Path _ | String _
9159         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9160         | StringList n | DeviceList n ->
9161             pr "  free (%s);\n" n
9162       ) (snd style);
9163
9164       pr "  if (r == %s)\n" error_code;
9165       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9166       pr "\n";
9167
9168       (match fst style with
9169        | RErr ->
9170            pr "  return Qnil;\n"
9171        | RInt _ | RBool _ ->
9172            pr "  return INT2NUM (r);\n"
9173        | RInt64 _ ->
9174            pr "  return ULL2NUM (r);\n"
9175        | RConstString _ ->
9176            pr "  return rb_str_new2 (r);\n";
9177        | RConstOptString _ ->
9178            pr "  if (r)\n";
9179            pr "    return rb_str_new2 (r);\n";
9180            pr "  else\n";
9181            pr "    return Qnil;\n";
9182        | RString _ ->
9183            pr "  VALUE rv = rb_str_new2 (r);\n";
9184            pr "  free (r);\n";
9185            pr "  return rv;\n";
9186        | RStringList _ ->
9187            pr "  int i, len = 0;\n";
9188            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9189            pr "  VALUE rv = rb_ary_new2 (len);\n";
9190            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9191            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9192            pr "    free (r[i]);\n";
9193            pr "  }\n";
9194            pr "  free (r);\n";
9195            pr "  return rv;\n"
9196        | RStruct (_, typ) ->
9197            let cols = cols_of_struct typ in
9198            generate_ruby_struct_code typ cols
9199        | RStructList (_, typ) ->
9200            let cols = cols_of_struct typ in
9201            generate_ruby_struct_list_code typ cols
9202        | RHashtable _ ->
9203            pr "  VALUE rv = rb_hash_new ();\n";
9204            pr "  int i;\n";
9205            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9206            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9207            pr "    free (r[i]);\n";
9208            pr "    free (r[i+1]);\n";
9209            pr "  }\n";
9210            pr "  free (r);\n";
9211            pr "  return rv;\n"
9212        | RBufferOut _ ->
9213            pr "  VALUE rv = rb_str_new (r, size);\n";
9214            pr "  free (r);\n";
9215            pr "  return rv;\n";
9216       );
9217
9218       pr "}\n";
9219       pr "\n"
9220   ) all_functions;
9221
9222   pr "\
9223 /* Initialize the module. */
9224 void Init__guestfs ()
9225 {
9226   m_guestfs = rb_define_module (\"Guestfs\");
9227   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9228   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9229
9230   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9231   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9232
9233 ";
9234   (* Define the rest of the methods. *)
9235   List.iter (
9236     fun (name, style, _, _, _, _, _) ->
9237       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9238       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9239   ) all_functions;
9240
9241   pr "}\n"
9242
9243 (* Ruby code to return a struct. *)
9244 and generate_ruby_struct_code typ cols =
9245   pr "  VALUE rv = rb_hash_new ();\n";
9246   List.iter (
9247     function
9248     | name, FString ->
9249         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9250     | name, FBuffer ->
9251         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9252     | name, FUUID ->
9253         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9254     | name, (FBytes|FUInt64) ->
9255         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9256     | name, FInt64 ->
9257         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9258     | name, FUInt32 ->
9259         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9260     | name, FInt32 ->
9261         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9262     | name, FOptPercent ->
9263         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9264     | name, FChar -> (* XXX wrong? *)
9265         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9266   ) cols;
9267   pr "  guestfs_free_%s (r);\n" typ;
9268   pr "  return rv;\n"
9269
9270 (* Ruby code to return a struct list. *)
9271 and generate_ruby_struct_list_code typ cols =
9272   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9273   pr "  int i;\n";
9274   pr "  for (i = 0; i < r->len; ++i) {\n";
9275   pr "    VALUE hv = rb_hash_new ();\n";
9276   List.iter (
9277     function
9278     | name, FString ->
9279         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9280     | name, FBuffer ->
9281         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
9282     | name, FUUID ->
9283         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9284     | name, (FBytes|FUInt64) ->
9285         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9286     | name, FInt64 ->
9287         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9288     | name, FUInt32 ->
9289         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9290     | name, FInt32 ->
9291         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9292     | name, FOptPercent ->
9293         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9294     | name, FChar -> (* XXX wrong? *)
9295         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9296   ) cols;
9297   pr "    rb_ary_push (rv, hv);\n";
9298   pr "  }\n";
9299   pr "  guestfs_free_%s_list (r);\n" typ;
9300   pr "  return rv;\n"
9301
9302 (* Generate Java bindings GuestFS.java file. *)
9303 and generate_java_java () =
9304   generate_header CStyle LGPLv2plus;
9305
9306   pr "\
9307 package com.redhat.et.libguestfs;
9308
9309 import java.util.HashMap;
9310 import com.redhat.et.libguestfs.LibGuestFSException;
9311 import com.redhat.et.libguestfs.PV;
9312 import com.redhat.et.libguestfs.VG;
9313 import com.redhat.et.libguestfs.LV;
9314 import com.redhat.et.libguestfs.Stat;
9315 import com.redhat.et.libguestfs.StatVFS;
9316 import com.redhat.et.libguestfs.IntBool;
9317 import com.redhat.et.libguestfs.Dirent;
9318
9319 /**
9320  * The GuestFS object is a libguestfs handle.
9321  *
9322  * @author rjones
9323  */
9324 public class GuestFS {
9325   // Load the native code.
9326   static {
9327     System.loadLibrary (\"guestfs_jni\");
9328   }
9329
9330   /**
9331    * The native guestfs_h pointer.
9332    */
9333   long g;
9334
9335   /**
9336    * Create a libguestfs handle.
9337    *
9338    * @throws LibGuestFSException
9339    */
9340   public GuestFS () throws LibGuestFSException
9341   {
9342     g = _create ();
9343   }
9344   private native long _create () throws LibGuestFSException;
9345
9346   /**
9347    * Close a libguestfs handle.
9348    *
9349    * You can also leave handles to be collected by the garbage
9350    * collector, but this method ensures that the resources used
9351    * by the handle are freed up immediately.  If you call any
9352    * other methods after closing the handle, you will get an
9353    * exception.
9354    *
9355    * @throws LibGuestFSException
9356    */
9357   public void close () throws LibGuestFSException
9358   {
9359     if (g != 0)
9360       _close (g);
9361     g = 0;
9362   }
9363   private native void _close (long g) throws LibGuestFSException;
9364
9365   public void finalize () throws LibGuestFSException
9366   {
9367     close ();
9368   }
9369
9370 ";
9371
9372   List.iter (
9373     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9374       if not (List.mem NotInDocs flags); then (
9375         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9376         let doc =
9377           if List.mem ProtocolLimitWarning flags then
9378             doc ^ "\n\n" ^ protocol_limit_warning
9379           else doc in
9380         let doc =
9381           if List.mem DangerWillRobinson flags then
9382             doc ^ "\n\n" ^ danger_will_robinson
9383           else doc in
9384         let doc =
9385           match deprecation_notice flags with
9386           | None -> doc
9387           | Some txt -> doc ^ "\n\n" ^ txt in
9388         let doc = pod2text ~width:60 name doc in
9389         let doc = List.map (            (* RHBZ#501883 *)
9390           function
9391           | "" -> "<p>"
9392           | nonempty -> nonempty
9393         ) doc in
9394         let doc = String.concat "\n   * " doc in
9395
9396         pr "  /**\n";
9397         pr "   * %s\n" shortdesc;
9398         pr "   * <p>\n";
9399         pr "   * %s\n" doc;
9400         pr "   * @throws LibGuestFSException\n";
9401         pr "   */\n";
9402         pr "  ";
9403       );
9404       generate_java_prototype ~public:true ~semicolon:false name style;
9405       pr "\n";
9406       pr "  {\n";
9407       pr "    if (g == 0)\n";
9408       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9409         name;
9410       pr "    ";
9411       if fst style <> RErr then pr "return ";
9412       pr "_%s " name;
9413       generate_java_call_args ~handle:"g" (snd style);
9414       pr ";\n";
9415       pr "  }\n";
9416       pr "  ";
9417       generate_java_prototype ~privat:true ~native:true name style;
9418       pr "\n";
9419       pr "\n";
9420   ) all_functions;
9421
9422   pr "}\n"
9423
9424 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9425 and generate_java_call_args ~handle args =
9426   pr "(%s" handle;
9427   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9428   pr ")"
9429
9430 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9431     ?(semicolon=true) name style =
9432   if privat then pr "private ";
9433   if public then pr "public ";
9434   if native then pr "native ";
9435
9436   (* return type *)
9437   (match fst style with
9438    | RErr -> pr "void ";
9439    | RInt _ -> pr "int ";
9440    | RInt64 _ -> pr "long ";
9441    | RBool _ -> pr "boolean ";
9442    | RConstString _ | RConstOptString _ | RString _
9443    | RBufferOut _ -> pr "String ";
9444    | RStringList _ -> pr "String[] ";
9445    | RStruct (_, typ) ->
9446        let name = java_name_of_struct typ in
9447        pr "%s " name;
9448    | RStructList (_, typ) ->
9449        let name = java_name_of_struct typ in
9450        pr "%s[] " name;
9451    | RHashtable _ -> pr "HashMap<String,String> ";
9452   );
9453
9454   if native then pr "_%s " name else pr "%s " name;
9455   pr "(";
9456   let needs_comma = ref false in
9457   if native then (
9458     pr "long g";
9459     needs_comma := true
9460   );
9461
9462   (* args *)
9463   List.iter (
9464     fun arg ->
9465       if !needs_comma then pr ", ";
9466       needs_comma := true;
9467
9468       match arg with
9469       | Pathname n
9470       | Device n | Dev_or_Path n
9471       | String n
9472       | OptString n
9473       | FileIn n
9474       | FileOut n ->
9475           pr "String %s" n
9476       | StringList n | DeviceList n ->
9477           pr "String[] %s" n
9478       | Bool n ->
9479           pr "boolean %s" n
9480       | Int n ->
9481           pr "int %s" n
9482       | Int64 n ->
9483           pr "long %s" n
9484   ) (snd style);
9485
9486   pr ")\n";
9487   pr "    throws LibGuestFSException";
9488   if semicolon then pr ";"
9489
9490 and generate_java_struct jtyp cols () =
9491   generate_header CStyle LGPLv2plus;
9492
9493   pr "\
9494 package com.redhat.et.libguestfs;
9495
9496 /**
9497  * Libguestfs %s structure.
9498  *
9499  * @author rjones
9500  * @see GuestFS
9501  */
9502 public class %s {
9503 " jtyp jtyp;
9504
9505   List.iter (
9506     function
9507     | name, FString
9508     | name, FUUID
9509     | name, FBuffer -> pr "  public String %s;\n" name
9510     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9511     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9512     | name, FChar -> pr "  public char %s;\n" name
9513     | name, FOptPercent ->
9514         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9515         pr "  public float %s;\n" name
9516   ) cols;
9517
9518   pr "}\n"
9519
9520 and generate_java_c () =
9521   generate_header CStyle LGPLv2plus;
9522
9523   pr "\
9524 #include <stdio.h>
9525 #include <stdlib.h>
9526 #include <string.h>
9527
9528 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9529 #include \"guestfs.h\"
9530
9531 /* Note that this function returns.  The exception is not thrown
9532  * until after the wrapper function returns.
9533  */
9534 static void
9535 throw_exception (JNIEnv *env, const char *msg)
9536 {
9537   jclass cl;
9538   cl = (*env)->FindClass (env,
9539                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9540   (*env)->ThrowNew (env, cl, msg);
9541 }
9542
9543 JNIEXPORT jlong JNICALL
9544 Java_com_redhat_et_libguestfs_GuestFS__1create
9545   (JNIEnv *env, jobject obj)
9546 {
9547   guestfs_h *g;
9548
9549   g = guestfs_create ();
9550   if (g == NULL) {
9551     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9552     return 0;
9553   }
9554   guestfs_set_error_handler (g, NULL, NULL);
9555   return (jlong) (long) g;
9556 }
9557
9558 JNIEXPORT void JNICALL
9559 Java_com_redhat_et_libguestfs_GuestFS__1close
9560   (JNIEnv *env, jobject obj, jlong jg)
9561 {
9562   guestfs_h *g = (guestfs_h *) (long) jg;
9563   guestfs_close (g);
9564 }
9565
9566 ";
9567
9568   List.iter (
9569     fun (name, style, _, _, _, _, _) ->
9570       pr "JNIEXPORT ";
9571       (match fst style with
9572        | RErr -> pr "void ";
9573        | RInt _ -> pr "jint ";
9574        | RInt64 _ -> pr "jlong ";
9575        | RBool _ -> pr "jboolean ";
9576        | RConstString _ | RConstOptString _ | RString _
9577        | RBufferOut _ -> pr "jstring ";
9578        | RStruct _ | RHashtable _ ->
9579            pr "jobject ";
9580        | RStringList _ | RStructList _ ->
9581            pr "jobjectArray ";
9582       );
9583       pr "JNICALL\n";
9584       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9585       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9586       pr "\n";
9587       pr "  (JNIEnv *env, jobject obj, jlong jg";
9588       List.iter (
9589         function
9590         | Pathname n
9591         | Device n | Dev_or_Path n
9592         | String n
9593         | OptString n
9594         | FileIn n
9595         | FileOut n ->
9596             pr ", jstring j%s" n
9597         | StringList n | DeviceList n ->
9598             pr ", jobjectArray j%s" n
9599         | Bool n ->
9600             pr ", jboolean j%s" n
9601         | Int n ->
9602             pr ", jint j%s" n
9603         | Int64 n ->
9604             pr ", jlong j%s" n
9605       ) (snd style);
9606       pr ")\n";
9607       pr "{\n";
9608       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9609       let error_code, no_ret =
9610         match fst style with
9611         | RErr -> pr "  int r;\n"; "-1", ""
9612         | RBool _
9613         | RInt _ -> pr "  int r;\n"; "-1", "0"
9614         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9615         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9616         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9617         | RString _ ->
9618             pr "  jstring jr;\n";
9619             pr "  char *r;\n"; "NULL", "NULL"
9620         | RStringList _ ->
9621             pr "  jobjectArray jr;\n";
9622             pr "  int r_len;\n";
9623             pr "  jclass cl;\n";
9624             pr "  jstring jstr;\n";
9625             pr "  char **r;\n"; "NULL", "NULL"
9626         | RStruct (_, typ) ->
9627             pr "  jobject jr;\n";
9628             pr "  jclass cl;\n";
9629             pr "  jfieldID fl;\n";
9630             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9631         | RStructList (_, typ) ->
9632             pr "  jobjectArray jr;\n";
9633             pr "  jclass cl;\n";
9634             pr "  jfieldID fl;\n";
9635             pr "  jobject jfl;\n";
9636             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9637         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9638         | RBufferOut _ ->
9639             pr "  jstring jr;\n";
9640             pr "  char *r;\n";
9641             pr "  size_t size;\n";
9642             "NULL", "NULL" in
9643       List.iter (
9644         function
9645         | Pathname n
9646         | Device n | Dev_or_Path n
9647         | String n
9648         | OptString n
9649         | FileIn n
9650         | FileOut n ->
9651             pr "  const char *%s;\n" n
9652         | StringList n | DeviceList n ->
9653             pr "  int %s_len;\n" n;
9654             pr "  const char **%s;\n" n
9655         | Bool n
9656         | Int n ->
9657             pr "  int %s;\n" n
9658         | Int64 n ->
9659             pr "  int64_t %s;\n" n
9660       ) (snd style);
9661
9662       let needs_i =
9663         (match fst style with
9664          | RStringList _ | RStructList _ -> true
9665          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9666          | RConstOptString _
9667          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9668           List.exists (function
9669                        | StringList _ -> true
9670                        | DeviceList _ -> true
9671                        | _ -> false) (snd style) in
9672       if needs_i then
9673         pr "  int i;\n";
9674
9675       pr "\n";
9676
9677       (* Get the parameters. *)
9678       List.iter (
9679         function
9680         | Pathname n
9681         | Device n | Dev_or_Path n
9682         | String n
9683         | FileIn n
9684         | FileOut n ->
9685             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9686         | OptString n ->
9687             (* This is completely undocumented, but Java null becomes
9688              * a NULL parameter.
9689              *)
9690             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9691         | StringList n | DeviceList n ->
9692             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9693             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9694             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9695             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9696               n;
9697             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9698             pr "  }\n";
9699             pr "  %s[%s_len] = NULL;\n" n n;
9700         | Bool n
9701         | Int n
9702         | Int64 n ->
9703             pr "  %s = j%s;\n" n n
9704       ) (snd style);
9705
9706       (* Make the call. *)
9707       pr "  r = guestfs_%s " name;
9708       generate_c_call_args ~handle:"g" style;
9709       pr ";\n";
9710
9711       (* Release the parameters. *)
9712       List.iter (
9713         function
9714         | Pathname n
9715         | Device n | Dev_or_Path n
9716         | String n
9717         | FileIn n
9718         | FileOut n ->
9719             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9720         | OptString n ->
9721             pr "  if (j%s)\n" n;
9722             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9723         | StringList n | DeviceList n ->
9724             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9725             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9726               n;
9727             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9728             pr "  }\n";
9729             pr "  free (%s);\n" n
9730         | Bool n
9731         | Int n
9732         | Int64 n -> ()
9733       ) (snd style);
9734
9735       (* Check for errors. *)
9736       pr "  if (r == %s) {\n" error_code;
9737       pr "    throw_exception (env, guestfs_last_error (g));\n";
9738       pr "    return %s;\n" no_ret;
9739       pr "  }\n";
9740
9741       (* Return value. *)
9742       (match fst style with
9743        | RErr -> ()
9744        | RInt _ -> pr "  return (jint) r;\n"
9745        | RBool _ -> pr "  return (jboolean) r;\n"
9746        | RInt64 _ -> pr "  return (jlong) r;\n"
9747        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9748        | RConstOptString _ ->
9749            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9750        | RString _ ->
9751            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9752            pr "  free (r);\n";
9753            pr "  return jr;\n"
9754        | RStringList _ ->
9755            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9756            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9757            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9758            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9759            pr "  for (i = 0; i < r_len; ++i) {\n";
9760            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9761            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9762            pr "    free (r[i]);\n";
9763            pr "  }\n";
9764            pr "  free (r);\n";
9765            pr "  return jr;\n"
9766        | RStruct (_, typ) ->
9767            let jtyp = java_name_of_struct typ in
9768            let cols = cols_of_struct typ in
9769            generate_java_struct_return typ jtyp cols
9770        | RStructList (_, typ) ->
9771            let jtyp = java_name_of_struct typ in
9772            let cols = cols_of_struct typ in
9773            generate_java_struct_list_return typ jtyp cols
9774        | RHashtable _ ->
9775            (* XXX *)
9776            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9777            pr "  return NULL;\n"
9778        | RBufferOut _ ->
9779            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9780            pr "  free (r);\n";
9781            pr "  return jr;\n"
9782       );
9783
9784       pr "}\n";
9785       pr "\n"
9786   ) all_functions
9787
9788 and generate_java_struct_return typ jtyp cols =
9789   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9790   pr "  jr = (*env)->AllocObject (env, cl);\n";
9791   List.iter (
9792     function
9793     | name, FString ->
9794         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9795         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9796     | name, FUUID ->
9797         pr "  {\n";
9798         pr "    char s[33];\n";
9799         pr "    memcpy (s, r->%s, 32);\n" name;
9800         pr "    s[32] = 0;\n";
9801         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9802         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9803         pr "  }\n";
9804     | name, FBuffer ->
9805         pr "  {\n";
9806         pr "    int len = r->%s_len;\n" name;
9807         pr "    char s[len+1];\n";
9808         pr "    memcpy (s, r->%s, len);\n" name;
9809         pr "    s[len] = 0;\n";
9810         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9811         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9812         pr "  }\n";
9813     | name, (FBytes|FUInt64|FInt64) ->
9814         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9815         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9816     | name, (FUInt32|FInt32) ->
9817         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9818         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9819     | name, FOptPercent ->
9820         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9821         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9822     | name, FChar ->
9823         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9824         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9825   ) cols;
9826   pr "  free (r);\n";
9827   pr "  return jr;\n"
9828
9829 and generate_java_struct_list_return typ jtyp cols =
9830   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9831   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9832   pr "  for (i = 0; i < r->len; ++i) {\n";
9833   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9834   List.iter (
9835     function
9836     | name, FString ->
9837         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9838         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9839     | name, FUUID ->
9840         pr "    {\n";
9841         pr "      char s[33];\n";
9842         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9843         pr "      s[32] = 0;\n";
9844         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9845         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9846         pr "    }\n";
9847     | name, FBuffer ->
9848         pr "    {\n";
9849         pr "      int len = r->val[i].%s_len;\n" name;
9850         pr "      char s[len+1];\n";
9851         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9852         pr "      s[len] = 0;\n";
9853         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9854         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9855         pr "    }\n";
9856     | name, (FBytes|FUInt64|FInt64) ->
9857         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9858         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9859     | name, (FUInt32|FInt32) ->
9860         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9861         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9862     | name, FOptPercent ->
9863         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9864         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9865     | name, FChar ->
9866         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9867         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9868   ) cols;
9869   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9870   pr "  }\n";
9871   pr "  guestfs_free_%s_list (r);\n" typ;
9872   pr "  return jr;\n"
9873
9874 and generate_java_makefile_inc () =
9875   generate_header HashStyle GPLv2plus;
9876
9877   pr "java_built_sources = \\\n";
9878   List.iter (
9879     fun (typ, jtyp) ->
9880         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9881   ) java_structs;
9882   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9883
9884 and generate_haskell_hs () =
9885   generate_header HaskellStyle LGPLv2plus;
9886
9887   (* XXX We only know how to generate partial FFI for Haskell
9888    * at the moment.  Please help out!
9889    *)
9890   let can_generate style =
9891     match style with
9892     | RErr, _
9893     | RInt _, _
9894     | RInt64 _, _ -> true
9895     | RBool _, _
9896     | RConstString _, _
9897     | RConstOptString _, _
9898     | RString _, _
9899     | RStringList _, _
9900     | RStruct _, _
9901     | RStructList _, _
9902     | RHashtable _, _
9903     | RBufferOut _, _ -> false in
9904
9905   pr "\
9906 {-# INCLUDE <guestfs.h> #-}
9907 {-# LANGUAGE ForeignFunctionInterface #-}
9908
9909 module Guestfs (
9910   create";
9911
9912   (* List out the names of the actions we want to export. *)
9913   List.iter (
9914     fun (name, style, _, _, _, _, _) ->
9915       if can_generate style then pr ",\n  %s" name
9916   ) all_functions;
9917
9918   pr "
9919   ) where
9920
9921 -- Unfortunately some symbols duplicate ones already present
9922 -- in Prelude.  We don't know which, so we hard-code a list
9923 -- here.
9924 import Prelude hiding (truncate)
9925
9926 import Foreign
9927 import Foreign.C
9928 import Foreign.C.Types
9929 import IO
9930 import Control.Exception
9931 import Data.Typeable
9932
9933 data GuestfsS = GuestfsS            -- represents the opaque C struct
9934 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9935 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9936
9937 -- XXX define properly later XXX
9938 data PV = PV
9939 data VG = VG
9940 data LV = LV
9941 data IntBool = IntBool
9942 data Stat = Stat
9943 data StatVFS = StatVFS
9944 data Hashtable = Hashtable
9945
9946 foreign import ccall unsafe \"guestfs_create\" c_create
9947   :: IO GuestfsP
9948 foreign import ccall unsafe \"&guestfs_close\" c_close
9949   :: FunPtr (GuestfsP -> IO ())
9950 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9951   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9952
9953 create :: IO GuestfsH
9954 create = do
9955   p <- c_create
9956   c_set_error_handler p nullPtr nullPtr
9957   h <- newForeignPtr c_close p
9958   return h
9959
9960 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9961   :: GuestfsP -> IO CString
9962
9963 -- last_error :: GuestfsH -> IO (Maybe String)
9964 -- last_error h = do
9965 --   str <- withForeignPtr h (\\p -> c_last_error p)
9966 --   maybePeek peekCString str
9967
9968 last_error :: GuestfsH -> IO (String)
9969 last_error h = do
9970   str <- withForeignPtr h (\\p -> c_last_error p)
9971   if (str == nullPtr)
9972     then return \"no error\"
9973     else peekCString str
9974
9975 ";
9976
9977   (* Generate wrappers for each foreign function. *)
9978   List.iter (
9979     fun (name, style, _, _, _, _, _) ->
9980       if can_generate style then (
9981         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9982         pr "  :: ";
9983         generate_haskell_prototype ~handle:"GuestfsP" style;
9984         pr "\n";
9985         pr "\n";
9986         pr "%s :: " name;
9987         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9988         pr "\n";
9989         pr "%s %s = do\n" name
9990           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9991         pr "  r <- ";
9992         (* Convert pointer arguments using with* functions. *)
9993         List.iter (
9994           function
9995           | FileIn n
9996           | FileOut n
9997           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9998           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9999           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10000           | Bool _ | Int _ | Int64 _ -> ()
10001         ) (snd style);
10002         (* Convert integer arguments. *)
10003         let args =
10004           List.map (
10005             function
10006             | Bool n -> sprintf "(fromBool %s)" n
10007             | Int n -> sprintf "(fromIntegral %s)" n
10008             | Int64 n -> sprintf "(fromIntegral %s)" n
10009             | FileIn n | FileOut n
10010             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10011           ) (snd style) in
10012         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10013           (String.concat " " ("p" :: args));
10014         (match fst style with
10015          | RErr | RInt _ | RInt64 _ | RBool _ ->
10016              pr "  if (r == -1)\n";
10017              pr "    then do\n";
10018              pr "      err <- last_error h\n";
10019              pr "      fail err\n";
10020          | RConstString _ | RConstOptString _ | RString _
10021          | RStringList _ | RStruct _
10022          | RStructList _ | RHashtable _ | RBufferOut _ ->
10023              pr "  if (r == nullPtr)\n";
10024              pr "    then do\n";
10025              pr "      err <- last_error h\n";
10026              pr "      fail err\n";
10027         );
10028         (match fst style with
10029          | RErr ->
10030              pr "    else return ()\n"
10031          | RInt _ ->
10032              pr "    else return (fromIntegral r)\n"
10033          | RInt64 _ ->
10034              pr "    else return (fromIntegral r)\n"
10035          | RBool _ ->
10036              pr "    else return (toBool r)\n"
10037          | RConstString _
10038          | RConstOptString _
10039          | RString _
10040          | RStringList _
10041          | RStruct _
10042          | RStructList _
10043          | RHashtable _
10044          | RBufferOut _ ->
10045              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10046         );
10047         pr "\n";
10048       )
10049   ) all_functions
10050
10051 and generate_haskell_prototype ~handle ?(hs = false) style =
10052   pr "%s -> " handle;
10053   let string = if hs then "String" else "CString" in
10054   let int = if hs then "Int" else "CInt" in
10055   let bool = if hs then "Bool" else "CInt" in
10056   let int64 = if hs then "Integer" else "Int64" in
10057   List.iter (
10058     fun arg ->
10059       (match arg with
10060        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10061        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10062        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10063        | Bool _ -> pr "%s" bool
10064        | Int _ -> pr "%s" int
10065        | Int64 _ -> pr "%s" int
10066        | FileIn _ -> pr "%s" string
10067        | FileOut _ -> pr "%s" string
10068       );
10069       pr " -> ";
10070   ) (snd style);
10071   pr "IO (";
10072   (match fst style with
10073    | RErr -> if not hs then pr "CInt"
10074    | RInt _ -> pr "%s" int
10075    | RInt64 _ -> pr "%s" int64
10076    | RBool _ -> pr "%s" bool
10077    | RConstString _ -> pr "%s" string
10078    | RConstOptString _ -> pr "Maybe %s" string
10079    | RString _ -> pr "%s" string
10080    | RStringList _ -> pr "[%s]" string
10081    | RStruct (_, typ) ->
10082        let name = java_name_of_struct typ in
10083        pr "%s" name
10084    | RStructList (_, typ) ->
10085        let name = java_name_of_struct typ in
10086        pr "[%s]" name
10087    | RHashtable _ -> pr "Hashtable"
10088    | RBufferOut _ -> pr "%s" string
10089   );
10090   pr ")"
10091
10092 and generate_csharp () =
10093   generate_header CPlusPlusStyle LGPLv2plus;
10094
10095   (* XXX Make this configurable by the C# assembly users. *)
10096   let library = "libguestfs.so.0" in
10097
10098   pr "\
10099 // These C# bindings are highly experimental at present.
10100 //
10101 // Firstly they only work on Linux (ie. Mono).  In order to get them
10102 // to work on Windows (ie. .Net) you would need to port the library
10103 // itself to Windows first.
10104 //
10105 // The second issue is that some calls are known to be incorrect and
10106 // can cause Mono to segfault.  Particularly: calls which pass or
10107 // return string[], or return any structure value.  This is because
10108 // we haven't worked out the correct way to do this from C#.
10109 //
10110 // The third issue is that when compiling you get a lot of warnings.
10111 // We are not sure whether the warnings are important or not.
10112 //
10113 // Fourthly we do not routinely build or test these bindings as part
10114 // of the make && make check cycle, which means that regressions might
10115 // go unnoticed.
10116 //
10117 // Suggestions and patches are welcome.
10118
10119 // To compile:
10120 //
10121 // gmcs Libguestfs.cs
10122 // mono Libguestfs.exe
10123 //
10124 // (You'll probably want to add a Test class / static main function
10125 // otherwise this won't do anything useful).
10126
10127 using System;
10128 using System.IO;
10129 using System.Runtime.InteropServices;
10130 using System.Runtime.Serialization;
10131 using System.Collections;
10132
10133 namespace Guestfs
10134 {
10135   class Error : System.ApplicationException
10136   {
10137     public Error (string message) : base (message) {}
10138     protected Error (SerializationInfo info, StreamingContext context) {}
10139   }
10140
10141   class Guestfs
10142   {
10143     IntPtr _handle;
10144
10145     [DllImport (\"%s\")]
10146     static extern IntPtr guestfs_create ();
10147
10148     public Guestfs ()
10149     {
10150       _handle = guestfs_create ();
10151       if (_handle == IntPtr.Zero)
10152         throw new Error (\"could not create guestfs handle\");
10153     }
10154
10155     [DllImport (\"%s\")]
10156     static extern void guestfs_close (IntPtr h);
10157
10158     ~Guestfs ()
10159     {
10160       guestfs_close (_handle);
10161     }
10162
10163     [DllImport (\"%s\")]
10164     static extern string guestfs_last_error (IntPtr h);
10165
10166 " library library library;
10167
10168   (* Generate C# structure bindings.  We prefix struct names with
10169    * underscore because C# cannot have conflicting struct names and
10170    * method names (eg. "class stat" and "stat").
10171    *)
10172   List.iter (
10173     fun (typ, cols) ->
10174       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10175       pr "    public class _%s {\n" typ;
10176       List.iter (
10177         function
10178         | name, FChar -> pr "      char %s;\n" name
10179         | name, FString -> pr "      string %s;\n" name
10180         | name, FBuffer ->
10181             pr "      uint %s_len;\n" name;
10182             pr "      string %s;\n" name
10183         | name, FUUID ->
10184             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10185             pr "      string %s;\n" name
10186         | name, FUInt32 -> pr "      uint %s;\n" name
10187         | name, FInt32 -> pr "      int %s;\n" name
10188         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10189         | name, FInt64 -> pr "      long %s;\n" name
10190         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10191       ) cols;
10192       pr "    }\n";
10193       pr "\n"
10194   ) structs;
10195
10196   (* Generate C# function bindings. *)
10197   List.iter (
10198     fun (name, style, _, _, _, shortdesc, _) ->
10199       let rec csharp_return_type () =
10200         match fst style with
10201         | RErr -> "void"
10202         | RBool n -> "bool"
10203         | RInt n -> "int"
10204         | RInt64 n -> "long"
10205         | RConstString n
10206         | RConstOptString n
10207         | RString n
10208         | RBufferOut n -> "string"
10209         | RStruct (_,n) -> "_" ^ n
10210         | RHashtable n -> "Hashtable"
10211         | RStringList n -> "string[]"
10212         | RStructList (_,n) -> sprintf "_%s[]" n
10213
10214       and c_return_type () =
10215         match fst style with
10216         | RErr
10217         | RBool _
10218         | RInt _ -> "int"
10219         | RInt64 _ -> "long"
10220         | RConstString _
10221         | RConstOptString _
10222         | RString _
10223         | RBufferOut _ -> "string"
10224         | RStruct (_,n) -> "_" ^ n
10225         | RHashtable _
10226         | RStringList _ -> "string[]"
10227         | RStructList (_,n) -> sprintf "_%s[]" n
10228     
10229       and c_error_comparison () =
10230         match fst style with
10231         | RErr
10232         | RBool _
10233         | RInt _
10234         | RInt64 _ -> "== -1"
10235         | RConstString _
10236         | RConstOptString _
10237         | RString _
10238         | RBufferOut _
10239         | RStruct (_,_)
10240         | RHashtable _
10241         | RStringList _
10242         | RStructList (_,_) -> "== null"
10243     
10244       and generate_extern_prototype () =
10245         pr "    static extern %s guestfs_%s (IntPtr h"
10246           (c_return_type ()) name;
10247         List.iter (
10248           function
10249           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10250           | FileIn n | FileOut n ->
10251               pr ", [In] string %s" n
10252           | StringList n | DeviceList n ->
10253               pr ", [In] string[] %s" n
10254           | Bool n ->
10255               pr ", bool %s" n
10256           | Int n ->
10257               pr ", int %s" n
10258           | Int64 n ->
10259               pr ", long %s" n
10260         ) (snd style);
10261         pr ");\n"
10262
10263       and generate_public_prototype () =
10264         pr "    public %s %s (" (csharp_return_type ()) name;
10265         let comma = ref false in
10266         let next () =
10267           if !comma then pr ", ";
10268           comma := true
10269         in
10270         List.iter (
10271           function
10272           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10273           | FileIn n | FileOut n ->
10274               next (); pr "string %s" n
10275           | StringList n | DeviceList n ->
10276               next (); pr "string[] %s" n
10277           | Bool n ->
10278               next (); pr "bool %s" n
10279           | Int n ->
10280               next (); pr "int %s" n
10281           | Int64 n ->
10282               next (); pr "long %s" n
10283         ) (snd style);
10284         pr ")\n"
10285
10286       and generate_call () =
10287         pr "guestfs_%s (_handle" name;
10288         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10289         pr ");\n";
10290       in
10291
10292       pr "    [DllImport (\"%s\")]\n" library;
10293       generate_extern_prototype ();
10294       pr "\n";
10295       pr "    /// <summary>\n";
10296       pr "    /// %s\n" shortdesc;
10297       pr "    /// </summary>\n";
10298       generate_public_prototype ();
10299       pr "    {\n";
10300       pr "      %s r;\n" (c_return_type ());
10301       pr "      r = ";
10302       generate_call ();
10303       pr "      if (r %s)\n" (c_error_comparison ());
10304       pr "        throw new Error (\"%s: \" + guestfs_last_error (_handle));\n"
10305         name;
10306       (match fst style with
10307        | RErr -> ()
10308        | RBool _ ->
10309            pr "      return r != 0 ? true : false;\n"
10310        | RHashtable _ ->
10311            pr "      Hashtable rr = new Hashtable ();\n";
10312            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10313            pr "        rr.Add (r[i], r[i+1]);\n";
10314            pr "      return rr;\n"
10315        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10316        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10317        | RStructList _ ->
10318            pr "      return r;\n"
10319       );
10320       pr "    }\n";
10321       pr "\n";
10322   ) all_functions_sorted;
10323
10324   pr "  }
10325 }
10326 "
10327
10328 and generate_bindtests () =
10329   generate_header CStyle LGPLv2plus;
10330
10331   pr "\
10332 #include <stdio.h>
10333 #include <stdlib.h>
10334 #include <inttypes.h>
10335 #include <string.h>
10336
10337 #include \"guestfs.h\"
10338 #include \"guestfs-internal.h\"
10339 #include \"guestfs-internal-actions.h\"
10340 #include \"guestfs_protocol.h\"
10341
10342 #define error guestfs_error
10343 #define safe_calloc guestfs_safe_calloc
10344 #define safe_malloc guestfs_safe_malloc
10345
10346 static void
10347 print_strings (char *const *argv)
10348 {
10349   int argc;
10350
10351   printf (\"[\");
10352   for (argc = 0; argv[argc] != NULL; ++argc) {
10353     if (argc > 0) printf (\", \");
10354     printf (\"\\\"%%s\\\"\", argv[argc]);
10355   }
10356   printf (\"]\\n\");
10357 }
10358
10359 /* The test0 function prints its parameters to stdout. */
10360 ";
10361
10362   let test0, tests =
10363     match test_functions with
10364     | [] -> assert false
10365     | test0 :: tests -> test0, tests in
10366
10367   let () =
10368     let (name, style, _, _, _, _, _) = test0 in
10369     generate_prototype ~extern:false ~semicolon:false ~newline:true
10370       ~handle:"g" ~prefix:"guestfs__" name style;
10371     pr "{\n";
10372     List.iter (
10373       function
10374       | Pathname n
10375       | Device n | Dev_or_Path n
10376       | String n
10377       | FileIn n
10378       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10379       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10380       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10381       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10382       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10383       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10384     ) (snd style);
10385     pr "  /* Java changes stdout line buffering so we need this: */\n";
10386     pr "  fflush (stdout);\n";
10387     pr "  return 0;\n";
10388     pr "}\n";
10389     pr "\n" in
10390
10391   List.iter (
10392     fun (name, style, _, _, _, _, _) ->
10393       if String.sub name (String.length name - 3) 3 <> "err" then (
10394         pr "/* Test normal return. */\n";
10395         generate_prototype ~extern:false ~semicolon:false ~newline:true
10396           ~handle:"g" ~prefix:"guestfs__" name style;
10397         pr "{\n";
10398         (match fst style with
10399          | RErr ->
10400              pr "  return 0;\n"
10401          | RInt _ ->
10402              pr "  int r;\n";
10403              pr "  sscanf (val, \"%%d\", &r);\n";
10404              pr "  return r;\n"
10405          | RInt64 _ ->
10406              pr "  int64_t r;\n";
10407              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10408              pr "  return r;\n"
10409          | RBool _ ->
10410              pr "  return STREQ (val, \"true\");\n"
10411          | RConstString _
10412          | RConstOptString _ ->
10413              (* Can't return the input string here.  Return a static
10414               * string so we ensure we get a segfault if the caller
10415               * tries to free it.
10416               *)
10417              pr "  return \"static string\";\n"
10418          | RString _ ->
10419              pr "  return strdup (val);\n"
10420          | RStringList _ ->
10421              pr "  char **strs;\n";
10422              pr "  int n, i;\n";
10423              pr "  sscanf (val, \"%%d\", &n);\n";
10424              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10425              pr "  for (i = 0; i < n; ++i) {\n";
10426              pr "    strs[i] = safe_malloc (g, 16);\n";
10427              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10428              pr "  }\n";
10429              pr "  strs[n] = NULL;\n";
10430              pr "  return strs;\n"
10431          | RStruct (_, typ) ->
10432              pr "  struct guestfs_%s *r;\n" typ;
10433              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10434              pr "  return r;\n"
10435          | RStructList (_, typ) ->
10436              pr "  struct guestfs_%s_list *r;\n" typ;
10437              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10438              pr "  sscanf (val, \"%%d\", &r->len);\n";
10439              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10440              pr "  return r;\n"
10441          | RHashtable _ ->
10442              pr "  char **strs;\n";
10443              pr "  int n, i;\n";
10444              pr "  sscanf (val, \"%%d\", &n);\n";
10445              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10446              pr "  for (i = 0; i < n; ++i) {\n";
10447              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10448              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10449              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10450              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10451              pr "  }\n";
10452              pr "  strs[n*2] = NULL;\n";
10453              pr "  return strs;\n"
10454          | RBufferOut _ ->
10455              pr "  return strdup (val);\n"
10456         );
10457         pr "}\n";
10458         pr "\n"
10459       ) else (
10460         pr "/* Test error return. */\n";
10461         generate_prototype ~extern:false ~semicolon:false ~newline:true
10462           ~handle:"g" ~prefix:"guestfs__" name style;
10463         pr "{\n";
10464         pr "  error (g, \"error\");\n";
10465         (match fst style with
10466          | RErr | RInt _ | RInt64 _ | RBool _ ->
10467              pr "  return -1;\n"
10468          | RConstString _ | RConstOptString _
10469          | RString _ | RStringList _ | RStruct _
10470          | RStructList _
10471          | RHashtable _
10472          | RBufferOut _ ->
10473              pr "  return NULL;\n"
10474         );
10475         pr "}\n";
10476         pr "\n"
10477       )
10478   ) tests
10479
10480 and generate_ocaml_bindtests () =
10481   generate_header OCamlStyle GPLv2plus;
10482
10483   pr "\
10484 let () =
10485   let g = Guestfs.create () in
10486 ";
10487
10488   let mkargs args =
10489     String.concat " " (
10490       List.map (
10491         function
10492         | CallString s -> "\"" ^ s ^ "\""
10493         | CallOptString None -> "None"
10494         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10495         | CallStringList xs ->
10496             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10497         | CallInt i when i >= 0 -> string_of_int i
10498         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10499         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10500         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10501         | CallBool b -> string_of_bool b
10502       ) args
10503     )
10504   in
10505
10506   generate_lang_bindtests (
10507     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10508   );
10509
10510   pr "print_endline \"EOF\"\n"
10511
10512 and generate_perl_bindtests () =
10513   pr "#!/usr/bin/perl -w\n";
10514   generate_header HashStyle GPLv2plus;
10515
10516   pr "\
10517 use strict;
10518
10519 use Sys::Guestfs;
10520
10521 my $g = Sys::Guestfs->new ();
10522 ";
10523
10524   let mkargs args =
10525     String.concat ", " (
10526       List.map (
10527         function
10528         | CallString s -> "\"" ^ s ^ "\""
10529         | CallOptString None -> "undef"
10530         | CallOptString (Some s) -> sprintf "\"%s\"" s
10531         | CallStringList xs ->
10532             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10533         | CallInt i -> string_of_int i
10534         | CallInt64 i -> Int64.to_string i
10535         | CallBool b -> if b then "1" else "0"
10536       ) args
10537     )
10538   in
10539
10540   generate_lang_bindtests (
10541     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10542   );
10543
10544   pr "print \"EOF\\n\"\n"
10545
10546 and generate_python_bindtests () =
10547   generate_header HashStyle GPLv2plus;
10548
10549   pr "\
10550 import guestfs
10551
10552 g = guestfs.GuestFS ()
10553 ";
10554
10555   let mkargs args =
10556     String.concat ", " (
10557       List.map (
10558         function
10559         | CallString s -> "\"" ^ s ^ "\""
10560         | CallOptString None -> "None"
10561         | CallOptString (Some s) -> sprintf "\"%s\"" s
10562         | CallStringList xs ->
10563             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10564         | CallInt i -> string_of_int i
10565         | CallInt64 i -> Int64.to_string i
10566         | CallBool b -> if b then "1" else "0"
10567       ) args
10568     )
10569   in
10570
10571   generate_lang_bindtests (
10572     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10573   );
10574
10575   pr "print \"EOF\"\n"
10576
10577 and generate_ruby_bindtests () =
10578   generate_header HashStyle GPLv2plus;
10579
10580   pr "\
10581 require 'guestfs'
10582
10583 g = Guestfs::create()
10584 ";
10585
10586   let mkargs args =
10587     String.concat ", " (
10588       List.map (
10589         function
10590         | CallString s -> "\"" ^ s ^ "\""
10591         | CallOptString None -> "nil"
10592         | CallOptString (Some s) -> sprintf "\"%s\"" s
10593         | CallStringList xs ->
10594             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10595         | CallInt i -> string_of_int i
10596         | CallInt64 i -> Int64.to_string i
10597         | CallBool b -> string_of_bool b
10598       ) args
10599     )
10600   in
10601
10602   generate_lang_bindtests (
10603     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10604   );
10605
10606   pr "print \"EOF\\n\"\n"
10607
10608 and generate_java_bindtests () =
10609   generate_header CStyle GPLv2plus;
10610
10611   pr "\
10612 import com.redhat.et.libguestfs.*;
10613
10614 public class Bindtests {
10615     public static void main (String[] argv)
10616     {
10617         try {
10618             GuestFS g = new GuestFS ();
10619 ";
10620
10621   let mkargs args =
10622     String.concat ", " (
10623       List.map (
10624         function
10625         | CallString s -> "\"" ^ s ^ "\""
10626         | CallOptString None -> "null"
10627         | CallOptString (Some s) -> sprintf "\"%s\"" s
10628         | CallStringList xs ->
10629             "new String[]{" ^
10630               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10631         | CallInt i -> string_of_int i
10632         | CallInt64 i -> Int64.to_string i
10633         | CallBool b -> string_of_bool b
10634       ) args
10635     )
10636   in
10637
10638   generate_lang_bindtests (
10639     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10640   );
10641
10642   pr "
10643             System.out.println (\"EOF\");
10644         }
10645         catch (Exception exn) {
10646             System.err.println (exn);
10647             System.exit (1);
10648         }
10649     }
10650 }
10651 "
10652
10653 and generate_haskell_bindtests () =
10654   generate_header HaskellStyle GPLv2plus;
10655
10656   pr "\
10657 module Bindtests where
10658 import qualified Guestfs
10659
10660 main = do
10661   g <- Guestfs.create
10662 ";
10663
10664   let mkargs args =
10665     String.concat " " (
10666       List.map (
10667         function
10668         | CallString s -> "\"" ^ s ^ "\""
10669         | CallOptString None -> "Nothing"
10670         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10671         | CallStringList xs ->
10672             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10673         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10674         | CallInt i -> string_of_int i
10675         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10676         | CallInt64 i -> Int64.to_string i
10677         | CallBool true -> "True"
10678         | CallBool false -> "False"
10679       ) args
10680     )
10681   in
10682
10683   generate_lang_bindtests (
10684     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10685   );
10686
10687   pr "  putStrLn \"EOF\"\n"
10688
10689 (* Language-independent bindings tests - we do it this way to
10690  * ensure there is parity in testing bindings across all languages.
10691  *)
10692 and generate_lang_bindtests call =
10693   call "test0" [CallString "abc"; CallOptString (Some "def");
10694                 CallStringList []; CallBool false;
10695                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10696   call "test0" [CallString "abc"; CallOptString None;
10697                 CallStringList []; CallBool false;
10698                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10699   call "test0" [CallString ""; CallOptString (Some "def");
10700                 CallStringList []; CallBool false;
10701                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10702   call "test0" [CallString ""; CallOptString (Some "");
10703                 CallStringList []; CallBool false;
10704                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10705   call "test0" [CallString "abc"; CallOptString (Some "def");
10706                 CallStringList ["1"]; CallBool false;
10707                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10708   call "test0" [CallString "abc"; CallOptString (Some "def");
10709                 CallStringList ["1"; "2"]; CallBool false;
10710                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10711   call "test0" [CallString "abc"; CallOptString (Some "def");
10712                 CallStringList ["1"]; CallBool true;
10713                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10714   call "test0" [CallString "abc"; CallOptString (Some "def");
10715                 CallStringList ["1"]; CallBool false;
10716                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10717   call "test0" [CallString "abc"; CallOptString (Some "def");
10718                 CallStringList ["1"]; CallBool false;
10719                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10720   call "test0" [CallString "abc"; CallOptString (Some "def");
10721                 CallStringList ["1"]; CallBool false;
10722                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10723   call "test0" [CallString "abc"; CallOptString (Some "def");
10724                 CallStringList ["1"]; CallBool false;
10725                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10726   call "test0" [CallString "abc"; CallOptString (Some "def");
10727                 CallStringList ["1"]; CallBool false;
10728                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10729   call "test0" [CallString "abc"; CallOptString (Some "def");
10730                 CallStringList ["1"]; CallBool false;
10731                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10732
10733 (* XXX Add here tests of the return and error functions. *)
10734
10735 (* Code to generator bindings for virt-inspector.  Currently only
10736  * implemented for OCaml code (for virt-p2v 2.0).
10737  *)
10738 let rng_input = "inspector/virt-inspector.rng"
10739
10740 (* Read the input file and parse it into internal structures.  This is
10741  * by no means a complete RELAX NG parser, but is just enough to be
10742  * able to parse the specific input file.
10743  *)
10744 type rng =
10745   | Element of string * rng list        (* <element name=name/> *)
10746   | Attribute of string * rng list        (* <attribute name=name/> *)
10747   | Interleave of rng list                (* <interleave/> *)
10748   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10749   | OneOrMore of rng                        (* <oneOrMore/> *)
10750   | Optional of rng                        (* <optional/> *)
10751   | Choice of string list                (* <choice><value/>*</choice> *)
10752   | Value of string                        (* <value>str</value> *)
10753   | Text                                (* <text/> *)
10754
10755 let rec string_of_rng = function
10756   | Element (name, xs) ->
10757       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10758   | Attribute (name, xs) ->
10759       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10760   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10761   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10762   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10763   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10764   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10765   | Value value -> "Value \"" ^ value ^ "\""
10766   | Text -> "Text"
10767
10768 and string_of_rng_list xs =
10769   String.concat ", " (List.map string_of_rng xs)
10770
10771 let rec parse_rng ?defines context = function
10772   | [] -> []
10773   | Xml.Element ("element", ["name", name], children) :: rest ->
10774       Element (name, parse_rng ?defines context children)
10775       :: parse_rng ?defines context rest
10776   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10777       Attribute (name, parse_rng ?defines context children)
10778       :: parse_rng ?defines context rest
10779   | Xml.Element ("interleave", [], children) :: rest ->
10780       Interleave (parse_rng ?defines context children)
10781       :: parse_rng ?defines context rest
10782   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10783       let rng = parse_rng ?defines context [child] in
10784       (match rng with
10785        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10786        | _ ->
10787            failwithf "%s: <zeroOrMore> contains more than one child element"
10788              context
10789       )
10790   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10791       let rng = parse_rng ?defines context [child] in
10792       (match rng with
10793        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10794        | _ ->
10795            failwithf "%s: <oneOrMore> contains more than one child element"
10796              context
10797       )
10798   | Xml.Element ("optional", [], [child]) :: rest ->
10799       let rng = parse_rng ?defines context [child] in
10800       (match rng with
10801        | [child] -> Optional child :: parse_rng ?defines context rest
10802        | _ ->
10803            failwithf "%s: <optional> contains more than one child element"
10804              context
10805       )
10806   | Xml.Element ("choice", [], children) :: rest ->
10807       let values = List.map (
10808         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10809         | _ ->
10810             failwithf "%s: can't handle anything except <value> in <choice>"
10811               context
10812       ) children in
10813       Choice values
10814       :: parse_rng ?defines context rest
10815   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10816       Value value :: parse_rng ?defines context rest
10817   | Xml.Element ("text", [], []) :: rest ->
10818       Text :: parse_rng ?defines context rest
10819   | Xml.Element ("ref", ["name", name], []) :: rest ->
10820       (* Look up the reference.  Because of limitations in this parser,
10821        * we can't handle arbitrarily nested <ref> yet.  You can only
10822        * use <ref> from inside <start>.
10823        *)
10824       (match defines with
10825        | None ->
10826            failwithf "%s: contains <ref>, but no refs are defined yet" context
10827        | Some map ->
10828            let rng = StringMap.find name map in
10829            rng @ parse_rng ?defines context rest
10830       )
10831   | x :: _ ->
10832       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10833
10834 let grammar =
10835   let xml = Xml.parse_file rng_input in
10836   match xml with
10837   | Xml.Element ("grammar", _,
10838                  Xml.Element ("start", _, gram) :: defines) ->
10839       (* The <define/> elements are referenced in the <start> section,
10840        * so build a map of those first.
10841        *)
10842       let defines = List.fold_left (
10843         fun map ->
10844           function Xml.Element ("define", ["name", name], defn) ->
10845             StringMap.add name defn map
10846           | _ ->
10847               failwithf "%s: expected <define name=name/>" rng_input
10848       ) StringMap.empty defines in
10849       let defines = StringMap.mapi parse_rng defines in
10850
10851       (* Parse the <start> clause, passing the defines. *)
10852       parse_rng ~defines "<start>" gram
10853   | _ ->
10854       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10855         rng_input
10856
10857 let name_of_field = function
10858   | Element (name, _) | Attribute (name, _)
10859   | ZeroOrMore (Element (name, _))
10860   | OneOrMore (Element (name, _))
10861   | Optional (Element (name, _)) -> name
10862   | Optional (Attribute (name, _)) -> name
10863   | Text -> (* an unnamed field in an element *)
10864       "data"
10865   | rng ->
10866       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10867
10868 (* At the moment this function only generates OCaml types.  However we
10869  * should parameterize it later so it can generate types/structs in a
10870  * variety of languages.
10871  *)
10872 let generate_types xs =
10873   (* A simple type is one that can be printed out directly, eg.
10874    * "string option".  A complex type is one which has a name and has
10875    * to be defined via another toplevel definition, eg. a struct.
10876    *
10877    * generate_type generates code for either simple or complex types.
10878    * In the simple case, it returns the string ("string option").  In
10879    * the complex case, it returns the name ("mountpoint").  In the
10880    * complex case it has to print out the definition before returning,
10881    * so it should only be called when we are at the beginning of a
10882    * new line (BOL context).
10883    *)
10884   let rec generate_type = function
10885     | Text ->                                (* string *)
10886         "string", true
10887     | Choice values ->                        (* [`val1|`val2|...] *)
10888         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10889     | ZeroOrMore rng ->                        (* <rng> list *)
10890         let t, is_simple = generate_type rng in
10891         t ^ " list (* 0 or more *)", is_simple
10892     | OneOrMore rng ->                        (* <rng> list *)
10893         let t, is_simple = generate_type rng in
10894         t ^ " list (* 1 or more *)", is_simple
10895                                         (* virt-inspector hack: bool *)
10896     | Optional (Attribute (name, [Value "1"])) ->
10897         "bool", true
10898     | Optional rng ->                        (* <rng> list *)
10899         let t, is_simple = generate_type rng in
10900         t ^ " option", is_simple
10901                                         (* type name = { fields ... } *)
10902     | Element (name, fields) when is_attrs_interleave fields ->
10903         generate_type_struct name (get_attrs_interleave fields)
10904     | Element (name, [field])                (* type name = field *)
10905     | Attribute (name, [field]) ->
10906         let t, is_simple = generate_type field in
10907         if is_simple then (t, true)
10908         else (
10909           pr "type %s = %s\n" name t;
10910           name, false
10911         )
10912     | Element (name, fields) ->              (* type name = { fields ... } *)
10913         generate_type_struct name fields
10914     | rng ->
10915         failwithf "generate_type failed at: %s" (string_of_rng rng)
10916
10917   and is_attrs_interleave = function
10918     | [Interleave _] -> true
10919     | Attribute _ :: fields -> is_attrs_interleave fields
10920     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
10921     | _ -> false
10922
10923   and get_attrs_interleave = function
10924     | [Interleave fields] -> fields
10925     | ((Attribute _) as field) :: fields
10926     | ((Optional (Attribute _)) as field) :: fields ->
10927         field :: get_attrs_interleave fields
10928     | _ -> assert false
10929
10930   and generate_types xs =
10931     List.iter (fun x -> ignore (generate_type x)) xs
10932
10933   and generate_type_struct name fields =
10934     (* Calculate the types of the fields first.  We have to do this
10935      * before printing anything so we are still in BOL context.
10936      *)
10937     let types = List.map fst (List.map generate_type fields) in
10938
10939     (* Special case of a struct containing just a string and another
10940      * field.  Turn it into an assoc list.
10941      *)
10942     match types with
10943     | ["string"; other] ->
10944         let fname1, fname2 =
10945           match fields with
10946           | [f1; f2] -> name_of_field f1, name_of_field f2
10947           | _ -> assert false in
10948         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
10949         name, false
10950
10951     | types ->
10952         pr "type %s = {\n" name;
10953         List.iter (
10954           fun (field, ftype) ->
10955             let fname = name_of_field field in
10956             pr "  %s_%s : %s;\n" name fname ftype
10957         ) (List.combine fields types);
10958         pr "}\n";
10959         (* Return the name of this type, and
10960          * false because it's not a simple type.
10961          *)
10962         name, false
10963   in
10964
10965   generate_types xs
10966
10967 let generate_parsers xs =
10968   (* As for generate_type above, generate_parser makes a parser for
10969    * some type, and returns the name of the parser it has generated.
10970    * Because it (may) need to print something, it should always be
10971    * called in BOL context.
10972    *)
10973   let rec generate_parser = function
10974     | Text ->                                (* string *)
10975         "string_child_or_empty"
10976     | Choice values ->                        (* [`val1|`val2|...] *)
10977         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
10978           (String.concat "|"
10979              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
10980     | ZeroOrMore rng ->                        (* <rng> list *)
10981         let pa = generate_parser rng in
10982         sprintf "(fun x -> List.map %s (Xml.children x))" pa
10983     | OneOrMore rng ->                        (* <rng> list *)
10984         let pa = generate_parser rng in
10985         sprintf "(fun x -> List.map %s (Xml.children x))" pa
10986                                         (* virt-inspector hack: bool *)
10987     | Optional (Attribute (name, [Value "1"])) ->
10988         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
10989     | Optional rng ->                        (* <rng> list *)
10990         let pa = generate_parser rng in
10991         sprintf "(function None -> None | Some x -> Some (%s x))" pa
10992                                         (* type name = { fields ... } *)
10993     | Element (name, fields) when is_attrs_interleave fields ->
10994         generate_parser_struct name (get_attrs_interleave fields)
10995     | Element (name, [field]) ->        (* type name = field *)
10996         let pa = generate_parser field in
10997         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
10998         pr "let %s =\n" parser_name;
10999         pr "  %s\n" pa;
11000         pr "let parse_%s = %s\n" name parser_name;
11001         parser_name
11002     | Attribute (name, [field]) ->
11003         let pa = generate_parser field in
11004         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11005         pr "let %s =\n" parser_name;
11006         pr "  %s\n" pa;
11007         pr "let parse_%s = %s\n" name parser_name;
11008         parser_name
11009     | Element (name, fields) ->              (* type name = { fields ... } *)
11010         generate_parser_struct name ([], fields)
11011     | rng ->
11012         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11013
11014   and is_attrs_interleave = function
11015     | [Interleave _] -> true
11016     | Attribute _ :: fields -> is_attrs_interleave fields
11017     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11018     | _ -> false
11019
11020   and get_attrs_interleave = function
11021     | [Interleave fields] -> [], fields
11022     | ((Attribute _) as field) :: fields
11023     | ((Optional (Attribute _)) as field) :: fields ->
11024         let attrs, interleaves = get_attrs_interleave fields in
11025         (field :: attrs), interleaves
11026     | _ -> assert false
11027
11028   and generate_parsers xs =
11029     List.iter (fun x -> ignore (generate_parser x)) xs
11030
11031   and generate_parser_struct name (attrs, interleaves) =
11032     (* Generate parsers for the fields first.  We have to do this
11033      * before printing anything so we are still in BOL context.
11034      *)
11035     let fields = attrs @ interleaves in
11036     let pas = List.map generate_parser fields in
11037
11038     (* Generate an intermediate tuple from all the fields first.
11039      * If the type is just a string + another field, then we will
11040      * return this directly, otherwise it is turned into a record.
11041      *
11042      * RELAX NG note: This code treats <interleave> and plain lists of
11043      * fields the same.  In other words, it doesn't bother enforcing
11044      * any ordering of fields in the XML.
11045      *)
11046     pr "let parse_%s x =\n" name;
11047     pr "  let t = (\n    ";
11048     let comma = ref false in
11049     List.iter (
11050       fun x ->
11051         if !comma then pr ",\n    ";
11052         comma := true;
11053         match x with
11054         | Optional (Attribute (fname, [field])), pa ->
11055             pr "%s x" pa
11056         | Optional (Element (fname, [field])), pa ->
11057             pr "%s (optional_child %S x)" pa fname
11058         | Attribute (fname, [Text]), _ ->
11059             pr "attribute %S x" fname
11060         | (ZeroOrMore _ | OneOrMore _), pa ->
11061             pr "%s x" pa
11062         | Text, pa ->
11063             pr "%s x" pa
11064         | (field, pa) ->
11065             let fname = name_of_field field in
11066             pr "%s (child %S x)" pa fname
11067     ) (List.combine fields pas);
11068     pr "\n  ) in\n";
11069
11070     (match fields with
11071      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11072          pr "  t\n"
11073
11074      | _ ->
11075          pr "  (Obj.magic t : %s)\n" name
11076 (*
11077          List.iter (
11078            function
11079            | (Optional (Attribute (fname, [field])), pa) ->
11080                pr "  %s_%s =\n" name fname;
11081                pr "    %s x;\n" pa
11082            | (Optional (Element (fname, [field])), pa) ->
11083                pr "  %s_%s =\n" name fname;
11084                pr "    (let x = optional_child %S x in\n" fname;
11085                pr "     %s x);\n" pa
11086            | (field, pa) ->
11087                let fname = name_of_field field in
11088                pr "  %s_%s =\n" name fname;
11089                pr "    (let x = child %S x in\n" fname;
11090                pr "     %s x);\n" pa
11091          ) (List.combine fields pas);
11092          pr "}\n"
11093 *)
11094     );
11095     sprintf "parse_%s" name
11096   in
11097
11098   generate_parsers xs
11099
11100 (* Generate ocaml/guestfs_inspector.mli. *)
11101 let generate_ocaml_inspector_mli () =
11102   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11103
11104   pr "\
11105 (** This is an OCaml language binding to the external [virt-inspector]
11106     program.
11107
11108     For more information, please read the man page [virt-inspector(1)].
11109 *)
11110
11111 ";
11112
11113   generate_types grammar;
11114   pr "(** The nested information returned from the {!inspect} function. *)\n";
11115   pr "\n";
11116
11117   pr "\
11118 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11119 (** To inspect a libvirt domain called [name], pass a singleton
11120     list: [inspect [name]].  When using libvirt only, you may
11121     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11122
11123     To inspect a disk image or images, pass a list of the filenames
11124     of the disk images: [inspect filenames]
11125
11126     This function inspects the given guest or disk images and
11127     returns a list of operating system(s) found and a large amount
11128     of information about them.  In the vast majority of cases,
11129     a virtual machine only contains a single operating system.
11130
11131     If the optional [~xml] parameter is given, then this function
11132     skips running the external virt-inspector program and just
11133     parses the given XML directly (which is expected to be XML
11134     produced from a previous run of virt-inspector).  The list of
11135     names and connect URI are ignored in this case.
11136
11137     This function can throw a wide variety of exceptions, for example
11138     if the external virt-inspector program cannot be found, or if
11139     it doesn't generate valid XML.
11140 *)
11141 "
11142
11143 (* Generate ocaml/guestfs_inspector.ml. *)
11144 let generate_ocaml_inspector_ml () =
11145   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11146
11147   pr "open Unix\n";
11148   pr "\n";
11149
11150   generate_types grammar;
11151   pr "\n";
11152
11153   pr "\
11154 (* Misc functions which are used by the parser code below. *)
11155 let first_child = function
11156   | Xml.Element (_, _, c::_) -> c
11157   | Xml.Element (name, _, []) ->
11158       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11159   | Xml.PCData str ->
11160       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11161
11162 let string_child_or_empty = function
11163   | Xml.Element (_, _, [Xml.PCData s]) -> s
11164   | Xml.Element (_, _, []) -> \"\"
11165   | Xml.Element (x, _, _) ->
11166       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11167                 x ^ \" instead\")
11168   | Xml.PCData str ->
11169       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11170
11171 let optional_child name xml =
11172   let children = Xml.children xml in
11173   try
11174     Some (List.find (function
11175                      | Xml.Element (n, _, _) when n = name -> true
11176                      | _ -> false) children)
11177   with
11178     Not_found -> None
11179
11180 let child name xml =
11181   match optional_child name xml with
11182   | Some c -> c
11183   | None ->
11184       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11185
11186 let attribute name xml =
11187   try Xml.attrib xml name
11188   with Xml.No_attribute _ ->
11189     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11190
11191 ";
11192
11193   generate_parsers grammar;
11194   pr "\n";
11195
11196   pr "\
11197 (* Run external virt-inspector, then use parser to parse the XML. *)
11198 let inspect ?connect ?xml names =
11199   let xml =
11200     match xml with
11201     | None ->
11202         if names = [] then invalid_arg \"inspect: no names given\";
11203         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11204           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11205           names in
11206         let cmd = List.map Filename.quote cmd in
11207         let cmd = String.concat \" \" cmd in
11208         let chan = open_process_in cmd in
11209         let xml = Xml.parse_in chan in
11210         (match close_process_in chan with
11211          | WEXITED 0 -> ()
11212          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11213          | WSIGNALED i | WSTOPPED i ->
11214              failwith (\"external virt-inspector command died or stopped on sig \" ^
11215                        string_of_int i)
11216         );
11217         xml
11218     | Some doc ->
11219         Xml.parse_string doc in
11220   parse_operatingsystems xml
11221 "
11222
11223 (* This is used to generate the src/MAX_PROC_NR file which
11224  * contains the maximum procedure number, a surrogate for the
11225  * ABI version number.  See src/Makefile.am for the details.
11226  *)
11227 and generate_max_proc_nr () =
11228   let proc_nrs = List.map (
11229     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11230   ) daemon_functions in
11231
11232   let max_proc_nr = List.fold_left max 0 proc_nrs in
11233
11234   pr "%d\n" max_proc_nr
11235
11236 let output_to filename k =
11237   let filename_new = filename ^ ".new" in
11238   chan := open_out filename_new;
11239   k ();
11240   close_out !chan;
11241   chan := Pervasives.stdout;
11242
11243   (* Is the new file different from the current file? *)
11244   if Sys.file_exists filename && files_equal filename filename_new then
11245     unlink filename_new                 (* same, so skip it *)
11246   else (
11247     (* different, overwrite old one *)
11248     (try chmod filename 0o644 with Unix_error _ -> ());
11249     rename filename_new filename;
11250     chmod filename 0o444;
11251     printf "written %s\n%!" filename;
11252   )
11253
11254 let perror msg = function
11255   | Unix_error (err, _, _) ->
11256       eprintf "%s: %s\n" msg (error_message err)
11257   | exn ->
11258       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11259
11260 (* Main program. *)
11261 let () =
11262   let lock_fd =
11263     try openfile "HACKING" [O_RDWR] 0
11264     with
11265     | Unix_error (ENOENT, _, _) ->
11266         eprintf "\
11267 You are probably running this from the wrong directory.
11268 Run it from the top source directory using the command
11269   src/generator.ml
11270 ";
11271         exit 1
11272     | exn ->
11273         perror "open: HACKING" exn;
11274         exit 1 in
11275
11276   (* Acquire a lock so parallel builds won't try to run the generator
11277    * twice at the same time.  Subsequent builds will wait for the first
11278    * one to finish.  Note the lock is released implicitly when the
11279    * program exits.
11280    *)
11281   (try lockf lock_fd F_LOCK 1
11282    with exn ->
11283      perror "lock: HACKING" exn;
11284      exit 1);
11285
11286   check_functions ();
11287
11288   output_to "src/guestfs_protocol.x" generate_xdr;
11289   output_to "src/guestfs-structs.h" generate_structs_h;
11290   output_to "src/guestfs-actions.h" generate_actions_h;
11291   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11292   output_to "src/guestfs-actions.c" generate_client_actions;
11293   output_to "src/guestfs-bindtests.c" generate_bindtests;
11294   output_to "src/guestfs-structs.pod" generate_structs_pod;
11295   output_to "src/guestfs-actions.pod" generate_actions_pod;
11296   output_to "src/guestfs-availability.pod" generate_availability_pod;
11297   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11298   output_to "src/libguestfs.syms" generate_linker_script;
11299   output_to "daemon/actions.h" generate_daemon_actions_h;
11300   output_to "daemon/stubs.c" generate_daemon_actions;
11301   output_to "daemon/names.c" generate_daemon_names;
11302   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11303   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11304   output_to "capitests/tests.c" generate_tests;
11305   output_to "fish/cmds.c" generate_fish_cmds;
11306   output_to "fish/completion.c" generate_fish_completion;
11307   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11308   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11309   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11310   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11311   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11312   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11313   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11314   output_to "perl/Guestfs.xs" generate_perl_xs;
11315   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11316   output_to "perl/bindtests.pl" generate_perl_bindtests;
11317   output_to "python/guestfs-py.c" generate_python_c;
11318   output_to "python/guestfs.py" generate_python_py;
11319   output_to "python/bindtests.py" generate_python_bindtests;
11320   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11321   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11322   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11323
11324   List.iter (
11325     fun (typ, jtyp) ->
11326       let cols = cols_of_struct typ in
11327       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11328       output_to filename (generate_java_struct jtyp cols);
11329   ) java_structs;
11330
11331   output_to "java/Makefile.inc" generate_java_makefile_inc;
11332   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11333   output_to "java/Bindtests.java" generate_java_bindtests;
11334   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11335   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11336   output_to "csharp/Libguestfs.cs" generate_csharp;
11337
11338   (* Always generate this file last, and unconditionally.  It's used
11339    * by the Makefile to know when we must re-run the generator.
11340    *)
11341   let chan = open_out "src/stamp-generator" in
11342   fprintf chan "1\n";
11343   close_out chan;
11344
11345   printf "generated %d lines of code\n" !lines