4f569ba5feb883dc9ec6535a79a0cab11c774c52
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #load "xml-light.cma";;
46
47 open Unix
48 open Printf
49
50 type style = ret * args
51 and ret =
52     (* "RErr" as a return value means an int used as a simple error
53      * indication, ie. 0 or -1.
54      *)
55   | RErr
56
57     (* "RInt" as a return value means an int which is -1 for error
58      * or any value >= 0 on success.  Only use this for smallish
59      * positive ints (0 <= i < 2^30).
60      *)
61   | RInt of string
62
63     (* "RInt64" is the same as RInt, but is guaranteed to be able
64      * to return a full 64 bit value, _except_ that -1 means error
65      * (so -1 cannot be a valid, non-error return value).
66      *)
67   | RInt64 of string
68
69     (* "RBool" is a bool return value which can be true/false or
70      * -1 for error.
71      *)
72   | RBool of string
73
74     (* "RConstString" is a string that refers to a constant value.
75      * The return value must NOT be NULL (since NULL indicates
76      * an error).
77      *
78      * Try to avoid using this.  In particular you cannot use this
79      * for values returned from the daemon, because there is no
80      * thread-safe way to return them in the C API.
81      *)
82   | RConstString of string
83
84     (* "RConstOptString" is an even more broken version of
85      * "RConstString".  The returned string may be NULL and there
86      * is no way to return an error indication.  Avoid using this!
87      *)
88   | RConstOptString of string
89
90     (* "RString" is a returned string.  It must NOT be NULL, since
91      * a NULL return indicates an error.  The caller frees this.
92      *)
93   | RString of string
94
95     (* "RStringList" is a list of strings.  No string in the list
96      * can be NULL.  The caller frees the strings and the array.
97      *)
98   | RStringList of string
99
100     (* "RStruct" is a function which returns a single named structure
101      * or an error indication (in C, a struct, and in other languages
102      * with varying representations, but usually very efficient).  See
103      * after the function list below for the structures.
104      *)
105   | RStruct of string * string          (* name of retval, name of struct *)
106
107     (* "RStructList" is a function which returns either a list/array
108      * of structures (could be zero-length), or an error indication.
109      *)
110   | RStructList of string * string      (* name of retval, name of struct *)
111
112     (* Key-value pairs of untyped strings.  Turns into a hashtable or
113      * dictionary in languages which support it.  DON'T use this as a
114      * general "bucket" for results.  Prefer a stronger typed return
115      * value if one is available, or write a custom struct.  Don't use
116      * this if the list could potentially be very long, since it is
117      * inefficient.  Keys should be unique.  NULLs are not permitted.
118      *)
119   | RHashtable of string
120
121     (* "RBufferOut" is handled almost exactly like RString, but
122      * it allows the string to contain arbitrary 8 bit data including
123      * ASCII NUL.  In the C API this causes an implicit extra parameter
124      * to be added of type <size_t *size_r>.  The extra parameter
125      * returns the actual size of the return buffer in bytes.
126      *
127      * Other programming languages support strings with arbitrary 8 bit
128      * data.
129      *
130      * At the RPC layer we have to use the opaque<> type instead of
131      * string<>.  Returned data is still limited to the max message
132      * size (ie. ~ 2 MB).
133      *)
134   | RBufferOut of string
135
136 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
137
138     (* Note in future we should allow a "variable args" parameter as
139      * the final parameter, to allow commands like
140      *   chmod mode file [file(s)...]
141      * This is not implemented yet, but many commands (such as chmod)
142      * are currently defined with the argument order keeping this future
143      * possibility in mind.
144      *)
145 and argt =
146   | String of string    (* const char *name, cannot be NULL *)
147   | Device of string    (* /dev device name, cannot be NULL *)
148   | Pathname of string  (* file name, cannot be NULL *)
149   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
150   | OptString of string (* const char *name, may be NULL *)
151   | StringList of string(* list of strings (each string cannot be NULL) *)
152   | DeviceList of string(* list of Device names (each cannot be NULL) *)
153   | Bool of string      (* boolean *)
154   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
155   | Int64 of string     (* any 64 bit int *)
156     (* These are treated as filenames (simple string parameters) in
157      * the C API and bindings.  But in the RPC protocol, we transfer
158      * the actual file content up to or down from the daemon.
159      * FileIn: local machine -> daemon (in request)
160      * FileOut: daemon -> local machine (in reply)
161      * In guestfish (only), the special name "-" means read from
162      * stdin or write to stdout.
163      *)
164   | FileIn of string
165   | FileOut of string
166 (* Not implemented:
167     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <char *, int> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177 *)
178
179 type flags =
180   | ProtocolLimitWarning  (* display warning about protocol size limits *)
181   | DangerWillRobinson    (* flags particularly dangerous commands *)
182   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
183   | FishAction of string  (* call this function in guestfish *)
184   | NotInFish             (* do not export via guestfish *)
185   | NotInDocs             (* do not add this function to documentation *)
186   | DeprecatedBy of string (* function is deprecated, use .. instead *)
187   | Optional of string    (* function is part of an optional group *)
188
189 (* You can supply zero or as many tests as you want per API call.
190  *
191  * Note that the test environment has 3 block devices, of size 500MB,
192  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
193  * a fourth ISO block device with some known files on it (/dev/sdd).
194  *
195  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
196  * Number of cylinders was 63 for IDE emulated disks with precisely
197  * the same size.  How exactly this is calculated is a mystery.
198  *
199  * The ISO block device (/dev/sdd) comes from images/test.iso.
200  *
201  * To be able to run the tests in a reasonable amount of time,
202  * the virtual machine and block devices are reused between tests.
203  * So don't try testing kill_subprocess :-x
204  *
205  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
206  *
207  * Don't assume anything about the previous contents of the block
208  * devices.  Use 'Init*' to create some initial scenarios.
209  *
210  * You can add a prerequisite clause to any individual test.  This
211  * is a run-time check, which, if it fails, causes the test to be
212  * skipped.  Useful if testing a command which might not work on
213  * all variations of libguestfs builds.  A test that has prerequisite
214  * of 'Always' is run unconditionally.
215  *
216  * In addition, packagers can skip individual tests by setting the
217  * environment variables:     eg:
218  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
219  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
220  *)
221 type tests = (test_init * test_prereq * test) list
222 and test =
223     (* Run the command sequence and just expect nothing to fail. *)
224   | TestRun of seq
225
226     (* Run the command sequence and expect the output of the final
227      * command to be the string.
228      *)
229   | TestOutput of seq * string
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the list of strings.
233      *)
234   | TestOutputList of seq * string list
235
236     (* Run the command sequence and expect the output of the final
237      * command to be the list of block devices (could be either
238      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
239      * character of each string).
240      *)
241   | TestOutputListOfDevices of seq * string list
242
243     (* Run the command sequence and expect the output of the final
244      * command to be the integer.
245      *)
246   | TestOutputInt of seq * int
247
248     (* Run the command sequence and expect the output of the final
249      * command to be <op> <int>, eg. ">=", "1".
250      *)
251   | TestOutputIntOp of seq * string * int
252
253     (* Run the command sequence and expect the output of the final
254      * command to be a true value (!= 0 or != NULL).
255      *)
256   | TestOutputTrue of seq
257
258     (* Run the command sequence and expect the output of the final
259      * command to be a false value (== 0 or == NULL, but not an error).
260      *)
261   | TestOutputFalse of seq
262
263     (* Run the command sequence and expect the output of the final
264      * command to be a list of the given length (but don't care about
265      * content).
266      *)
267   | TestOutputLength of seq * int
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a buffer (RBufferOut), ie. string + size.
271      *)
272   | TestOutputBuffer of seq * string
273
274     (* Run the command sequence and expect the output of the final
275      * command to be a structure.
276      *)
277   | TestOutputStruct of seq * test_field_compare list
278
279     (* Run the command sequence and expect the final command (only)
280      * to fail.
281      *)
282   | TestLastFail of seq
283
284 and test_field_compare =
285   | CompareWithInt of string * int
286   | CompareWithIntOp of string * string * int
287   | CompareWithString of string * string
288   | CompareFieldsIntEq of string * string
289   | CompareFieldsStrEq of string * string
290
291 (* Test prerequisites. *)
292 and test_prereq =
293     (* Test always runs. *)
294   | Always
295
296     (* Test is currently disabled - eg. it fails, or it tests some
297      * unimplemented feature.
298      *)
299   | Disabled
300
301     (* 'string' is some C code (a function body) that should return
302      * true or false.  The test will run if the code returns true.
303      *)
304   | If of string
305
306     (* As for 'If' but the test runs _unless_ the code returns true. *)
307   | Unless of string
308
309 (* Some initial scenarios for testing. *)
310 and test_init =
311     (* Do nothing, block devices could contain random stuff including
312      * LVM PVs, and some filesystems might be mounted.  This is usually
313      * a bad idea.
314      *)
315   | InitNone
316
317     (* Block devices are empty and no filesystems are mounted. *)
318   | InitEmpty
319
320     (* /dev/sda contains a single partition /dev/sda1, with random
321      * content.  /dev/sdb and /dev/sdc may have random content.
322      * No LVM.
323      *)
324   | InitPartition
325
326     (* /dev/sda contains a single partition /dev/sda1, which is formatted
327      * as ext2, empty [except for lost+found] and mounted on /.
328      * /dev/sdb and /dev/sdc may have random content.
329      * No LVM.
330      *)
331   | InitBasicFS
332
333     (* /dev/sda:
334      *   /dev/sda1 (is a PV):
335      *     /dev/VG/LV (size 8MB):
336      *       formatted as ext2, empty [except for lost+found], mounted on /
337      * /dev/sdb and /dev/sdc may have random content.
338      *)
339   | InitBasicFSonLVM
340
341     (* /dev/sdd (the ISO, see images/ directory in source)
342      * is mounted on /
343      *)
344   | InitISOFS
345
346 (* Sequence of commands for testing. *)
347 and seq = cmd list
348 and cmd = string list
349
350 (* Note about long descriptions: When referring to another
351  * action, use the format C<guestfs_other> (ie. the full name of
352  * the C function).  This will be replaced as appropriate in other
353  * language bindings.
354  *
355  * Apart from that, long descriptions are just perldoc paragraphs.
356  *)
357
358 (* Generate a random UUID (used in tests). *)
359 let uuidgen () =
360   let chan = open_process_in "uuidgen" in
361   let uuid = input_line chan in
362   (match close_process_in chan with
363    | WEXITED 0 -> ()
364    | WEXITED _ ->
365        failwith "uuidgen: process exited with non-zero status"
366    | WSIGNALED _ | WSTOPPED _ ->
367        failwith "uuidgen: process signalled or stopped by signal"
368   );
369   uuid
370
371 (* These test functions are used in the language binding tests. *)
372
373 let test_all_args = [
374   String "str";
375   OptString "optstr";
376   StringList "strlist";
377   Bool "b";
378   Int "integer";
379   Int64 "integer64";
380   FileIn "filein";
381   FileOut "fileout";
382 ]
383
384 let test_all_rets = [
385   (* except for RErr, which is tested thoroughly elsewhere *)
386   "test0rint",         RInt "valout";
387   "test0rint64",       RInt64 "valout";
388   "test0rbool",        RBool "valout";
389   "test0rconststring", RConstString "valout";
390   "test0rconstoptstring", RConstOptString "valout";
391   "test0rstring",      RString "valout";
392   "test0rstringlist",  RStringList "valout";
393   "test0rstruct",      RStruct ("valout", "lvm_pv");
394   "test0rstructlist",  RStructList ("valout", "lvm_pv");
395   "test0rhashtable",   RHashtable "valout";
396 ]
397
398 let test_functions = [
399   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
400    [],
401    "internal test function - do not use",
402    "\
403 This is an internal test function which is used to test whether
404 the automatically generated bindings can handle every possible
405 parameter type correctly.
406
407 It echos the contents of each parameter to stdout.
408
409 You probably don't want to call this function.");
410 ] @ List.flatten (
411   List.map (
412     fun (name, ret) ->
413       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
414         [],
415         "internal test function - do not use",
416         "\
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
420
421 It converts string C<val> to the return type.
422
423 You probably don't want to call this function.");
424        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
425         [],
426         "internal test function - do not use",
427         "\
428 This is an internal test function which is used to test whether
429 the automatically generated bindings can handle every possible
430 return type correctly.
431
432 This function always returns an error.
433
434 You probably don't want to call this function.")]
435   ) test_all_rets
436 )
437
438 (* non_daemon_functions are any functions which don't get processed
439  * in the daemon, eg. functions for setting and getting local
440  * configuration values.
441  *)
442
443 let non_daemon_functions = test_functions @ [
444   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
445    [],
446    "launch the qemu subprocess",
447    "\
448 Internally libguestfs is implemented by running a virtual machine
449 using L<qemu(1)>.
450
451 You should call this after configuring the handle
452 (eg. adding drives) but before performing any actions.");
453
454   ("wait_ready", (RErr, []), -1, [NotInFish],
455    [],
456    "wait until the qemu subprocess launches (no op)",
457    "\
458 This function is a no op.
459
460 In versions of the API E<lt> 1.0.71 you had to call this function
461 just after calling C<guestfs_launch> to wait for the launch
462 to complete.  However this is no longer necessary because
463 C<guestfs_launch> now does the waiting.
464
465 If you see any calls to this function in code then you can just
466 remove them, unless you want to retain compatibility with older
467 versions of the API.");
468
469   ("kill_subprocess", (RErr, []), -1, [],
470    [],
471    "kill the qemu subprocess",
472    "\
473 This kills the qemu subprocess.  You should never need to call this.");
474
475   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
476    [],
477    "add an image to examine or modify",
478    "\
479 This function adds a virtual machine disk image C<filename> to the
480 guest.  The first time you call this function, the disk appears as IDE
481 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
482 so on.
483
484 You don't necessarily need to be root when using libguestfs.  However
485 you obviously do need sufficient permissions to access the filename
486 for whatever operations you want to perform (ie. read access if you
487 just want to read the image or write access if you want to modify the
488 image).
489
490 This is equivalent to the qemu parameter
491 C<-drive file=filename,cache=off,if=...>.
492
493 C<cache=off> is omitted in cases where it is not supported by
494 the underlying filesystem.
495
496 C<if=...> is set at compile time by the configuration option
497 C<./configure --with-drive-if=...>.  In the rare case where you
498 might need to change this at run time, use C<guestfs_add_drive_with_if>
499 or C<guestfs_add_drive_ro_with_if>.
500
501 Note that this call checks for the existence of C<filename>.  This
502 stops you from specifying other types of drive which are supported
503 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
504 the general C<guestfs_config> call instead.");
505
506   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
507    [],
508    "add a CD-ROM disk image to examine",
509    "\
510 This function adds a virtual CD-ROM disk image to the guest.
511
512 This is equivalent to the qemu parameter C<-cdrom filename>.
513
514 Notes:
515
516 =over 4
517
518 =item *
519
520 This call checks for the existence of C<filename>.  This
521 stops you from specifying other types of drive which are supported
522 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
523 the general C<guestfs_config> call instead.
524
525 =item *
526
527 If you just want to add an ISO file (often you use this as an
528 efficient way to transfer large files into the guest), then you
529 should probably use C<guestfs_add_drive_ro> instead.
530
531 =back");
532
533   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
534    [],
535    "add a drive in snapshot mode (read-only)",
536    "\
537 This adds a drive in snapshot mode, making it effectively
538 read-only.
539
540 Note that writes to the device are allowed, and will be seen for
541 the duration of the guestfs handle, but they are written
542 to a temporary file which is discarded as soon as the guestfs
543 handle is closed.  We don't currently have any method to enable
544 changes to be committed, although qemu can support this.
545
546 This is equivalent to the qemu parameter
547 C<-drive file=filename,snapshot=on,if=...>.
548
549 C<if=...> is set at compile time by the configuration option
550 C<./configure --with-drive-if=...>.  In the rare case where you
551 might need to change this at run time, use C<guestfs_add_drive_with_if>
552 or C<guestfs_add_drive_ro_with_if>.
553
554 Note that this call checks for the existence of C<filename>.  This
555 stops you from specifying other types of drive which are supported
556 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
557 the general C<guestfs_config> call instead.");
558
559   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
560    [],
561    "add qemu parameters",
562    "\
563 This can be used to add arbitrary qemu command line parameters
564 of the form C<-param value>.  Actually it's not quite arbitrary - we
565 prevent you from setting some parameters which would interfere with
566 parameters that we use.
567
568 The first character of C<param> string must be a C<-> (dash).
569
570 C<value> can be NULL.");
571
572   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
573    [],
574    "set the qemu binary",
575    "\
576 Set the qemu binary that we will use.
577
578 The default is chosen when the library was compiled by the
579 configure script.
580
581 You can also override this by setting the C<LIBGUESTFS_QEMU>
582 environment variable.
583
584 Setting C<qemu> to C<NULL> restores the default qemu binary.
585
586 Note that you should call this function as early as possible
587 after creating the handle.  This is because some pre-launch
588 operations depend on testing qemu features (by running C<qemu -help>).
589 If the qemu binary changes, we don't retest features, and
590 so you might see inconsistent results.  Using the environment
591 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
592 the qemu binary at the same time as the handle is created.");
593
594   ("get_qemu", (RConstString "qemu", []), -1, [],
595    [InitNone, Always, TestRun (
596       [["get_qemu"]])],
597    "get the qemu binary",
598    "\
599 Return the current qemu binary.
600
601 This is always non-NULL.  If it wasn't set already, then this will
602 return the default qemu binary name.");
603
604   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
605    [],
606    "set the search path",
607    "\
608 Set the path that libguestfs searches for kernel and initrd.img.
609
610 The default is C<$libdir/guestfs> unless overridden by setting
611 C<LIBGUESTFS_PATH> environment variable.
612
613 Setting C<path> to C<NULL> restores the default path.");
614
615   ("get_path", (RConstString "path", []), -1, [],
616    [InitNone, Always, TestRun (
617       [["get_path"]])],
618    "get the search path",
619    "\
620 Return the current search path.
621
622 This is always non-NULL.  If it wasn't set already, then this will
623 return the default path.");
624
625   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
626    [],
627    "add options to kernel command line",
628    "\
629 This function is used to add additional options to the
630 guest kernel command line.
631
632 The default is C<NULL> unless overridden by setting
633 C<LIBGUESTFS_APPEND> environment variable.
634
635 Setting C<append> to C<NULL> means I<no> additional options
636 are passed (libguestfs always adds a few of its own).");
637
638   ("get_append", (RConstOptString "append", []), -1, [],
639    (* This cannot be tested with the current framework.  The
640     * function can return NULL in normal operations, which the
641     * test framework interprets as an error.
642     *)
643    [],
644    "get the additional kernel options",
645    "\
646 Return the additional kernel options which are added to the
647 guest kernel command line.
648
649 If C<NULL> then no options are added.");
650
651   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
652    [],
653    "set autosync mode",
654    "\
655 If C<autosync> is true, this enables autosync.  Libguestfs will make a
656 best effort attempt to run C<guestfs_umount_all> followed by
657 C<guestfs_sync> when the handle is closed
658 (also if the program exits without closing handles).
659
660 This is disabled by default (except in guestfish where it is
661 enabled by default).");
662
663   ("get_autosync", (RBool "autosync", []), -1, [],
664    [InitNone, Always, TestRun (
665       [["get_autosync"]])],
666    "get autosync mode",
667    "\
668 Get the autosync flag.");
669
670   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
671    [],
672    "set verbose mode",
673    "\
674 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
675
676 Verbose messages are disabled unless the environment variable
677 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
678
679   ("get_verbose", (RBool "verbose", []), -1, [],
680    [],
681    "get verbose mode",
682    "\
683 This returns the verbose messages flag.");
684
685   ("is_ready", (RBool "ready", []), -1, [],
686    [InitNone, Always, TestOutputTrue (
687       [["is_ready"]])],
688    "is ready to accept commands",
689    "\
690 This returns true iff this handle is ready to accept commands
691 (in the C<READY> state).
692
693 For more information on states, see L<guestfs(3)>.");
694
695   ("is_config", (RBool "config", []), -1, [],
696    [InitNone, Always, TestOutputFalse (
697       [["is_config"]])],
698    "is in configuration state",
699    "\
700 This returns true iff this handle is being configured
701 (in the C<CONFIG> state).
702
703 For more information on states, see L<guestfs(3)>.");
704
705   ("is_launching", (RBool "launching", []), -1, [],
706    [InitNone, Always, TestOutputFalse (
707       [["is_launching"]])],
708    "is launching subprocess",
709    "\
710 This returns true iff this handle is launching the subprocess
711 (in the C<LAUNCHING> state).
712
713 For more information on states, see L<guestfs(3)>.");
714
715   ("is_busy", (RBool "busy", []), -1, [],
716    [InitNone, Always, TestOutputFalse (
717       [["is_busy"]])],
718    "is busy processing a command",
719    "\
720 This returns true iff this handle is busy processing a command
721 (in the C<BUSY> state).
722
723 For more information on states, see L<guestfs(3)>.");
724
725   ("get_state", (RInt "state", []), -1, [],
726    [],
727    "get the current state",
728    "\
729 This returns the current state as an opaque integer.  This is
730 only useful for printing debug and internal error messages.
731
732 For more information on states, see L<guestfs(3)>.");
733
734   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
735    [InitNone, Always, TestOutputInt (
736       [["set_memsize"; "500"];
737        ["get_memsize"]], 500)],
738    "set memory allocated to the qemu subprocess",
739    "\
740 This sets the memory size in megabytes allocated to the
741 qemu subprocess.  This only has any effect if called before
742 C<guestfs_launch>.
743
744 You can also change this by setting the environment
745 variable C<LIBGUESTFS_MEMSIZE> before the handle is
746 created.
747
748 For more information on the architecture of libguestfs,
749 see L<guestfs(3)>.");
750
751   ("get_memsize", (RInt "memsize", []), -1, [],
752    [InitNone, Always, TestOutputIntOp (
753       [["get_memsize"]], ">=", 256)],
754    "get memory allocated to the qemu subprocess",
755    "\
756 This gets the memory size in megabytes allocated to the
757 qemu subprocess.
758
759 If C<guestfs_set_memsize> was not called
760 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
761 then this returns the compiled-in default value for memsize.
762
763 For more information on the architecture of libguestfs,
764 see L<guestfs(3)>.");
765
766   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
767    [InitNone, Always, TestOutputIntOp (
768       [["get_pid"]], ">=", 1)],
769    "get PID of qemu subprocess",
770    "\
771 Return the process ID of the qemu subprocess.  If there is no
772 qemu subprocess, then this will return an error.
773
774 This is an internal call used for debugging and testing.");
775
776   ("version", (RStruct ("version", "version"), []), -1, [],
777    [InitNone, Always, TestOutputStruct (
778       [["version"]], [CompareWithInt ("major", 1)])],
779    "get the library version number",
780    "\
781 Return the libguestfs version number that the program is linked
782 against.
783
784 Note that because of dynamic linking this is not necessarily
785 the version of libguestfs that you compiled against.  You can
786 compile the program, and then at runtime dynamically link
787 against a completely different C<libguestfs.so> library.
788
789 This call was added in version C<1.0.58>.  In previous
790 versions of libguestfs there was no way to get the version
791 number.  From C code you can use ELF weak linking tricks to find out if
792 this symbol exists (if it doesn't, then it's an earlier version).
793
794 The call returns a structure with four elements.  The first
795 three (C<major>, C<minor> and C<release>) are numbers and
796 correspond to the usual version triplet.  The fourth element
797 (C<extra>) is a string and is normally empty, but may be
798 used for distro-specific information.
799
800 To construct the original version string:
801 C<$major.$minor.$release$extra>
802
803 I<Note:> Don't use this call to test for availability
804 of features.  Distro backports makes this unreliable.  Use
805 C<guestfs_available> instead.");
806
807   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
808    [InitNone, Always, TestOutputTrue (
809       [["set_selinux"; "true"];
810        ["get_selinux"]])],
811    "set SELinux enabled or disabled at appliance boot",
812    "\
813 This sets the selinux flag that is passed to the appliance
814 at boot time.  The default is C<selinux=0> (disabled).
815
816 Note that if SELinux is enabled, it is always in
817 Permissive mode (C<enforcing=0>).
818
819 For more information on the architecture of libguestfs,
820 see L<guestfs(3)>.");
821
822   ("get_selinux", (RBool "selinux", []), -1, [],
823    [],
824    "get SELinux enabled flag",
825    "\
826 This returns the current setting of the selinux flag which
827 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
828
829 For more information on the architecture of libguestfs,
830 see L<guestfs(3)>.");
831
832   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
833    [InitNone, Always, TestOutputFalse (
834       [["set_trace"; "false"];
835        ["get_trace"]])],
836    "enable or disable command traces",
837    "\
838 If the command trace flag is set to 1, then commands are
839 printed on stdout before they are executed in a format
840 which is very similar to the one used by guestfish.  In
841 other words, you can run a program with this enabled, and
842 you will get out a script which you can feed to guestfish
843 to perform the same set of actions.
844
845 If you want to trace C API calls into libguestfs (and
846 other libraries) then possibly a better way is to use
847 the external ltrace(1) command.
848
849 Command traces are disabled unless the environment variable
850 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
851
852   ("get_trace", (RBool "trace", []), -1, [],
853    [],
854    "get command trace enabled flag",
855    "\
856 Return the command trace flag.");
857
858   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
859    [InitNone, Always, TestOutputFalse (
860       [["set_direct"; "false"];
861        ["get_direct"]])],
862    "enable or disable direct appliance mode",
863    "\
864 If the direct appliance mode flag is enabled, then stdin and
865 stdout are passed directly through to the appliance once it
866 is launched.
867
868 One consequence of this is that log messages aren't caught
869 by the library and handled by C<guestfs_set_log_message_callback>,
870 but go straight to stdout.
871
872 You probably don't want to use this unless you know what you
873 are doing.
874
875 The default is disabled.");
876
877   ("get_direct", (RBool "direct", []), -1, [],
878    [],
879    "get direct appliance mode flag",
880    "\
881 Return the direct appliance mode flag.");
882
883   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
884    [InitNone, Always, TestOutputTrue (
885       [["set_recovery_proc"; "true"];
886        ["get_recovery_proc"]])],
887    "enable or disable the recovery process",
888    "\
889 If this is called with the parameter C<false> then
890 C<guestfs_launch> does not create a recovery process.  The
891 purpose of the recovery process is to stop runaway qemu
892 processes in the case where the main program aborts abruptly.
893
894 This only has any effect if called before C<guestfs_launch>,
895 and the default is true.
896
897 About the only time when you would want to disable this is
898 if the main process will fork itself into the background
899 (\"daemonize\" itself).  In this case the recovery process
900 thinks that the main program has disappeared and so kills
901 qemu, which is not very helpful.");
902
903   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
904    [],
905    "get recovery process enabled flag",
906    "\
907 Return the recovery process enabled flag.");
908
909   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
910    [],
911    "add a drive specifying the QEMU block emulation to use",
912    "\
913 This is the same as C<guestfs_add_drive> but it allows you
914 to specify the QEMU interface emulation to use at run time.");
915
916   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917    [],
918    "add a drive read-only specifying the QEMU block emulation to use",
919    "\
920 This is the same as C<guestfs_add_drive_ro> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
922
923 ]
924
925 (* daemon_functions are any functions which cause some action
926  * to take place in the daemon.
927  *)
928
929 let daemon_functions = [
930   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
931    [InitEmpty, Always, TestOutput (
932       [["part_disk"; "/dev/sda"; "mbr"];
933        ["mkfs"; "ext2"; "/dev/sda1"];
934        ["mount"; "/dev/sda1"; "/"];
935        ["write_file"; "/new"; "new file contents"; "0"];
936        ["cat"; "/new"]], "new file contents")],
937    "mount a guest disk at a position in the filesystem",
938    "\
939 Mount a guest disk at a position in the filesystem.  Block devices
940 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
941 the guest.  If those block devices contain partitions, they will have
942 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
943 names can be used.
944
945 The rules are the same as for L<mount(2)>:  A filesystem must
946 first be mounted on C</> before others can be mounted.  Other
947 filesystems can only be mounted on directories which already
948 exist.
949
950 The mounted filesystem is writable, if we have sufficient permissions
951 on the underlying device.
952
953 The filesystem options C<sync> and C<noatime> are set with this
954 call, in order to improve reliability.");
955
956   ("sync", (RErr, []), 2, [],
957    [ InitEmpty, Always, TestRun [["sync"]]],
958    "sync disks, writes are flushed through to the disk image",
959    "\
960 This syncs the disk, so that any writes are flushed through to the
961 underlying disk image.
962
963 You should always call this if you have modified a disk image, before
964 closing the handle.");
965
966   ("touch", (RErr, [Pathname "path"]), 3, [],
967    [InitBasicFS, Always, TestOutputTrue (
968       [["touch"; "/new"];
969        ["exists"; "/new"]])],
970    "update file timestamps or create a new file",
971    "\
972 Touch acts like the L<touch(1)> command.  It can be used to
973 update the timestamps on a file, or, if the file does not exist,
974 to create a new zero-length file.");
975
976   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
977    [InitISOFS, Always, TestOutput (
978       [["cat"; "/known-2"]], "abcdef\n")],
979    "list the contents of a file",
980    "\
981 Return the contents of the file named C<path>.
982
983 Note that this function cannot correctly handle binary files
984 (specifically, files containing C<\\0> character which is treated
985 as end of string).  For those you need to use the C<guestfs_read_file>
986 or C<guestfs_download> functions which have a more complex interface.");
987
988   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
989    [], (* XXX Tricky to test because it depends on the exact format
990         * of the 'ls -l' command, which changes between F10 and F11.
991         *)
992    "list the files in a directory (long format)",
993    "\
994 List the files in C<directory> (relative to the root directory,
995 there is no cwd) in the format of 'ls -la'.
996
997 This command is mostly useful for interactive sessions.  It
998 is I<not> intended that you try to parse the output string.");
999
1000   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1001    [InitBasicFS, Always, TestOutputList (
1002       [["touch"; "/new"];
1003        ["touch"; "/newer"];
1004        ["touch"; "/newest"];
1005        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1006    "list the files in a directory",
1007    "\
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd).  The '.' and '..' entries are not returned, but
1010 hidden files are shown.
1011
1012 This command is mostly useful for interactive sessions.  Programs
1013 should probably use C<guestfs_readdir> instead.");
1014
1015   ("list_devices", (RStringList "devices", []), 7, [],
1016    [InitEmpty, Always, TestOutputListOfDevices (
1017       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1018    "list the block devices",
1019    "\
1020 List all the block devices.
1021
1022 The full block device names are returned, eg. C</dev/sda>");
1023
1024   ("list_partitions", (RStringList "partitions", []), 8, [],
1025    [InitBasicFS, Always, TestOutputListOfDevices (
1026       [["list_partitions"]], ["/dev/sda1"]);
1027     InitEmpty, Always, TestOutputListOfDevices (
1028       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1029        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1030    "list the partitions",
1031    "\
1032 List all the partitions detected on all block devices.
1033
1034 The full partition device names are returned, eg. C</dev/sda1>
1035
1036 This does not return logical volumes.  For that you will need to
1037 call C<guestfs_lvs>.");
1038
1039   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1040    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1041       [["pvs"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["pvcreate"; "/dev/sda1"];
1045        ["pvcreate"; "/dev/sda2"];
1046        ["pvcreate"; "/dev/sda3"];
1047        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1048    "list the LVM physical volumes (PVs)",
1049    "\
1050 List all the physical volumes detected.  This is the equivalent
1051 of the L<pvs(8)> command.
1052
1053 This returns a list of just the device names that contain
1054 PVs (eg. C</dev/sda2>).
1055
1056 See also C<guestfs_pvs_full>.");
1057
1058   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1059    [InitBasicFSonLVM, Always, TestOutputList (
1060       [["vgs"]], ["VG"]);
1061     InitEmpty, Always, TestOutputList (
1062       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1063        ["pvcreate"; "/dev/sda1"];
1064        ["pvcreate"; "/dev/sda2"];
1065        ["pvcreate"; "/dev/sda3"];
1066        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1067        ["vgcreate"; "VG2"; "/dev/sda3"];
1068        ["vgs"]], ["VG1"; "VG2"])],
1069    "list the LVM volume groups (VGs)",
1070    "\
1071 List all the volumes groups detected.  This is the equivalent
1072 of the L<vgs(8)> command.
1073
1074 This returns a list of just the volume group names that were
1075 detected (eg. C<VolGroup00>).
1076
1077 See also C<guestfs_vgs_full>.");
1078
1079   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1080    [InitBasicFSonLVM, Always, TestOutputList (
1081       [["lvs"]], ["/dev/VG/LV"]);
1082     InitEmpty, Always, TestOutputList (
1083       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1084        ["pvcreate"; "/dev/sda1"];
1085        ["pvcreate"; "/dev/sda2"];
1086        ["pvcreate"; "/dev/sda3"];
1087        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1088        ["vgcreate"; "VG2"; "/dev/sda3"];
1089        ["lvcreate"; "LV1"; "VG1"; "50"];
1090        ["lvcreate"; "LV2"; "VG1"; "50"];
1091        ["lvcreate"; "LV3"; "VG2"; "50"];
1092        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1093    "list the LVM logical volumes (LVs)",
1094    "\
1095 List all the logical volumes detected.  This is the equivalent
1096 of the L<lvs(8)> command.
1097
1098 This returns a list of the logical volume device names
1099 (eg. C</dev/VolGroup00/LogVol00>).
1100
1101 See also C<guestfs_lvs_full>.");
1102
1103   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1104    [], (* XXX how to test? *)
1105    "list the LVM physical volumes (PVs)",
1106    "\
1107 List all the physical volumes detected.  This is the equivalent
1108 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1109
1110   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1111    [], (* XXX how to test? *)
1112    "list the LVM volume groups (VGs)",
1113    "\
1114 List all the volumes groups detected.  This is the equivalent
1115 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1116
1117   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1118    [], (* XXX how to test? *)
1119    "list the LVM logical volumes (LVs)",
1120    "\
1121 List all the logical volumes detected.  This is the equivalent
1122 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1123
1124   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1125    [InitISOFS, Always, TestOutputList (
1126       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1127     InitISOFS, Always, TestOutputList (
1128       [["read_lines"; "/empty"]], [])],
1129    "read file as lines",
1130    "\
1131 Return the contents of the file named C<path>.
1132
1133 The file contents are returned as a list of lines.  Trailing
1134 C<LF> and C<CRLF> character sequences are I<not> returned.
1135
1136 Note that this function cannot correctly handle binary files
1137 (specifically, files containing C<\\0> character which is treated
1138 as end of line).  For those you need to use the C<guestfs_read_file>
1139 function which has a more complex interface.");
1140
1141   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1142    [], (* XXX Augeas code needs tests. *)
1143    "create a new Augeas handle",
1144    "\
1145 Create a new Augeas handle for editing configuration files.
1146 If there was any previous Augeas handle associated with this
1147 guestfs session, then it is closed.
1148
1149 You must call this before using any other C<guestfs_aug_*>
1150 commands.
1151
1152 C<root> is the filesystem root.  C<root> must not be NULL,
1153 use C</> instead.
1154
1155 The flags are the same as the flags defined in
1156 E<lt>augeas.hE<gt>, the logical I<or> of the following
1157 integers:
1158
1159 =over 4
1160
1161 =item C<AUG_SAVE_BACKUP> = 1
1162
1163 Keep the original file with a C<.augsave> extension.
1164
1165 =item C<AUG_SAVE_NEWFILE> = 2
1166
1167 Save changes into a file with extension C<.augnew>, and
1168 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1169
1170 =item C<AUG_TYPE_CHECK> = 4
1171
1172 Typecheck lenses (can be expensive).
1173
1174 =item C<AUG_NO_STDINC> = 8
1175
1176 Do not use standard load path for modules.
1177
1178 =item C<AUG_SAVE_NOOP> = 16
1179
1180 Make save a no-op, just record what would have been changed.
1181
1182 =item C<AUG_NO_LOAD> = 32
1183
1184 Do not load the tree in C<guestfs_aug_init>.
1185
1186 =back
1187
1188 To close the handle, you can call C<guestfs_aug_close>.
1189
1190 To find out more about Augeas, see L<http://augeas.net/>.");
1191
1192   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1193    [], (* XXX Augeas code needs tests. *)
1194    "close the current Augeas handle",
1195    "\
1196 Close the current Augeas handle and free up any resources
1197 used by it.  After calling this, you have to call
1198 C<guestfs_aug_init> again before you can use any other
1199 Augeas functions.");
1200
1201   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1202    [], (* XXX Augeas code needs tests. *)
1203    "define an Augeas variable",
1204    "\
1205 Defines an Augeas variable C<name> whose value is the result
1206 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1207 undefined.
1208
1209 On success this returns the number of nodes in C<expr>, or
1210 C<0> if C<expr> evaluates to something which is not a nodeset.");
1211
1212   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1213    [], (* XXX Augeas code needs tests. *)
1214    "define an Augeas node",
1215    "\
1216 Defines a variable C<name> whose value is the result of
1217 evaluating C<expr>.
1218
1219 If C<expr> evaluates to an empty nodeset, a node is created,
1220 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1221 C<name> will be the nodeset containing that single node.
1222
1223 On success this returns a pair containing the
1224 number of nodes in the nodeset, and a boolean flag
1225 if a node was created.");
1226
1227   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "look up the value of an Augeas path",
1230    "\
1231 Look up the value associated with C<path>.  If C<path>
1232 matches exactly one node, the C<value> is returned.");
1233
1234   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1235    [], (* XXX Augeas code needs tests. *)
1236    "set Augeas path to value",
1237    "\
1238 Set the value associated with C<path> to C<value>.");
1239
1240   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1241    [], (* XXX Augeas code needs tests. *)
1242    "insert a sibling Augeas node",
1243    "\
1244 Create a new sibling C<label> for C<path>, inserting it into
1245 the tree before or after C<path> (depending on the boolean
1246 flag C<before>).
1247
1248 C<path> must match exactly one existing node in the tree, and
1249 C<label> must be a label, ie. not contain C</>, C<*> or end
1250 with a bracketed index C<[N]>.");
1251
1252   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1253    [], (* XXX Augeas code needs tests. *)
1254    "remove an Augeas path",
1255    "\
1256 Remove C<path> and all of its children.
1257
1258 On success this returns the number of entries which were removed.");
1259
1260   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "move Augeas node",
1263    "\
1264 Move the node C<src> to C<dest>.  C<src> must match exactly
1265 one node.  C<dest> is overwritten if it exists.");
1266
1267   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1268    [], (* XXX Augeas code needs tests. *)
1269    "return Augeas nodes which match augpath",
1270    "\
1271 Returns a list of paths which match the path expression C<path>.
1272 The returned paths are sufficiently qualified so that they match
1273 exactly one node in the current tree.");
1274
1275   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "write all pending Augeas changes to disk",
1278    "\
1279 This writes all pending changes to disk.
1280
1281 The flags which were passed to C<guestfs_aug_init> affect exactly
1282 how files are saved.");
1283
1284   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1285    [], (* XXX Augeas code needs tests. *)
1286    "load files into the tree",
1287    "\
1288 Load files into the tree.
1289
1290 See C<aug_load> in the Augeas documentation for the full gory
1291 details.");
1292
1293   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1294    [], (* XXX Augeas code needs tests. *)
1295    "list Augeas nodes under augpath",
1296    "\
1297 This is just a shortcut for listing C<guestfs_aug_match>
1298 C<path/*> and sorting the resulting nodes into alphabetical order.");
1299
1300   ("rm", (RErr, [Pathname "path"]), 29, [],
1301    [InitBasicFS, Always, TestRun
1302       [["touch"; "/new"];
1303        ["rm"; "/new"]];
1304     InitBasicFS, Always, TestLastFail
1305       [["rm"; "/new"]];
1306     InitBasicFS, Always, TestLastFail
1307       [["mkdir"; "/new"];
1308        ["rm"; "/new"]]],
1309    "remove a file",
1310    "\
1311 Remove the single file C<path>.");
1312
1313   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1314    [InitBasicFS, Always, TestRun
1315       [["mkdir"; "/new"];
1316        ["rmdir"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["rmdir"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["touch"; "/new"];
1321        ["rmdir"; "/new"]]],
1322    "remove a directory",
1323    "\
1324 Remove the single directory C<path>.");
1325
1326   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1327    [InitBasicFS, Always, TestOutputFalse
1328       [["mkdir"; "/new"];
1329        ["mkdir"; "/new/foo"];
1330        ["touch"; "/new/foo/bar"];
1331        ["rm_rf"; "/new"];
1332        ["exists"; "/new"]]],
1333    "remove a file or directory recursively",
1334    "\
1335 Remove the file or directory C<path>, recursively removing the
1336 contents if its a directory.  This is like the C<rm -rf> shell
1337 command.");
1338
1339   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1340    [InitBasicFS, Always, TestOutputTrue
1341       [["mkdir"; "/new"];
1342        ["is_dir"; "/new"]];
1343     InitBasicFS, Always, TestLastFail
1344       [["mkdir"; "/new/foo/bar"]]],
1345    "create a directory",
1346    "\
1347 Create a directory named C<path>.");
1348
1349   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1350    [InitBasicFS, Always, TestOutputTrue
1351       [["mkdir_p"; "/new/foo/bar"];
1352        ["is_dir"; "/new/foo/bar"]];
1353     InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new"]];
1359     (* Regression tests for RHBZ#503133: *)
1360     InitBasicFS, Always, TestRun
1361       [["mkdir"; "/new"];
1362        ["mkdir_p"; "/new"]];
1363     InitBasicFS, Always, TestLastFail
1364       [["touch"; "/new"];
1365        ["mkdir_p"; "/new"]]],
1366    "create a directory and parents",
1367    "\
1368 Create a directory named C<path>, creating any parent directories
1369 as necessary.  This is like the C<mkdir -p> shell command.");
1370
1371   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1372    [], (* XXX Need stat command to test *)
1373    "change file mode",
1374    "\
1375 Change the mode (permissions) of C<path> to C<mode>.  Only
1376 numeric modes are supported.
1377
1378 I<Note>: When using this command from guestfish, C<mode>
1379 by default would be decimal, unless you prefix it with
1380 C<0> to get octal, ie. use C<0700> not C<700>.");
1381
1382   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1383    [], (* XXX Need stat command to test *)
1384    "change file owner and group",
1385    "\
1386 Change the file owner to C<owner> and group to C<group>.
1387
1388 Only numeric uid and gid are supported.  If you want to use
1389 names, you will need to locate and parse the password file
1390 yourself (Augeas support makes this relatively easy).");
1391
1392   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1393    [InitISOFS, Always, TestOutputTrue (
1394       [["exists"; "/empty"]]);
1395     InitISOFS, Always, TestOutputTrue (
1396       [["exists"; "/directory"]])],
1397    "test if file or directory exists",
1398    "\
1399 This returns C<true> if and only if there is a file, directory
1400 (or anything) with the given C<path> name.
1401
1402 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1403
1404   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1405    [InitISOFS, Always, TestOutputTrue (
1406       [["is_file"; "/known-1"]]);
1407     InitISOFS, Always, TestOutputFalse (
1408       [["is_file"; "/directory"]])],
1409    "test if file exists",
1410    "\
1411 This returns C<true> if and only if there is a file
1412 with the given C<path> name.  Note that it returns false for
1413 other objects like directories.
1414
1415 See also C<guestfs_stat>.");
1416
1417   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1418    [InitISOFS, Always, TestOutputFalse (
1419       [["is_dir"; "/known-3"]]);
1420     InitISOFS, Always, TestOutputTrue (
1421       [["is_dir"; "/directory"]])],
1422    "test if file exists",
1423    "\
1424 This returns C<true> if and only if there is a directory
1425 with the given C<path> name.  Note that it returns false for
1426 other objects like files.
1427
1428 See also C<guestfs_stat>.");
1429
1430   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1431    [InitEmpty, Always, TestOutputListOfDevices (
1432       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1433        ["pvcreate"; "/dev/sda1"];
1434        ["pvcreate"; "/dev/sda2"];
1435        ["pvcreate"; "/dev/sda3"];
1436        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1437    "create an LVM physical volume",
1438    "\
1439 This creates an LVM physical volume on the named C<device>,
1440 where C<device> should usually be a partition name such
1441 as C</dev/sda1>.");
1442
1443   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1444    [InitEmpty, Always, TestOutputList (
1445       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446        ["pvcreate"; "/dev/sda1"];
1447        ["pvcreate"; "/dev/sda2"];
1448        ["pvcreate"; "/dev/sda3"];
1449        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1450        ["vgcreate"; "VG2"; "/dev/sda3"];
1451        ["vgs"]], ["VG1"; "VG2"])],
1452    "create an LVM volume group",
1453    "\
1454 This creates an LVM volume group called C<volgroup>
1455 from the non-empty list of physical volumes C<physvols>.");
1456
1457   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1458    [InitEmpty, Always, TestOutputList (
1459       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1460        ["pvcreate"; "/dev/sda1"];
1461        ["pvcreate"; "/dev/sda2"];
1462        ["pvcreate"; "/dev/sda3"];
1463        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1464        ["vgcreate"; "VG2"; "/dev/sda3"];
1465        ["lvcreate"; "LV1"; "VG1"; "50"];
1466        ["lvcreate"; "LV2"; "VG1"; "50"];
1467        ["lvcreate"; "LV3"; "VG2"; "50"];
1468        ["lvcreate"; "LV4"; "VG2"; "50"];
1469        ["lvcreate"; "LV5"; "VG2"; "50"];
1470        ["lvs"]],
1471       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1472        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1473    "create an LVM volume group",
1474    "\
1475 This creates an LVM volume group called C<logvol>
1476 on the volume group C<volgroup>, with C<size> megabytes.");
1477
1478   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1479    [InitEmpty, Always, TestOutput (
1480       [["part_disk"; "/dev/sda"; "mbr"];
1481        ["mkfs"; "ext2"; "/dev/sda1"];
1482        ["mount_options"; ""; "/dev/sda1"; "/"];
1483        ["write_file"; "/new"; "new file contents"; "0"];
1484        ["cat"; "/new"]], "new file contents")],
1485    "make a filesystem",
1486    "\
1487 This creates a filesystem on C<device> (usually a partition
1488 or LVM logical volume).  The filesystem type is C<fstype>, for
1489 example C<ext3>.");
1490
1491   ("sfdisk", (RErr, [Device "device";
1492                      Int "cyls"; Int "heads"; Int "sectors";
1493                      StringList "lines"]), 43, [DangerWillRobinson],
1494    [],
1495    "create partitions on a block device",
1496    "\
1497 This is a direct interface to the L<sfdisk(8)> program for creating
1498 partitions on block devices.
1499
1500 C<device> should be a block device, for example C</dev/sda>.
1501
1502 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1503 and sectors on the device, which are passed directly to sfdisk as
1504 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1505 of these, then the corresponding parameter is omitted.  Usually for
1506 'large' disks, you can just pass C<0> for these, but for small
1507 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1508 out the right geometry and you will need to tell it.
1509
1510 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1511 information refer to the L<sfdisk(8)> manpage.
1512
1513 To create a single partition occupying the whole disk, you would
1514 pass C<lines> as a single element list, when the single element being
1515 the string C<,> (comma).
1516
1517 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1518 C<guestfs_part_init>");
1519
1520   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1521    [InitBasicFS, Always, TestOutput (
1522       [["write_file"; "/new"; "new file contents"; "0"];
1523        ["cat"; "/new"]], "new file contents");
1524     InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1526        ["cat"; "/new"]], "\nnew file contents\n");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\n\n"; "0"];
1529        ["cat"; "/new"]], "\n\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; ""; "0"];
1532        ["cat"; "/new"]], "");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; "\n\n\n"; "0"];
1535        ["cat"; "/new"]], "\n\n\n");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n"; "0"];
1538        ["cat"; "/new"]], "\n")],
1539    "create a file",
1540    "\
1541 This call creates a file called C<path>.  The contents of the
1542 file is the string C<content> (which can contain any 8 bit data),
1543 with length C<size>.
1544
1545 As a special case, if C<size> is C<0>
1546 then the length is calculated using C<strlen> (so in this case
1547 the content cannot contain embedded ASCII NULs).
1548
1549 I<NB.> Owing to a bug, writing content containing ASCII NUL
1550 characters does I<not> work, even if the length is specified.
1551 We hope to resolve this bug in a future version.  In the meantime
1552 use C<guestfs_upload>.");
1553
1554   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1555    [InitEmpty, Always, TestOutputListOfDevices (
1556       [["part_disk"; "/dev/sda"; "mbr"];
1557        ["mkfs"; "ext2"; "/dev/sda1"];
1558        ["mount_options"; ""; "/dev/sda1"; "/"];
1559        ["mounts"]], ["/dev/sda1"]);
1560     InitEmpty, Always, TestOutputList (
1561       [["part_disk"; "/dev/sda"; "mbr"];
1562        ["mkfs"; "ext2"; "/dev/sda1"];
1563        ["mount_options"; ""; "/dev/sda1"; "/"];
1564        ["umount"; "/"];
1565        ["mounts"]], [])],
1566    "unmount a filesystem",
1567    "\
1568 This unmounts the given filesystem.  The filesystem may be
1569 specified either by its mountpoint (path) or the device which
1570 contains the filesystem.");
1571
1572   ("mounts", (RStringList "devices", []), 46, [],
1573    [InitBasicFS, Always, TestOutputListOfDevices (
1574       [["mounts"]], ["/dev/sda1"])],
1575    "show mounted filesystems",
1576    "\
1577 This returns the list of currently mounted filesystems.  It returns
1578 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1579
1580 Some internal mounts are not shown.
1581
1582 See also: C<guestfs_mountpoints>");
1583
1584   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1585    [InitBasicFS, Always, TestOutputList (
1586       [["umount_all"];
1587        ["mounts"]], []);
1588     (* check that umount_all can unmount nested mounts correctly: *)
1589     InitEmpty, Always, TestOutputList (
1590       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1591        ["mkfs"; "ext2"; "/dev/sda1"];
1592        ["mkfs"; "ext2"; "/dev/sda2"];
1593        ["mkfs"; "ext2"; "/dev/sda3"];
1594        ["mount_options"; ""; "/dev/sda1"; "/"];
1595        ["mkdir"; "/mp1"];
1596        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1597        ["mkdir"; "/mp1/mp2"];
1598        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1599        ["mkdir"; "/mp1/mp2/mp3"];
1600        ["umount_all"];
1601        ["mounts"]], [])],
1602    "unmount all filesystems",
1603    "\
1604 This unmounts all mounted filesystems.
1605
1606 Some internal mounts are not unmounted by this call.");
1607
1608   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1609    [],
1610    "remove all LVM LVs, VGs and PVs",
1611    "\
1612 This command removes all LVM logical volumes, volume groups
1613 and physical volumes.");
1614
1615   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1616    [InitISOFS, Always, TestOutput (
1617       [["file"; "/empty"]], "empty");
1618     InitISOFS, Always, TestOutput (
1619       [["file"; "/known-1"]], "ASCII text");
1620     InitISOFS, Always, TestLastFail (
1621       [["file"; "/notexists"]])],
1622    "determine file type",
1623    "\
1624 This call uses the standard L<file(1)> command to determine
1625 the type or contents of the file.  This also works on devices,
1626 for example to find out whether a partition contains a filesystem.
1627
1628 This call will also transparently look inside various types
1629 of compressed file.
1630
1631 The exact command which runs is C<file -zbsL path>.  Note in
1632 particular that the filename is not prepended to the output
1633 (the C<-b> option).");
1634
1635   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1636    [InitBasicFS, Always, TestOutput (
1637       [["upload"; "test-command"; "/test-command"];
1638        ["chmod"; "0o755"; "/test-command"];
1639        ["command"; "/test-command 1"]], "Result1");
1640     InitBasicFS, Always, TestOutput (
1641       [["upload"; "test-command"; "/test-command"];
1642        ["chmod"; "0o755"; "/test-command"];
1643        ["command"; "/test-command 2"]], "Result2\n");
1644     InitBasicFS, Always, TestOutput (
1645       [["upload"; "test-command"; "/test-command"];
1646        ["chmod"; "0o755"; "/test-command"];
1647        ["command"; "/test-command 3"]], "\nResult3");
1648     InitBasicFS, Always, TestOutput (
1649       [["upload"; "test-command"; "/test-command"];
1650        ["chmod"; "0o755"; "/test-command"];
1651        ["command"; "/test-command 4"]], "\nResult4\n");
1652     InitBasicFS, Always, TestOutput (
1653       [["upload"; "test-command"; "/test-command"];
1654        ["chmod"; "0o755"; "/test-command"];
1655        ["command"; "/test-command 5"]], "\nResult5\n\n");
1656     InitBasicFS, Always, TestOutput (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1660     InitBasicFS, Always, TestOutput (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command"; "/test-command 7"]], "");
1664     InitBasicFS, Always, TestOutput (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command"; "/test-command 8"]], "\n");
1668     InitBasicFS, Always, TestOutput (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command"; "/test-command 9"]], "\n\n");
1672     InitBasicFS, Always, TestOutput (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1676     InitBasicFS, Always, TestOutput (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1680     InitBasicFS, Always, TestLastFail (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command"; "/test-command"]])],
1684    "run a command from the guest filesystem",
1685    "\
1686 This call runs a command from the guest filesystem.  The
1687 filesystem must be mounted, and must contain a compatible
1688 operating system (ie. something Linux, with the same
1689 or compatible processor architecture).
1690
1691 The single parameter is an argv-style list of arguments.
1692 The first element is the name of the program to run.
1693 Subsequent elements are parameters.  The list must be
1694 non-empty (ie. must contain a program name).  Note that
1695 the command runs directly, and is I<not> invoked via
1696 the shell (see C<guestfs_sh>).
1697
1698 The return value is anything printed to I<stdout> by
1699 the command.
1700
1701 If the command returns a non-zero exit status, then
1702 this function returns an error message.  The error message
1703 string is the content of I<stderr> from the command.
1704
1705 The C<$PATH> environment variable will contain at least
1706 C</usr/bin> and C</bin>.  If you require a program from
1707 another location, you should provide the full path in the
1708 first parameter.
1709
1710 Shared libraries and data files required by the program
1711 must be available on filesystems which are mounted in the
1712 correct places.  It is the caller's responsibility to ensure
1713 all filesystems that are needed are mounted at the right
1714 locations.");
1715
1716   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1717    [InitBasicFS, Always, TestOutputList (
1718       [["upload"; "test-command"; "/test-command"];
1719        ["chmod"; "0o755"; "/test-command"];
1720        ["command_lines"; "/test-command 1"]], ["Result1"]);
1721     InitBasicFS, Always, TestOutputList (
1722       [["upload"; "test-command"; "/test-command"];
1723        ["chmod"; "0o755"; "/test-command"];
1724        ["command_lines"; "/test-command 2"]], ["Result2"]);
1725     InitBasicFS, Always, TestOutputList (
1726       [["upload"; "test-command"; "/test-command"];
1727        ["chmod"; "0o755"; "/test-command"];
1728        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1729     InitBasicFS, Always, TestOutputList (
1730       [["upload"; "test-command"; "/test-command"];
1731        ["chmod"; "0o755"; "/test-command"];
1732        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1733     InitBasicFS, Always, TestOutputList (
1734       [["upload"; "test-command"; "/test-command"];
1735        ["chmod"; "0o755"; "/test-command"];
1736        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1737     InitBasicFS, Always, TestOutputList (
1738       [["upload"; "test-command"; "/test-command"];
1739        ["chmod"; "0o755"; "/test-command"];
1740        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1741     InitBasicFS, Always, TestOutputList (
1742       [["upload"; "test-command"; "/test-command"];
1743        ["chmod"; "0o755"; "/test-command"];
1744        ["command_lines"; "/test-command 7"]], []);
1745     InitBasicFS, Always, TestOutputList (
1746       [["upload"; "test-command"; "/test-command"];
1747        ["chmod"; "0o755"; "/test-command"];
1748        ["command_lines"; "/test-command 8"]], [""]);
1749     InitBasicFS, Always, TestOutputList (
1750       [["upload"; "test-command"; "/test-command"];
1751        ["chmod"; "0o755"; "/test-command"];
1752        ["command_lines"; "/test-command 9"]], ["";""]);
1753     InitBasicFS, Always, TestOutputList (
1754       [["upload"; "test-command"; "/test-command"];
1755        ["chmod"; "0o755"; "/test-command"];
1756        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1757     InitBasicFS, Always, TestOutputList (
1758       [["upload"; "test-command"; "/test-command"];
1759        ["chmod"; "0o755"; "/test-command"];
1760        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1761    "run a command, returning lines",
1762    "\
1763 This is the same as C<guestfs_command>, but splits the
1764 result into a list of lines.
1765
1766 See also: C<guestfs_sh_lines>");
1767
1768   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1769    [InitISOFS, Always, TestOutputStruct (
1770       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1771    "get file information",
1772    "\
1773 Returns file information for the given C<path>.
1774
1775 This is the same as the C<stat(2)> system call.");
1776
1777   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1778    [InitISOFS, Always, TestOutputStruct (
1779       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1780    "get file information for a symbolic link",
1781    "\
1782 Returns file information for the given C<path>.
1783
1784 This is the same as C<guestfs_stat> except that if C<path>
1785 is a symbolic link, then the link is stat-ed, not the file it
1786 refers to.
1787
1788 This is the same as the C<lstat(2)> system call.");
1789
1790   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1793    "get file system statistics",
1794    "\
1795 Returns file system statistics for any mounted file system.
1796 C<path> should be a file or directory in the mounted file system
1797 (typically it is the mount point itself, but it doesn't need to be).
1798
1799 This is the same as the C<statvfs(2)> system call.");
1800
1801   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1802    [], (* XXX test *)
1803    "get ext2/ext3/ext4 superblock details",
1804    "\
1805 This returns the contents of the ext2, ext3 or ext4 filesystem
1806 superblock on C<device>.
1807
1808 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1809 manpage for more details.  The list of fields returned isn't
1810 clearly defined, and depends on both the version of C<tune2fs>
1811 that libguestfs was built against, and the filesystem itself.");
1812
1813   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1814    [InitEmpty, Always, TestOutputTrue (
1815       [["blockdev_setro"; "/dev/sda"];
1816        ["blockdev_getro"; "/dev/sda"]])],
1817    "set block device to read-only",
1818    "\
1819 Sets the block device named C<device> to read-only.
1820
1821 This uses the L<blockdev(8)> command.");
1822
1823   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1824    [InitEmpty, Always, TestOutputFalse (
1825       [["blockdev_setrw"; "/dev/sda"];
1826        ["blockdev_getro"; "/dev/sda"]])],
1827    "set block device to read-write",
1828    "\
1829 Sets the block device named C<device> to read-write.
1830
1831 This uses the L<blockdev(8)> command.");
1832
1833   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1834    [InitEmpty, Always, TestOutputTrue (
1835       [["blockdev_setro"; "/dev/sda"];
1836        ["blockdev_getro"; "/dev/sda"]])],
1837    "is block device set to read-only",
1838    "\
1839 Returns a boolean indicating if the block device is read-only
1840 (true if read-only, false if not).
1841
1842 This uses the L<blockdev(8)> command.");
1843
1844   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1845    [InitEmpty, Always, TestOutputInt (
1846       [["blockdev_getss"; "/dev/sda"]], 512)],
1847    "get sectorsize of block device",
1848    "\
1849 This returns the size of sectors on a block device.
1850 Usually 512, but can be larger for modern devices.
1851
1852 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1853 for that).
1854
1855 This uses the L<blockdev(8)> command.");
1856
1857   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1858    [InitEmpty, Always, TestOutputInt (
1859       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1860    "get blocksize of block device",
1861    "\
1862 This returns the block size of a device.
1863
1864 (Note this is different from both I<size in blocks> and
1865 I<filesystem block size>).
1866
1867 This uses the L<blockdev(8)> command.");
1868
1869   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1870    [], (* XXX test *)
1871    "set blocksize of block device",
1872    "\
1873 This sets the block size of a device.
1874
1875 (Note this is different from both I<size in blocks> and
1876 I<filesystem block size>).
1877
1878 This uses the L<blockdev(8)> command.");
1879
1880   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1881    [InitEmpty, Always, TestOutputInt (
1882       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1883    "get total size of device in 512-byte sectors",
1884    "\
1885 This returns the size of the device in units of 512-byte sectors
1886 (even if the sectorsize isn't 512 bytes ... weird).
1887
1888 See also C<guestfs_blockdev_getss> for the real sector size of
1889 the device, and C<guestfs_blockdev_getsize64> for the more
1890 useful I<size in bytes>.
1891
1892 This uses the L<blockdev(8)> command.");
1893
1894   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1895    [InitEmpty, Always, TestOutputInt (
1896       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1897    "get total size of device in bytes",
1898    "\
1899 This returns the size of the device in bytes.
1900
1901 See also C<guestfs_blockdev_getsz>.
1902
1903 This uses the L<blockdev(8)> command.");
1904
1905   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1906    [InitEmpty, Always, TestRun
1907       [["blockdev_flushbufs"; "/dev/sda"]]],
1908    "flush device buffers",
1909    "\
1910 This tells the kernel to flush internal buffers associated
1911 with C<device>.
1912
1913 This uses the L<blockdev(8)> command.");
1914
1915   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1916    [InitEmpty, Always, TestRun
1917       [["blockdev_rereadpt"; "/dev/sda"]]],
1918    "reread partition table",
1919    "\
1920 Reread the partition table on C<device>.
1921
1922 This uses the L<blockdev(8)> command.");
1923
1924   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1925    [InitBasicFS, Always, TestOutput (
1926       (* Pick a file from cwd which isn't likely to change. *)
1927       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1928        ["checksum"; "md5"; "/COPYING.LIB"]],
1929       Digest.to_hex (Digest.file "COPYING.LIB"))],
1930    "upload a file from the local machine",
1931    "\
1932 Upload local file C<filename> to C<remotefilename> on the
1933 filesystem.
1934
1935 C<filename> can also be a named pipe.
1936
1937 See also C<guestfs_download>.");
1938
1939   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1940    [InitBasicFS, Always, TestOutput (
1941       (* Pick a file from cwd which isn't likely to change. *)
1942       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1944        ["upload"; "testdownload.tmp"; "/upload"];
1945        ["checksum"; "md5"; "/upload"]],
1946       Digest.to_hex (Digest.file "COPYING.LIB"))],
1947    "download a file to the local machine",
1948    "\
1949 Download file C<remotefilename> and save it as C<filename>
1950 on the local machine.
1951
1952 C<filename> can also be a named pipe.
1953
1954 See also C<guestfs_upload>, C<guestfs_cat>.");
1955
1956   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1957    [InitISOFS, Always, TestOutput (
1958       [["checksum"; "crc"; "/known-3"]], "2891671662");
1959     InitISOFS, Always, TestLastFail (
1960       [["checksum"; "crc"; "/notexists"]]);
1961     InitISOFS, Always, TestOutput (
1962       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1963     InitISOFS, Always, TestOutput (
1964       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1965     InitISOFS, Always, TestOutput (
1966       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1973    "compute MD5, SHAx or CRC checksum of file",
1974    "\
1975 This call computes the MD5, SHAx or CRC checksum of the
1976 file named C<path>.
1977
1978 The type of checksum to compute is given by the C<csumtype>
1979 parameter which must have one of the following values:
1980
1981 =over 4
1982
1983 =item C<crc>
1984
1985 Compute the cyclic redundancy check (CRC) specified by POSIX
1986 for the C<cksum> command.
1987
1988 =item C<md5>
1989
1990 Compute the MD5 hash (using the C<md5sum> program).
1991
1992 =item C<sha1>
1993
1994 Compute the SHA1 hash (using the C<sha1sum> program).
1995
1996 =item C<sha224>
1997
1998 Compute the SHA224 hash (using the C<sha224sum> program).
1999
2000 =item C<sha256>
2001
2002 Compute the SHA256 hash (using the C<sha256sum> program).
2003
2004 =item C<sha384>
2005
2006 Compute the SHA384 hash (using the C<sha384sum> program).
2007
2008 =item C<sha512>
2009
2010 Compute the SHA512 hash (using the C<sha512sum> program).
2011
2012 =back
2013
2014 The checksum is returned as a printable string.");
2015
2016   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2017    [InitBasicFS, Always, TestOutput (
2018       [["tar_in"; "../images/helloworld.tar"; "/"];
2019        ["cat"; "/hello"]], "hello\n")],
2020    "unpack tarfile to directory",
2021    "\
2022 This command uploads and unpacks local file C<tarfile> (an
2023 I<uncompressed> tar file) into C<directory>.
2024
2025 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2026
2027   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2028    [],
2029    "pack directory into tarfile",
2030    "\
2031 This command packs the contents of C<directory> and downloads
2032 it to local file C<tarfile>.
2033
2034 To download a compressed tarball, use C<guestfs_tgz_out>.");
2035
2036   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2037    [InitBasicFS, Always, TestOutput (
2038       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2039        ["cat"; "/hello"]], "hello\n")],
2040    "unpack compressed tarball to directory",
2041    "\
2042 This command uploads and unpacks local file C<tarball> (a
2043 I<gzip compressed> tar file) into C<directory>.
2044
2045 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2046
2047   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2048    [],
2049    "pack directory into compressed tarball",
2050    "\
2051 This command packs the contents of C<directory> and downloads
2052 it to local file C<tarball>.
2053
2054 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2055
2056   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2057    [InitBasicFS, Always, TestLastFail (
2058       [["umount"; "/"];
2059        ["mount_ro"; "/dev/sda1"; "/"];
2060        ["touch"; "/new"]]);
2061     InitBasicFS, Always, TestOutput (
2062       [["write_file"; "/new"; "data"; "0"];
2063        ["umount"; "/"];
2064        ["mount_ro"; "/dev/sda1"; "/"];
2065        ["cat"; "/new"]], "data")],
2066    "mount a guest disk, read-only",
2067    "\
2068 This is the same as the C<guestfs_mount> command, but it
2069 mounts the filesystem with the read-only (I<-o ro>) flag.");
2070
2071   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2072    [],
2073    "mount a guest disk with mount options",
2074    "\
2075 This is the same as the C<guestfs_mount> command, but it
2076 allows you to set the mount options as for the
2077 L<mount(8)> I<-o> flag.");
2078
2079   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2080    [],
2081    "mount a guest disk with mount options and vfstype",
2082    "\
2083 This is the same as the C<guestfs_mount> command, but it
2084 allows you to set both the mount options and the vfstype
2085 as for the L<mount(8)> I<-o> and I<-t> flags.");
2086
2087   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2088    [],
2089    "debugging and internals",
2090    "\
2091 The C<guestfs_debug> command exposes some internals of
2092 C<guestfsd> (the guestfs daemon) that runs inside the
2093 qemu subprocess.
2094
2095 There is no comprehensive help for this command.  You have
2096 to look at the file C<daemon/debug.c> in the libguestfs source
2097 to find out what you can do.");
2098
2099   ("lvremove", (RErr, [Device "device"]), 77, [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        ["lvremove"; "/dev/VG/LV1"];
2107        ["lvs"]], ["/dev/VG/LV2"]);
2108     InitEmpty, Always, TestOutputList (
2109       [["part_disk"; "/dev/sda"; "mbr"];
2110        ["pvcreate"; "/dev/sda1"];
2111        ["vgcreate"; "VG"; "/dev/sda1"];
2112        ["lvcreate"; "LV1"; "VG"; "50"];
2113        ["lvcreate"; "LV2"; "VG"; "50"];
2114        ["lvremove"; "/dev/VG"];
2115        ["lvs"]], []);
2116     InitEmpty, Always, TestOutputList (
2117       [["part_disk"; "/dev/sda"; "mbr"];
2118        ["pvcreate"; "/dev/sda1"];
2119        ["vgcreate"; "VG"; "/dev/sda1"];
2120        ["lvcreate"; "LV1"; "VG"; "50"];
2121        ["lvcreate"; "LV2"; "VG"; "50"];
2122        ["lvremove"; "/dev/VG"];
2123        ["vgs"]], ["VG"])],
2124    "remove an LVM logical volume",
2125    "\
2126 Remove an LVM logical volume C<device>, where C<device> is
2127 the path to the LV, such as C</dev/VG/LV>.
2128
2129 You can also remove all LVs in a volume group by specifying
2130 the VG name, C</dev/VG>.");
2131
2132   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2133    [InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["vgremove"; "VG"];
2140        ["lvs"]], []);
2141     InitEmpty, Always, TestOutputList (
2142       [["part_disk"; "/dev/sda"; "mbr"];
2143        ["pvcreate"; "/dev/sda1"];
2144        ["vgcreate"; "VG"; "/dev/sda1"];
2145        ["lvcreate"; "LV1"; "VG"; "50"];
2146        ["lvcreate"; "LV2"; "VG"; "50"];
2147        ["vgremove"; "VG"];
2148        ["vgs"]], [])],
2149    "remove an LVM volume group",
2150    "\
2151 Remove an LVM volume group C<vgname>, (for example C<VG>).
2152
2153 This also forcibly removes all logical volumes in the volume
2154 group (if any).");
2155
2156   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2157    [InitEmpty, Always, TestOutputListOfDevices (
2158       [["part_disk"; "/dev/sda"; "mbr"];
2159        ["pvcreate"; "/dev/sda1"];
2160        ["vgcreate"; "VG"; "/dev/sda1"];
2161        ["lvcreate"; "LV1"; "VG"; "50"];
2162        ["lvcreate"; "LV2"; "VG"; "50"];
2163        ["vgremove"; "VG"];
2164        ["pvremove"; "/dev/sda1"];
2165        ["lvs"]], []);
2166     InitEmpty, Always, TestOutputListOfDevices (
2167       [["part_disk"; "/dev/sda"; "mbr"];
2168        ["pvcreate"; "/dev/sda1"];
2169        ["vgcreate"; "VG"; "/dev/sda1"];
2170        ["lvcreate"; "LV1"; "VG"; "50"];
2171        ["lvcreate"; "LV2"; "VG"; "50"];
2172        ["vgremove"; "VG"];
2173        ["pvremove"; "/dev/sda1"];
2174        ["vgs"]], []);
2175     InitEmpty, Always, TestOutputListOfDevices (
2176       [["part_disk"; "/dev/sda"; "mbr"];
2177        ["pvcreate"; "/dev/sda1"];
2178        ["vgcreate"; "VG"; "/dev/sda1"];
2179        ["lvcreate"; "LV1"; "VG"; "50"];
2180        ["lvcreate"; "LV2"; "VG"; "50"];
2181        ["vgremove"; "VG"];
2182        ["pvremove"; "/dev/sda1"];
2183        ["pvs"]], [])],
2184    "remove an LVM physical volume",
2185    "\
2186 This wipes a physical volume C<device> so that LVM will no longer
2187 recognise it.
2188
2189 The implementation uses the C<pvremove> command which refuses to
2190 wipe physical volumes that contain any volume groups, so you have
2191 to remove those first.");
2192
2193   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2194    [InitBasicFS, Always, TestOutput (
2195       [["set_e2label"; "/dev/sda1"; "testlabel"];
2196        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2197    "set the ext2/3/4 filesystem label",
2198    "\
2199 This sets the ext2/3/4 filesystem label of the filesystem on
2200 C<device> to C<label>.  Filesystem labels are limited to
2201 16 characters.
2202
2203 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2204 to return the existing label on a filesystem.");
2205
2206   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2207    [],
2208    "get the ext2/3/4 filesystem label",
2209    "\
2210 This returns the ext2/3/4 filesystem label of the filesystem on
2211 C<device>.");
2212
2213   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2214    (let uuid = uuidgen () in
2215     [InitBasicFS, Always, TestOutput (
2216        [["set_e2uuid"; "/dev/sda1"; uuid];
2217         ["get_e2uuid"; "/dev/sda1"]], uuid);
2218      InitBasicFS, Always, TestOutput (
2219        [["set_e2uuid"; "/dev/sda1"; "clear"];
2220         ["get_e2uuid"; "/dev/sda1"]], "");
2221      (* We can't predict what UUIDs will be, so just check the commands run. *)
2222      InitBasicFS, Always, TestRun (
2223        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2224      InitBasicFS, Always, TestRun (
2225        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2226    "set the ext2/3/4 filesystem UUID",
2227    "\
2228 This sets the ext2/3/4 filesystem UUID of the filesystem on
2229 C<device> to C<uuid>.  The format of the UUID and alternatives
2230 such as C<clear>, C<random> and C<time> are described in the
2231 L<tune2fs(8)> manpage.
2232
2233 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2234 to return the existing UUID of a filesystem.");
2235
2236   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2237    [],
2238    "get the ext2/3/4 filesystem UUID",
2239    "\
2240 This returns the ext2/3/4 filesystem UUID of the filesystem on
2241 C<device>.");
2242
2243   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2244    [InitBasicFS, Always, TestOutputInt (
2245       [["umount"; "/dev/sda1"];
2246        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2247     InitBasicFS, Always, TestOutputInt (
2248       [["umount"; "/dev/sda1"];
2249        ["zero"; "/dev/sda1"];
2250        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2251    "run the filesystem checker",
2252    "\
2253 This runs the filesystem checker (fsck) on C<device> which
2254 should have filesystem type C<fstype>.
2255
2256 The returned integer is the status.  See L<fsck(8)> for the
2257 list of status codes from C<fsck>.
2258
2259 Notes:
2260
2261 =over 4
2262
2263 =item *
2264
2265 Multiple status codes can be summed together.
2266
2267 =item *
2268
2269 A non-zero return code can mean \"success\", for example if
2270 errors have been corrected on the filesystem.
2271
2272 =item *
2273
2274 Checking or repairing NTFS volumes is not supported
2275 (by linux-ntfs).
2276
2277 =back
2278
2279 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2280
2281   ("zero", (RErr, [Device "device"]), 85, [],
2282    [InitBasicFS, Always, TestOutput (
2283       [["umount"; "/dev/sda1"];
2284        ["zero"; "/dev/sda1"];
2285        ["file"; "/dev/sda1"]], "data")],
2286    "write zeroes to the device",
2287    "\
2288 This command writes zeroes over the first few blocks of C<device>.
2289
2290 How many blocks are zeroed isn't specified (but it's I<not> enough
2291 to securely wipe the device).  It should be sufficient to remove
2292 any partition tables, filesystem superblocks and so on.
2293
2294 See also: C<guestfs_scrub_device>.");
2295
2296   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2297    (* Test disabled because grub-install incompatible with virtio-blk driver.
2298     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2299     *)
2300    [InitBasicFS, Disabled, TestOutputTrue (
2301       [["grub_install"; "/"; "/dev/sda1"];
2302        ["is_dir"; "/boot"]])],
2303    "install GRUB",
2304    "\
2305 This command installs GRUB (the Grand Unified Bootloader) on
2306 C<device>, with the root directory being C<root>.");
2307
2308   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2309    [InitBasicFS, Always, TestOutput (
2310       [["write_file"; "/old"; "file content"; "0"];
2311        ["cp"; "/old"; "/new"];
2312        ["cat"; "/new"]], "file content");
2313     InitBasicFS, Always, TestOutputTrue (
2314       [["write_file"; "/old"; "file content"; "0"];
2315        ["cp"; "/old"; "/new"];
2316        ["is_file"; "/old"]]);
2317     InitBasicFS, Always, TestOutput (
2318       [["write_file"; "/old"; "file content"; "0"];
2319        ["mkdir"; "/dir"];
2320        ["cp"; "/old"; "/dir/new"];
2321        ["cat"; "/dir/new"]], "file content")],
2322    "copy a file",
2323    "\
2324 This copies a file from C<src> to C<dest> where C<dest> is
2325 either a destination filename or destination directory.");
2326
2327   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2328    [InitBasicFS, Always, TestOutput (
2329       [["mkdir"; "/olddir"];
2330        ["mkdir"; "/newdir"];
2331        ["write_file"; "/olddir/file"; "file content"; "0"];
2332        ["cp_a"; "/olddir"; "/newdir"];
2333        ["cat"; "/newdir/olddir/file"]], "file content")],
2334    "copy a file or directory recursively",
2335    "\
2336 This copies a file or directory from C<src> to C<dest>
2337 recursively using the C<cp -a> command.");
2338
2339   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2340    [InitBasicFS, Always, TestOutput (
2341       [["write_file"; "/old"; "file content"; "0"];
2342        ["mv"; "/old"; "/new"];
2343        ["cat"; "/new"]], "file content");
2344     InitBasicFS, Always, TestOutputFalse (
2345       [["write_file"; "/old"; "file content"; "0"];
2346        ["mv"; "/old"; "/new"];
2347        ["is_file"; "/old"]])],
2348    "move a file",
2349    "\
2350 This moves a file from C<src> to C<dest> where C<dest> is
2351 either a destination filename or destination directory.");
2352
2353   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2354    [InitEmpty, Always, TestRun (
2355       [["drop_caches"; "3"]])],
2356    "drop kernel page cache, dentries and inodes",
2357    "\
2358 This instructs the guest kernel to drop its page cache,
2359 and/or dentries and inode caches.  The parameter C<whattodrop>
2360 tells the kernel what precisely to drop, see
2361 L<http://linux-mm.org/Drop_Caches>
2362
2363 Setting C<whattodrop> to 3 should drop everything.
2364
2365 This automatically calls L<sync(2)> before the operation,
2366 so that the maximum guest memory is freed.");
2367
2368   ("dmesg", (RString "kmsgs", []), 91, [],
2369    [InitEmpty, Always, TestRun (
2370       [["dmesg"]])],
2371    "return kernel messages",
2372    "\
2373 This returns the kernel messages (C<dmesg> output) from
2374 the guest kernel.  This is sometimes useful for extended
2375 debugging of problems.
2376
2377 Another way to get the same information is to enable
2378 verbose messages with C<guestfs_set_verbose> or by setting
2379 the environment variable C<LIBGUESTFS_DEBUG=1> before
2380 running the program.");
2381
2382   ("ping_daemon", (RErr, []), 92, [],
2383    [InitEmpty, Always, TestRun (
2384       [["ping_daemon"]])],
2385    "ping the guest daemon",
2386    "\
2387 This is a test probe into the guestfs daemon running inside
2388 the qemu subprocess.  Calling this function checks that the
2389 daemon responds to the ping message, without affecting the daemon
2390 or attached block device(s) in any other way.");
2391
2392   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2393    [InitBasicFS, Always, TestOutputTrue (
2394       [["write_file"; "/file1"; "contents of a file"; "0"];
2395        ["cp"; "/file1"; "/file2"];
2396        ["equal"; "/file1"; "/file2"]]);
2397     InitBasicFS, Always, TestOutputFalse (
2398       [["write_file"; "/file1"; "contents of a file"; "0"];
2399        ["write_file"; "/file2"; "contents of another file"; "0"];
2400        ["equal"; "/file1"; "/file2"]]);
2401     InitBasicFS, Always, TestLastFail (
2402       [["equal"; "/file1"; "/file2"]])],
2403    "test if two files have equal contents",
2404    "\
2405 This compares the two files C<file1> and C<file2> and returns
2406 true if their content is exactly equal, or false otherwise.
2407
2408 The external L<cmp(1)> program is used for the comparison.");
2409
2410   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2411    [InitISOFS, Always, TestOutputList (
2412       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2413     InitISOFS, Always, TestOutputList (
2414       [["strings"; "/empty"]], [])],
2415    "print the printable strings in a file",
2416    "\
2417 This runs the L<strings(1)> command on a file and returns
2418 the list of printable strings found.");
2419
2420   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2421    [InitISOFS, Always, TestOutputList (
2422       [["strings_e"; "b"; "/known-5"]], []);
2423     InitBasicFS, Disabled, TestOutputList (
2424       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2425        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2426    "print the printable strings in a file",
2427    "\
2428 This is like the C<guestfs_strings> command, but allows you to
2429 specify the encoding.
2430
2431 See the L<strings(1)> manpage for the full list of encodings.
2432
2433 Commonly useful encodings are C<l> (lower case L) which will
2434 show strings inside Windows/x86 files.
2435
2436 The returned strings are transcoded to UTF-8.");
2437
2438   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2439    [InitISOFS, Always, TestOutput (
2440       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2441     (* Test for RHBZ#501888c2 regression which caused large hexdump
2442      * commands to segfault.
2443      *)
2444     InitISOFS, Always, TestRun (
2445       [["hexdump"; "/100krandom"]])],
2446    "dump a file in hexadecimal",
2447    "\
2448 This runs C<hexdump -C> on the given C<path>.  The result is
2449 the human-readable, canonical hex dump of the file.");
2450
2451   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2452    [InitNone, Always, TestOutput (
2453       [["part_disk"; "/dev/sda"; "mbr"];
2454        ["mkfs"; "ext3"; "/dev/sda1"];
2455        ["mount_options"; ""; "/dev/sda1"; "/"];
2456        ["write_file"; "/new"; "test file"; "0"];
2457        ["umount"; "/dev/sda1"];
2458        ["zerofree"; "/dev/sda1"];
2459        ["mount_options"; ""; "/dev/sda1"; "/"];
2460        ["cat"; "/new"]], "test file")],
2461    "zero unused inodes and disk blocks on ext2/3 filesystem",
2462    "\
2463 This runs the I<zerofree> program on C<device>.  This program
2464 claims to zero unused inodes and disk blocks on an ext2/3
2465 filesystem, thus making it possible to compress the filesystem
2466 more effectively.
2467
2468 You should B<not> run this program if the filesystem is
2469 mounted.
2470
2471 It is possible that using this program can damage the filesystem
2472 or data on the filesystem.");
2473
2474   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2475    [],
2476    "resize an LVM physical volume",
2477    "\
2478 This resizes (expands or shrinks) an existing LVM physical
2479 volume to match the new size of the underlying device.");
2480
2481   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2482                        Int "cyls"; Int "heads"; Int "sectors";
2483                        String "line"]), 99, [DangerWillRobinson],
2484    [],
2485    "modify a single partition on a block device",
2486    "\
2487 This runs L<sfdisk(8)> option to modify just the single
2488 partition C<n> (note: C<n> counts from 1).
2489
2490 For other parameters, see C<guestfs_sfdisk>.  You should usually
2491 pass C<0> for the cyls/heads/sectors parameters.
2492
2493 See also: C<guestfs_part_add>");
2494
2495   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2496    [],
2497    "display the partition table",
2498    "\
2499 This displays the partition table on C<device>, in the
2500 human-readable output of the L<sfdisk(8)> command.  It is
2501 not intended to be parsed.
2502
2503 See also: C<guestfs_part_list>");
2504
2505   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2506    [],
2507    "display the kernel geometry",
2508    "\
2509 This displays the kernel's idea of the geometry of C<device>.
2510
2511 The result is in human-readable format, and not designed to
2512 be parsed.");
2513
2514   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2515    [],
2516    "display the disk geometry from the partition table",
2517    "\
2518 This displays the disk geometry of C<device> read from the
2519 partition table.  Especially in the case where the underlying
2520 block device has been resized, this can be different from the
2521 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2522
2523 The result is in human-readable format, and not designed to
2524 be parsed.");
2525
2526   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2527    [],
2528    "activate or deactivate all volume groups",
2529    "\
2530 This command activates or (if C<activate> is false) deactivates
2531 all logical volumes in all volume groups.
2532 If activated, then they are made known to the
2533 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2534 then those devices disappear.
2535
2536 This command is the same as running C<vgchange -a y|n>");
2537
2538   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2539    [],
2540    "activate or deactivate some volume groups",
2541    "\
2542 This command activates or (if C<activate> is false) deactivates
2543 all logical volumes in the listed volume groups C<volgroups>.
2544 If activated, then they are made known to the
2545 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2546 then those devices disappear.
2547
2548 This command is the same as running C<vgchange -a y|n volgroups...>
2549
2550 Note that if C<volgroups> is an empty list then B<all> volume groups
2551 are activated or deactivated.");
2552
2553   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2554    [InitNone, Always, TestOutput (
2555       [["part_disk"; "/dev/sda"; "mbr"];
2556        ["pvcreate"; "/dev/sda1"];
2557        ["vgcreate"; "VG"; "/dev/sda1"];
2558        ["lvcreate"; "LV"; "VG"; "10"];
2559        ["mkfs"; "ext2"; "/dev/VG/LV"];
2560        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2561        ["write_file"; "/new"; "test content"; "0"];
2562        ["umount"; "/"];
2563        ["lvresize"; "/dev/VG/LV"; "20"];
2564        ["e2fsck_f"; "/dev/VG/LV"];
2565        ["resize2fs"; "/dev/VG/LV"];
2566        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2567        ["cat"; "/new"]], "test content")],
2568    "resize an LVM logical volume",
2569    "\
2570 This resizes (expands or shrinks) an existing LVM logical
2571 volume to C<mbytes>.  When reducing, data in the reduced part
2572 is lost.");
2573
2574   ("resize2fs", (RErr, [Device "device"]), 106, [],
2575    [], (* lvresize tests this *)
2576    "resize an ext2/ext3 filesystem",
2577    "\
2578 This resizes an ext2 or ext3 filesystem to match the size of
2579 the underlying device.
2580
2581 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2582 on the C<device> before calling this command.  For unknown reasons
2583 C<resize2fs> sometimes gives an error about this and sometimes not.
2584 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2585 calling this function.");
2586
2587   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2588    [InitBasicFS, Always, TestOutputList (
2589       [["find"; "/"]], ["lost+found"]);
2590     InitBasicFS, Always, TestOutputList (
2591       [["touch"; "/a"];
2592        ["mkdir"; "/b"];
2593        ["touch"; "/b/c"];
2594        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2595     InitBasicFS, Always, TestOutputList (
2596       [["mkdir_p"; "/a/b/c"];
2597        ["touch"; "/a/b/c/d"];
2598        ["find"; "/a/b/"]], ["c"; "c/d"])],
2599    "find all files and directories",
2600    "\
2601 This command lists out all files and directories, recursively,
2602 starting at C<directory>.  It is essentially equivalent to
2603 running the shell command C<find directory -print> but some
2604 post-processing happens on the output, described below.
2605
2606 This returns a list of strings I<without any prefix>.  Thus
2607 if the directory structure was:
2608
2609  /tmp/a
2610  /tmp/b
2611  /tmp/c/d
2612
2613 then the returned list from C<guestfs_find> C</tmp> would be
2614 4 elements:
2615
2616  a
2617  b
2618  c
2619  c/d
2620
2621 If C<directory> is not a directory, then this command returns
2622 an error.
2623
2624 The returned list is sorted.
2625
2626 See also C<guestfs_find0>.");
2627
2628   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2629    [], (* lvresize tests this *)
2630    "check an ext2/ext3 filesystem",
2631    "\
2632 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2633 filesystem checker on C<device>, noninteractively (C<-p>),
2634 even if the filesystem appears to be clean (C<-f>).
2635
2636 This command is only needed because of C<guestfs_resize2fs>
2637 (q.v.).  Normally you should use C<guestfs_fsck>.");
2638
2639   ("sleep", (RErr, [Int "secs"]), 109, [],
2640    [InitNone, Always, TestRun (
2641       [["sleep"; "1"]])],
2642    "sleep for some seconds",
2643    "\
2644 Sleep for C<secs> seconds.");
2645
2646   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2647    [InitNone, Always, TestOutputInt (
2648       [["part_disk"; "/dev/sda"; "mbr"];
2649        ["mkfs"; "ntfs"; "/dev/sda1"];
2650        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2651     InitNone, Always, TestOutputInt (
2652       [["part_disk"; "/dev/sda"; "mbr"];
2653        ["mkfs"; "ext2"; "/dev/sda1"];
2654        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2655    "probe NTFS volume",
2656    "\
2657 This command runs the L<ntfs-3g.probe(8)> command which probes
2658 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2659 be mounted read-write, and some cannot be mounted at all).
2660
2661 C<rw> is a boolean flag.  Set it to true if you want to test
2662 if the volume can be mounted read-write.  Set it to false if
2663 you want to test if the volume can be mounted read-only.
2664
2665 The return value is an integer which C<0> if the operation
2666 would succeed, or some non-zero value documented in the
2667 L<ntfs-3g.probe(8)> manual page.");
2668
2669   ("sh", (RString "output", [String "command"]), 111, [],
2670    [], (* XXX needs tests *)
2671    "run a command via the shell",
2672    "\
2673 This call runs a command from the guest filesystem via the
2674 guest's C</bin/sh>.
2675
2676 This is like C<guestfs_command>, but passes the command to:
2677
2678  /bin/sh -c \"command\"
2679
2680 Depending on the guest's shell, this usually results in
2681 wildcards being expanded, shell expressions being interpolated
2682 and so on.
2683
2684 All the provisos about C<guestfs_command> apply to this call.");
2685
2686   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2687    [], (* XXX needs tests *)
2688    "run a command via the shell returning lines",
2689    "\
2690 This is the same as C<guestfs_sh>, but splits the result
2691 into a list of lines.
2692
2693 See also: C<guestfs_command_lines>");
2694
2695   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2696    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2697     * code in stubs.c, since all valid glob patterns must start with "/".
2698     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2699     *)
2700    [InitBasicFS, Always, TestOutputList (
2701       [["mkdir_p"; "/a/b/c"];
2702        ["touch"; "/a/b/c/d"];
2703        ["touch"; "/a/b/c/e"];
2704        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2705     InitBasicFS, Always, TestOutputList (
2706       [["mkdir_p"; "/a/b/c"];
2707        ["touch"; "/a/b/c/d"];
2708        ["touch"; "/a/b/c/e"];
2709        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710     InitBasicFS, Always, TestOutputList (
2711       [["mkdir_p"; "/a/b/c"];
2712        ["touch"; "/a/b/c/d"];
2713        ["touch"; "/a/b/c/e"];
2714        ["glob_expand"; "/a/*/x/*"]], [])],
2715    "expand a wildcard path",
2716    "\
2717 This command searches for all the pathnames matching
2718 C<pattern> according to the wildcard expansion rules
2719 used by the shell.
2720
2721 If no paths match, then this returns an empty list
2722 (note: not an error).
2723
2724 It is just a wrapper around the C L<glob(3)> function
2725 with flags C<GLOB_MARK|GLOB_BRACE>.
2726 See that manual page for more details.");
2727
2728   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2729    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2730       [["scrub_device"; "/dev/sdc"]])],
2731    "scrub (securely wipe) a device",
2732    "\
2733 This command writes patterns over C<device> to make data retrieval
2734 more difficult.
2735
2736 It is an interface to the L<scrub(1)> program.  See that
2737 manual page for more details.");
2738
2739   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2740    [InitBasicFS, Always, TestRun (
2741       [["write_file"; "/file"; "content"; "0"];
2742        ["scrub_file"; "/file"]])],
2743    "scrub (securely wipe) a file",
2744    "\
2745 This command writes patterns over a file to make data retrieval
2746 more difficult.
2747
2748 The file is I<removed> after scrubbing.
2749
2750 It is an interface to the L<scrub(1)> program.  See that
2751 manual page for more details.");
2752
2753   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2754    [], (* XXX needs testing *)
2755    "scrub (securely wipe) free space",
2756    "\
2757 This command creates the directory C<dir> and then fills it
2758 with files until the filesystem is full, and scrubs the files
2759 as for C<guestfs_scrub_file>, and deletes them.
2760 The intention is to scrub any free space on the partition
2761 containing C<dir>.
2762
2763 It is an interface to the L<scrub(1)> program.  See that
2764 manual page for more details.");
2765
2766   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2767    [InitBasicFS, Always, TestRun (
2768       [["mkdir"; "/tmp"];
2769        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2770    "create a temporary directory",
2771    "\
2772 This command creates a temporary directory.  The
2773 C<template> parameter should be a full pathname for the
2774 temporary directory name with the final six characters being
2775 \"XXXXXX\".
2776
2777 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2778 the second one being suitable for Windows filesystems.
2779
2780 The name of the temporary directory that was created
2781 is returned.
2782
2783 The temporary directory is created with mode 0700
2784 and is owned by root.
2785
2786 The caller is responsible for deleting the temporary
2787 directory and its contents after use.
2788
2789 See also: L<mkdtemp(3)>");
2790
2791   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2792    [InitISOFS, Always, TestOutputInt (
2793       [["wc_l"; "/10klines"]], 10000)],
2794    "count lines in a file",
2795    "\
2796 This command counts the lines in a file, using the
2797 C<wc -l> external command.");
2798
2799   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2800    [InitISOFS, Always, TestOutputInt (
2801       [["wc_w"; "/10klines"]], 10000)],
2802    "count words in a file",
2803    "\
2804 This command counts the words in a file, using the
2805 C<wc -w> external command.");
2806
2807   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2808    [InitISOFS, Always, TestOutputInt (
2809       [["wc_c"; "/100kallspaces"]], 102400)],
2810    "count characters in a file",
2811    "\
2812 This command counts the characters in a file, using the
2813 C<wc -c> external command.");
2814
2815   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2816    [InitISOFS, Always, TestOutputList (
2817       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2818    "return first 10 lines of a file",
2819    "\
2820 This command returns up to the first 10 lines of a file as
2821 a list of strings.");
2822
2823   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2824    [InitISOFS, Always, TestOutputList (
2825       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2826     InitISOFS, Always, TestOutputList (
2827       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2828     InitISOFS, Always, TestOutputList (
2829       [["head_n"; "0"; "/10klines"]], [])],
2830    "return first N lines of a file",
2831    "\
2832 If the parameter C<nrlines> is a positive number, this returns the first
2833 C<nrlines> lines of the file C<path>.
2834
2835 If the parameter C<nrlines> is a negative number, this returns lines
2836 from the file C<path>, excluding the last C<nrlines> lines.
2837
2838 If the parameter C<nrlines> is zero, this returns an empty list.");
2839
2840   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2841    [InitISOFS, Always, TestOutputList (
2842       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2843    "return last 10 lines of a file",
2844    "\
2845 This command returns up to the last 10 lines of a file as
2846 a list of strings.");
2847
2848   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2849    [InitISOFS, Always, TestOutputList (
2850       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2851     InitISOFS, Always, TestOutputList (
2852       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2853     InitISOFS, Always, TestOutputList (
2854       [["tail_n"; "0"; "/10klines"]], [])],
2855    "return last N lines of a file",
2856    "\
2857 If the parameter C<nrlines> is a positive number, this returns the last
2858 C<nrlines> lines of the file C<path>.
2859
2860 If the parameter C<nrlines> is a negative number, this returns lines
2861 from the file C<path>, starting with the C<-nrlines>th line.
2862
2863 If the parameter C<nrlines> is zero, this returns an empty list.");
2864
2865   ("df", (RString "output", []), 125, [],
2866    [], (* XXX Tricky to test because it depends on the exact format
2867         * of the 'df' command and other imponderables.
2868         *)
2869    "report file system disk space usage",
2870    "\
2871 This command runs the C<df> command to report disk space used.
2872
2873 This command is mostly useful for interactive sessions.  It
2874 is I<not> intended that you try to parse the output string.
2875 Use C<statvfs> from programs.");
2876
2877   ("df_h", (RString "output", []), 126, [],
2878    [], (* XXX Tricky to test because it depends on the exact format
2879         * of the 'df' command and other imponderables.
2880         *)
2881    "report file system disk space usage (human readable)",
2882    "\
2883 This command runs the C<df -h> command to report disk space used
2884 in human-readable format.
2885
2886 This command is mostly useful for interactive sessions.  It
2887 is I<not> intended that you try to parse the output string.
2888 Use C<statvfs> from programs.");
2889
2890   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2891    [InitISOFS, Always, TestOutputInt (
2892       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2893    "estimate file space usage",
2894    "\
2895 This command runs the C<du -s> command to estimate file space
2896 usage for C<path>.
2897
2898 C<path> can be a file or a directory.  If C<path> is a directory
2899 then the estimate includes the contents of the directory and all
2900 subdirectories (recursively).
2901
2902 The result is the estimated size in I<kilobytes>
2903 (ie. units of 1024 bytes).");
2904
2905   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2906    [InitISOFS, Always, TestOutputList (
2907       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2908    "list files in an initrd",
2909    "\
2910 This command lists out files contained in an initrd.
2911
2912 The files are listed without any initial C</> character.  The
2913 files are listed in the order they appear (not necessarily
2914 alphabetical).  Directory names are listed as separate items.
2915
2916 Old Linux kernels (2.4 and earlier) used a compressed ext2
2917 filesystem as initrd.  We I<only> support the newer initramfs
2918 format (compressed cpio files).");
2919
2920   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2921    [],
2922    "mount a file using the loop device",
2923    "\
2924 This command lets you mount C<file> (a filesystem image
2925 in a file) on a mount point.  It is entirely equivalent to
2926 the command C<mount -o loop file mountpoint>.");
2927
2928   ("mkswap", (RErr, [Device "device"]), 130, [],
2929    [InitEmpty, Always, TestRun (
2930       [["part_disk"; "/dev/sda"; "mbr"];
2931        ["mkswap"; "/dev/sda1"]])],
2932    "create a swap partition",
2933    "\
2934 Create a swap partition on C<device>.");
2935
2936   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2937    [InitEmpty, Always, TestRun (
2938       [["part_disk"; "/dev/sda"; "mbr"];
2939        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2940    "create a swap partition with a label",
2941    "\
2942 Create a swap partition on C<device> with label C<label>.
2943
2944 Note that you cannot attach a swap label to a block device
2945 (eg. C</dev/sda>), just to a partition.  This appears to be
2946 a limitation of the kernel or swap tools.");
2947
2948   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2949    (let uuid = uuidgen () in
2950     [InitEmpty, Always, TestRun (
2951        [["part_disk"; "/dev/sda"; "mbr"];
2952         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2953    "create a swap partition with an explicit UUID",
2954    "\
2955 Create a swap partition on C<device> with UUID C<uuid>.");
2956
2957   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2958    [InitBasicFS, Always, TestOutputStruct (
2959       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2960        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2961        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2962     InitBasicFS, Always, TestOutputStruct (
2963       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2964        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2965    "make block, character or FIFO devices",
2966    "\
2967 This call creates block or character special devices, or
2968 named pipes (FIFOs).
2969
2970 The C<mode> parameter should be the mode, using the standard
2971 constants.  C<devmajor> and C<devminor> are the
2972 device major and minor numbers, only used when creating block
2973 and character special devices.");
2974
2975   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2976    [InitBasicFS, Always, TestOutputStruct (
2977       [["mkfifo"; "0o777"; "/node"];
2978        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2979    "make FIFO (named pipe)",
2980    "\
2981 This call creates a FIFO (named pipe) called C<path> with
2982 mode C<mode>.  It is just a convenient wrapper around
2983 C<guestfs_mknod>.");
2984
2985   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2986    [InitBasicFS, Always, TestOutputStruct (
2987       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2988        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2989    "make block device node",
2990    "\
2991 This call creates a block device node called C<path> with
2992 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2993 It is just a convenient wrapper around C<guestfs_mknod>.");
2994
2995   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2996    [InitBasicFS, Always, TestOutputStruct (
2997       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2998        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2999    "make char device node",
3000    "\
3001 This call creates a char device node called C<path> with
3002 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3003 It is just a convenient wrapper around C<guestfs_mknod>.");
3004
3005   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3006    [], (* XXX umask is one of those stateful things that we should
3007         * reset between each test.
3008         *)
3009    "set file mode creation mask (umask)",
3010    "\
3011 This function sets the mask used for creating new files and
3012 device nodes to C<mask & 0777>.
3013
3014 Typical umask values would be C<022> which creates new files
3015 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3016 C<002> which creates new files with permissions like
3017 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3018
3019 The default umask is C<022>.  This is important because it
3020 means that directories and device nodes will be created with
3021 C<0644> or C<0755> mode even if you specify C<0777>.
3022
3023 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3024
3025 This call returns the previous umask.");
3026
3027   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3028    [],
3029    "read directories entries",
3030    "\
3031 This returns the list of directory entries in directory C<dir>.
3032
3033 All entries in the directory are returned, including C<.> and
3034 C<..>.  The entries are I<not> sorted, but returned in the same
3035 order as the underlying filesystem.
3036
3037 Also this call returns basic file type information about each
3038 file.  The C<ftyp> field will contain one of the following characters:
3039
3040 =over 4
3041
3042 =item 'b'
3043
3044 Block special
3045
3046 =item 'c'
3047
3048 Char special
3049
3050 =item 'd'
3051
3052 Directory
3053
3054 =item 'f'
3055
3056 FIFO (named pipe)
3057
3058 =item 'l'
3059
3060 Symbolic link
3061
3062 =item 'r'
3063
3064 Regular file
3065
3066 =item 's'
3067
3068 Socket
3069
3070 =item 'u'
3071
3072 Unknown file type
3073
3074 =item '?'
3075
3076 The L<readdir(3)> returned a C<d_type> field with an
3077 unexpected value
3078
3079 =back
3080
3081 This function is primarily intended for use by programs.  To
3082 get a simple list of names, use C<guestfs_ls>.  To get a printable
3083 directory for human consumption, use C<guestfs_ll>.");
3084
3085   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3086    [],
3087    "create partitions on a block device",
3088    "\
3089 This is a simplified interface to the C<guestfs_sfdisk>
3090 command, where partition sizes are specified in megabytes
3091 only (rounded to the nearest cylinder) and you don't need
3092 to specify the cyls, heads and sectors parameters which
3093 were rarely if ever used anyway.
3094
3095 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3096 and C<guestfs_part_disk>");
3097
3098   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3099    [],
3100    "determine file type inside a compressed file",
3101    "\
3102 This command runs C<file> after first decompressing C<path>
3103 using C<method>.
3104
3105 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3106
3107 Since 1.0.63, use C<guestfs_file> instead which can now
3108 process compressed files.");
3109
3110   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3111    [],
3112    "list extended attributes of a file or directory",
3113    "\
3114 This call lists the extended attributes of the file or directory
3115 C<path>.
3116
3117 At the system call level, this is a combination of the
3118 L<listxattr(2)> and L<getxattr(2)> calls.
3119
3120 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3121
3122   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3123    [],
3124    "list extended attributes of a file or directory",
3125    "\
3126 This is the same as C<guestfs_getxattrs>, but if C<path>
3127 is a symbolic link, then it returns the extended attributes
3128 of the link itself.");
3129
3130   ("setxattr", (RErr, [String "xattr";
3131                        String "val"; Int "vallen"; (* will be BufferIn *)
3132                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3133    [],
3134    "set extended attribute of a file or directory",
3135    "\
3136 This call sets the extended attribute named C<xattr>
3137 of the file C<path> to the value C<val> (of length C<vallen>).
3138 The value is arbitrary 8 bit data.
3139
3140 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3141
3142   ("lsetxattr", (RErr, [String "xattr";
3143                         String "val"; Int "vallen"; (* will be BufferIn *)
3144                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3145    [],
3146    "set extended attribute of a file or directory",
3147    "\
3148 This is the same as C<guestfs_setxattr>, but if C<path>
3149 is a symbolic link, then it sets an extended attribute
3150 of the link itself.");
3151
3152   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3153    [],
3154    "remove extended attribute of a file or directory",
3155    "\
3156 This call removes the extended attribute named C<xattr>
3157 of the file C<path>.
3158
3159 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3160
3161   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3162    [],
3163    "remove extended attribute of a file or directory",
3164    "\
3165 This is the same as C<guestfs_removexattr>, but if C<path>
3166 is a symbolic link, then it removes an extended attribute
3167 of the link itself.");
3168
3169   ("mountpoints", (RHashtable "mps", []), 147, [],
3170    [],
3171    "show mountpoints",
3172    "\
3173 This call is similar to C<guestfs_mounts>.  That call returns
3174 a list of devices.  This one returns a hash table (map) of
3175 device name to directory where the device is mounted.");
3176
3177   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3178    (* This is a special case: while you would expect a parameter
3179     * of type "Pathname", that doesn't work, because it implies
3180     * NEED_ROOT in the generated calling code in stubs.c, and
3181     * this function cannot use NEED_ROOT.
3182     *)
3183    [],
3184    "create a mountpoint",
3185    "\
3186 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3187 specialized calls that can be used to create extra mountpoints
3188 before mounting the first filesystem.
3189
3190 These calls are I<only> necessary in some very limited circumstances,
3191 mainly the case where you want to mount a mix of unrelated and/or
3192 read-only filesystems together.
3193
3194 For example, live CDs often contain a \"Russian doll\" nest of
3195 filesystems, an ISO outer layer, with a squashfs image inside, with
3196 an ext2/3 image inside that.  You can unpack this as follows
3197 in guestfish:
3198
3199  add-ro Fedora-11-i686-Live.iso
3200  run
3201  mkmountpoint /cd
3202  mkmountpoint /squash
3203  mkmountpoint /ext3
3204  mount /dev/sda /cd
3205  mount-loop /cd/LiveOS/squashfs.img /squash
3206  mount-loop /squash/LiveOS/ext3fs.img /ext3
3207
3208 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3209
3210   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3211    [],
3212    "remove a mountpoint",
3213    "\
3214 This calls removes a mountpoint that was previously created
3215 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3216 for full details.");
3217
3218   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3219    [InitISOFS, Always, TestOutputBuffer (
3220       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3221    "read a file",
3222    "\
3223 This calls returns the contents of the file C<path> as a
3224 buffer.
3225
3226 Unlike C<guestfs_cat>, this function can correctly
3227 handle files that contain embedded ASCII NUL characters.
3228 However unlike C<guestfs_download>, this function is limited
3229 in the total size of file that can be handled.");
3230
3231   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3232    [InitISOFS, Always, TestOutputList (
3233       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3234     InitISOFS, Always, TestOutputList (
3235       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3236    "return lines matching a pattern",
3237    "\
3238 This calls the external C<grep> program and returns the
3239 matching lines.");
3240
3241   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3242    [InitISOFS, Always, TestOutputList (
3243       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3244    "return lines matching a pattern",
3245    "\
3246 This calls the external C<egrep> program and returns the
3247 matching lines.");
3248
3249   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3250    [InitISOFS, Always, TestOutputList (
3251       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3252    "return lines matching a pattern",
3253    "\
3254 This calls the external C<fgrep> program and returns the
3255 matching lines.");
3256
3257   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3258    [InitISOFS, Always, TestOutputList (
3259       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3260    "return lines matching a pattern",
3261    "\
3262 This calls the external C<grep -i> program and returns the
3263 matching lines.");
3264
3265   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3266    [InitISOFS, Always, TestOutputList (
3267       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3268    "return lines matching a pattern",
3269    "\
3270 This calls the external C<egrep -i> program and returns the
3271 matching lines.");
3272
3273   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3274    [InitISOFS, Always, TestOutputList (
3275       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3276    "return lines matching a pattern",
3277    "\
3278 This calls the external C<fgrep -i> program and returns the
3279 matching lines.");
3280
3281   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3282    [InitISOFS, Always, TestOutputList (
3283       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3284    "return lines matching a pattern",
3285    "\
3286 This calls the external C<zgrep> program and returns the
3287 matching lines.");
3288
3289   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3290    [InitISOFS, Always, TestOutputList (
3291       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3292    "return lines matching a pattern",
3293    "\
3294 This calls the external C<zegrep> program and returns the
3295 matching lines.");
3296
3297   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3298    [InitISOFS, Always, TestOutputList (
3299       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3300    "return lines matching a pattern",
3301    "\
3302 This calls the external C<zfgrep> program and returns the
3303 matching lines.");
3304
3305   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3306    [InitISOFS, Always, TestOutputList (
3307       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3308    "return lines matching a pattern",
3309    "\
3310 This calls the external C<zgrep -i> program and returns the
3311 matching lines.");
3312
3313   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3314    [InitISOFS, Always, TestOutputList (
3315       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3316    "return lines matching a pattern",
3317    "\
3318 This calls the external C<zegrep -i> program and returns the
3319 matching lines.");
3320
3321   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3322    [InitISOFS, Always, TestOutputList (
3323       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3324    "return lines matching a pattern",
3325    "\
3326 This calls the external C<zfgrep -i> program and returns the
3327 matching lines.");
3328
3329   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3330    [InitISOFS, Always, TestOutput (
3331       [["realpath"; "/../directory"]], "/directory")],
3332    "canonicalized absolute pathname",
3333    "\
3334 Return the canonicalized absolute pathname of C<path>.  The
3335 returned path has no C<.>, C<..> or symbolic link path elements.");
3336
3337   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3338    [InitBasicFS, Always, TestOutputStruct (
3339       [["touch"; "/a"];
3340        ["ln"; "/a"; "/b"];
3341        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3342    "create a hard link",
3343    "\
3344 This command creates a hard link using the C<ln> command.");
3345
3346   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3347    [InitBasicFS, Always, TestOutputStruct (
3348       [["touch"; "/a"];
3349        ["touch"; "/b"];
3350        ["ln_f"; "/a"; "/b"];
3351        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3352    "create a hard link",
3353    "\
3354 This command creates a hard link using the C<ln -f> command.
3355 The C<-f> option removes the link (C<linkname>) if it exists already.");
3356
3357   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3358    [InitBasicFS, Always, TestOutputStruct (
3359       [["touch"; "/a"];
3360        ["ln_s"; "a"; "/b"];
3361        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3362    "create a symbolic link",
3363    "\
3364 This command creates a symbolic link using the C<ln -s> command.");
3365
3366   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3367    [InitBasicFS, Always, TestOutput (
3368       [["mkdir_p"; "/a/b"];
3369        ["touch"; "/a/b/c"];
3370        ["ln_sf"; "../d"; "/a/b/c"];
3371        ["readlink"; "/a/b/c"]], "../d")],
3372    "create a symbolic link",
3373    "\
3374 This command creates a symbolic link using the C<ln -sf> command,
3375 The C<-f> option removes the link (C<linkname>) if it exists already.");
3376
3377   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3378    [] (* XXX tested above *),
3379    "read the target of a symbolic link",
3380    "\
3381 This command reads the target of a symbolic link.");
3382
3383   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3384    [InitBasicFS, Always, TestOutputStruct (
3385       [["fallocate"; "/a"; "1000000"];
3386        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3387    "preallocate a file in the guest filesystem",
3388    "\
3389 This command preallocates a file (containing zero bytes) named
3390 C<path> of size C<len> bytes.  If the file exists already, it
3391 is overwritten.
3392
3393 Do not confuse this with the guestfish-specific
3394 C<alloc> command which allocates a file in the host and
3395 attaches it as a device.");
3396
3397   ("swapon_device", (RErr, [Device "device"]), 170, [],
3398    [InitPartition, Always, TestRun (
3399       [["mkswap"; "/dev/sda1"];
3400        ["swapon_device"; "/dev/sda1"];
3401        ["swapoff_device"; "/dev/sda1"]])],
3402    "enable swap on device",
3403    "\
3404 This command enables the libguestfs appliance to use the
3405 swap device or partition named C<device>.  The increased
3406 memory is made available for all commands, for example
3407 those run using C<guestfs_command> or C<guestfs_sh>.
3408
3409 Note that you should not swap to existing guest swap
3410 partitions unless you know what you are doing.  They may
3411 contain hibernation information, or other information that
3412 the guest doesn't want you to trash.  You also risk leaking
3413 information about the host to the guest this way.  Instead,
3414 attach a new host device to the guest and swap on that.");
3415
3416   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3417    [], (* XXX tested by swapon_device *)
3418    "disable swap on device",
3419    "\
3420 This command disables the libguestfs appliance swap
3421 device or partition named C<device>.
3422 See C<guestfs_swapon_device>.");
3423
3424   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3425    [InitBasicFS, Always, TestRun (
3426       [["fallocate"; "/swap"; "8388608"];
3427        ["mkswap_file"; "/swap"];
3428        ["swapon_file"; "/swap"];
3429        ["swapoff_file"; "/swap"]])],
3430    "enable swap on file",
3431    "\
3432 This command enables swap to a file.
3433 See C<guestfs_swapon_device> for other notes.");
3434
3435   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3436    [], (* XXX tested by swapon_file *)
3437    "disable swap on file",
3438    "\
3439 This command disables the libguestfs appliance swap on file.");
3440
3441   ("swapon_label", (RErr, [String "label"]), 174, [],
3442    [InitEmpty, Always, TestRun (
3443       [["part_disk"; "/dev/sdb"; "mbr"];
3444        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3445        ["swapon_label"; "swapit"];
3446        ["swapoff_label"; "swapit"];
3447        ["zero"; "/dev/sdb"];
3448        ["blockdev_rereadpt"; "/dev/sdb"]])],
3449    "enable swap on labeled swap partition",
3450    "\
3451 This command enables swap to a labeled swap partition.
3452 See C<guestfs_swapon_device> for other notes.");
3453
3454   ("swapoff_label", (RErr, [String "label"]), 175, [],
3455    [], (* XXX tested by swapon_label *)
3456    "disable swap on labeled swap partition",
3457    "\
3458 This command disables the libguestfs appliance swap on
3459 labeled swap partition.");
3460
3461   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3462    (let uuid = uuidgen () in
3463     [InitEmpty, Always, TestRun (
3464        [["mkswap_U"; uuid; "/dev/sdb"];
3465         ["swapon_uuid"; uuid];
3466         ["swapoff_uuid"; uuid]])]),
3467    "enable swap on swap partition by UUID",
3468    "\
3469 This command enables swap to a swap partition with the given UUID.
3470 See C<guestfs_swapon_device> for other notes.");
3471
3472   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3473    [], (* XXX tested by swapon_uuid *)
3474    "disable swap on swap partition by UUID",
3475    "\
3476 This command disables the libguestfs appliance swap partition
3477 with the given UUID.");
3478
3479   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3480    [InitBasicFS, Always, TestRun (
3481       [["fallocate"; "/swap"; "8388608"];
3482        ["mkswap_file"; "/swap"]])],
3483    "create a swap file",
3484    "\
3485 Create a swap file.
3486
3487 This command just writes a swap file signature to an existing
3488 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3489
3490   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3491    [InitISOFS, Always, TestRun (
3492       [["inotify_init"; "0"]])],
3493    "create an inotify handle",
3494    "\
3495 This command creates a new inotify handle.
3496 The inotify subsystem can be used to notify events which happen to
3497 objects in the guest filesystem.
3498
3499 C<maxevents> is the maximum number of events which will be
3500 queued up between calls to C<guestfs_inotify_read> or
3501 C<guestfs_inotify_files>.
3502 If this is passed as C<0>, then the kernel (or previously set)
3503 default is used.  For Linux 2.6.29 the default was 16384 events.
3504 Beyond this limit, the kernel throws away events, but records
3505 the fact that it threw them away by setting a flag
3506 C<IN_Q_OVERFLOW> in the returned structure list (see
3507 C<guestfs_inotify_read>).
3508
3509 Before any events are generated, you have to add some
3510 watches to the internal watch list.  See:
3511 C<guestfs_inotify_add_watch>,
3512 C<guestfs_inotify_rm_watch> and
3513 C<guestfs_inotify_watch_all>.
3514
3515 Queued up events should be read periodically by calling
3516 C<guestfs_inotify_read>
3517 (or C<guestfs_inotify_files> which is just a helpful
3518 wrapper around C<guestfs_inotify_read>).  If you don't
3519 read the events out often enough then you risk the internal
3520 queue overflowing.
3521
3522 The handle should be closed after use by calling
3523 C<guestfs_inotify_close>.  This also removes any
3524 watches automatically.
3525
3526 See also L<inotify(7)> for an overview of the inotify interface
3527 as exposed by the Linux kernel, which is roughly what we expose
3528 via libguestfs.  Note that there is one global inotify handle
3529 per libguestfs instance.");
3530
3531   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3532    [InitBasicFS, Always, TestOutputList (
3533       [["inotify_init"; "0"];
3534        ["inotify_add_watch"; "/"; "1073741823"];
3535        ["touch"; "/a"];
3536        ["touch"; "/b"];
3537        ["inotify_files"]], ["a"; "b"])],
3538    "add an inotify watch",
3539    "\
3540 Watch C<path> for the events listed in C<mask>.
3541
3542 Note that if C<path> is a directory then events within that
3543 directory are watched, but this does I<not> happen recursively
3544 (in subdirectories).
3545
3546 Note for non-C or non-Linux callers: the inotify events are
3547 defined by the Linux kernel ABI and are listed in
3548 C</usr/include/sys/inotify.h>.");
3549
3550   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3551    [],
3552    "remove an inotify watch",
3553    "\
3554 Remove a previously defined inotify watch.
3555 See C<guestfs_inotify_add_watch>.");
3556
3557   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3558    [],
3559    "return list of inotify events",
3560    "\
3561 Return the complete queue of events that have happened
3562 since the previous read call.
3563
3564 If no events have happened, this returns an empty list.
3565
3566 I<Note>: In order to make sure that all events have been
3567 read, you must call this function repeatedly until it
3568 returns an empty list.  The reason is that the call will
3569 read events up to the maximum appliance-to-host message
3570 size and leave remaining events in the queue.");
3571
3572   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3573    [],
3574    "return list of watched files that had events",
3575    "\
3576 This function is a helpful wrapper around C<guestfs_inotify_read>
3577 which just returns a list of pathnames of objects that were
3578 touched.  The returned pathnames are sorted and deduplicated.");
3579
3580   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3581    [],
3582    "close the inotify handle",
3583    "\
3584 This closes the inotify handle which was previously
3585 opened by inotify_init.  It removes all watches, throws
3586 away any pending events, and deallocates all resources.");
3587
3588   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3589    [],
3590    "set SELinux security context",
3591    "\
3592 This sets the SELinux security context of the daemon
3593 to the string C<context>.
3594
3595 See the documentation about SELINUX in L<guestfs(3)>.");
3596
3597   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3598    [],
3599    "get SELinux security context",
3600    "\
3601 This gets the SELinux security context of the daemon.
3602
3603 See the documentation about SELINUX in L<guestfs(3)>,
3604 and C<guestfs_setcon>");
3605
3606   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3607    [InitEmpty, Always, TestOutput (
3608       [["part_disk"; "/dev/sda"; "mbr"];
3609        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3610        ["mount_options"; ""; "/dev/sda1"; "/"];
3611        ["write_file"; "/new"; "new file contents"; "0"];
3612        ["cat"; "/new"]], "new file contents")],
3613    "make a filesystem with block size",
3614    "\
3615 This call is similar to C<guestfs_mkfs>, but it allows you to
3616 control the block size of the resulting filesystem.  Supported
3617 block sizes depend on the filesystem type, but typically they
3618 are C<1024>, C<2048> or C<4096> only.");
3619
3620   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3621    [InitEmpty, Always, TestOutput (
3622       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3623        ["mke2journal"; "4096"; "/dev/sda1"];
3624        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3625        ["mount_options"; ""; "/dev/sda2"; "/"];
3626        ["write_file"; "/new"; "new file contents"; "0"];
3627        ["cat"; "/new"]], "new file contents")],
3628    "make ext2/3/4 external journal",
3629    "\
3630 This creates an ext2 external journal on C<device>.  It is equivalent
3631 to the command:
3632
3633  mke2fs -O journal_dev -b blocksize device");
3634
3635   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3636    [InitEmpty, Always, TestOutput (
3637       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3638        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3639        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3640        ["mount_options"; ""; "/dev/sda2"; "/"];
3641        ["write_file"; "/new"; "new file contents"; "0"];
3642        ["cat"; "/new"]], "new file contents")],
3643    "make ext2/3/4 external journal with label",
3644    "\
3645 This creates an ext2 external journal on C<device> with label C<label>.");
3646
3647   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3648    (let uuid = uuidgen () in
3649     [InitEmpty, Always, TestOutput (
3650        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3651         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3652         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3653         ["mount_options"; ""; "/dev/sda2"; "/"];
3654         ["write_file"; "/new"; "new file contents"; "0"];
3655         ["cat"; "/new"]], "new file contents")]),
3656    "make ext2/3/4 external journal with UUID",
3657    "\
3658 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3659
3660   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3661    [],
3662    "make ext2/3/4 filesystem with external journal",
3663    "\
3664 This creates an ext2/3/4 filesystem on C<device> with
3665 an external journal on C<journal>.  It is equivalent
3666 to the command:
3667
3668  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3669
3670 See also C<guestfs_mke2journal>.");
3671
3672   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3673    [],
3674    "make ext2/3/4 filesystem with external journal",
3675    "\
3676 This creates an ext2/3/4 filesystem on C<device> with
3677 an external journal on the journal labeled C<label>.
3678
3679 See also C<guestfs_mke2journal_L>.");
3680
3681   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3682    [],
3683    "make ext2/3/4 filesystem with external journal",
3684    "\
3685 This creates an ext2/3/4 filesystem on C<device> with
3686 an external journal on the journal with UUID C<uuid>.
3687
3688 See also C<guestfs_mke2journal_U>.");
3689
3690   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3691    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3692    "load a kernel module",
3693    "\
3694 This loads a kernel module in the appliance.
3695
3696 The kernel module must have been whitelisted when libguestfs
3697 was built (see C<appliance/kmod.whitelist.in> in the source).");
3698
3699   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3700    [InitNone, Always, TestOutput (
3701       [["echo_daemon"; "This is a test"]], "This is a test"
3702     )],
3703    "echo arguments back to the client",
3704    "\
3705 This command concatenate the list of C<words> passed with single spaces between
3706 them and returns the resulting string.
3707
3708 You can use this command to test the connection through to the daemon.
3709
3710 See also C<guestfs_ping_daemon>.");
3711
3712   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3713    [], (* There is a regression test for this. *)
3714    "find all files and directories, returning NUL-separated list",
3715    "\
3716 This command lists out all files and directories, recursively,
3717 starting at C<directory>, placing the resulting list in the
3718 external file called C<files>.
3719
3720 This command works the same way as C<guestfs_find> with the
3721 following exceptions:
3722
3723 =over 4
3724
3725 =item *
3726
3727 The resulting list is written to an external file.
3728
3729 =item *
3730
3731 Items (filenames) in the result are separated
3732 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3733
3734 =item *
3735
3736 This command is not limited in the number of names that it
3737 can return.
3738
3739 =item *
3740
3741 The result list is not sorted.
3742
3743 =back");
3744
3745   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3746    [InitISOFS, Always, TestOutput (
3747       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3748     InitISOFS, Always, TestOutput (
3749       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3750     InitISOFS, Always, TestOutput (
3751       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3752     InitISOFS, Always, TestLastFail (
3753       [["case_sensitive_path"; "/Known-1/"]]);
3754     InitBasicFS, Always, TestOutput (
3755       [["mkdir"; "/a"];
3756        ["mkdir"; "/a/bbb"];
3757        ["touch"; "/a/bbb/c"];
3758        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3759     InitBasicFS, Always, TestOutput (
3760       [["mkdir"; "/a"];
3761        ["mkdir"; "/a/bbb"];
3762        ["touch"; "/a/bbb/c"];
3763        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3764     InitBasicFS, Always, TestLastFail (
3765       [["mkdir"; "/a"];
3766        ["mkdir"; "/a/bbb"];
3767        ["touch"; "/a/bbb/c"];
3768        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3769    "return true path on case-insensitive filesystem",
3770    "\
3771 This can be used to resolve case insensitive paths on
3772 a filesystem which is case sensitive.  The use case is
3773 to resolve paths which you have read from Windows configuration
3774 files or the Windows Registry, to the true path.
3775
3776 The command handles a peculiarity of the Linux ntfs-3g
3777 filesystem driver (and probably others), which is that although
3778 the underlying filesystem is case-insensitive, the driver
3779 exports the filesystem to Linux as case-sensitive.
3780
3781 One consequence of this is that special directories such
3782 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3783 (or other things) depending on the precise details of how
3784 they were created.  In Windows itself this would not be
3785 a problem.
3786
3787 Bug or feature?  You decide:
3788 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3789
3790 This function resolves the true case of each element in the
3791 path and returns the case-sensitive path.
3792
3793 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3794 might return C<\"/WINDOWS/system32\"> (the exact return value
3795 would depend on details of how the directories were originally
3796 created under Windows).
3797
3798 I<Note>:
3799 This function does not handle drive names, backslashes etc.
3800
3801 See also C<guestfs_realpath>.");
3802
3803   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3804    [InitBasicFS, Always, TestOutput (
3805       [["vfs_type"; "/dev/sda1"]], "ext2")],
3806    "get the Linux VFS type corresponding to a mounted device",
3807    "\
3808 This command gets the block device type corresponding to
3809 a mounted device called C<device>.
3810
3811 Usually the result is the name of the Linux VFS module that
3812 is used to mount this device (probably determined automatically
3813 if you used the C<guestfs_mount> call).");
3814
3815   ("truncate", (RErr, [Pathname "path"]), 199, [],
3816    [InitBasicFS, Always, TestOutputStruct (
3817       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3818        ["truncate"; "/test"];
3819        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3820    "truncate a file to zero size",
3821    "\
3822 This command truncates C<path> to a zero-length file.  The
3823 file must exist already.");
3824
3825   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3826    [InitBasicFS, Always, TestOutputStruct (
3827       [["touch"; "/test"];
3828        ["truncate_size"; "/test"; "1000"];
3829        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3830    "truncate a file to a particular size",
3831    "\
3832 This command truncates C<path> to size C<size> bytes.  The file
3833 must exist already.  If the file is smaller than C<size> then
3834 the file is extended to the required size with null bytes.");
3835
3836   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3837    [InitBasicFS, Always, TestOutputStruct (
3838       [["touch"; "/test"];
3839        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3840        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3841    "set timestamp of a file with nanosecond precision",
3842    "\
3843 This command sets the timestamps of a file with nanosecond
3844 precision.
3845
3846 C<atsecs, atnsecs> are the last access time (atime) in secs and
3847 nanoseconds from the epoch.
3848
3849 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3850 secs and nanoseconds from the epoch.
3851
3852 If the C<*nsecs> field contains the special value C<-1> then
3853 the corresponding timestamp is set to the current time.  (The
3854 C<*secs> field is ignored in this case).
3855
3856 If the C<*nsecs> field contains the special value C<-2> then
3857 the corresponding timestamp is left unchanged.  (The
3858 C<*secs> field is ignored in this case).");
3859
3860   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3861    [InitBasicFS, Always, TestOutputStruct (
3862       [["mkdir_mode"; "/test"; "0o111"];
3863        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3864    "create a directory with a particular mode",
3865    "\
3866 This command creates a directory, setting the initial permissions
3867 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3868
3869   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3870    [], (* XXX *)
3871    "change file owner and group",
3872    "\
3873 Change the file owner to C<owner> and group to C<group>.
3874 This is like C<guestfs_chown> but if C<path> is a symlink then
3875 the link itself is changed, not the target.
3876
3877 Only numeric uid and gid are supported.  If you want to use
3878 names, you will need to locate and parse the password file
3879 yourself (Augeas support makes this relatively easy).");
3880
3881   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3882    [], (* XXX *)
3883    "lstat on multiple files",
3884    "\
3885 This call allows you to perform the C<guestfs_lstat> operation
3886 on multiple files, where all files are in the directory C<path>.
3887 C<names> is the list of files from this directory.
3888
3889 On return you get a list of stat structs, with a one-to-one
3890 correspondence to the C<names> list.  If any name did not exist
3891 or could not be lstat'd, then the C<ino> field of that structure
3892 is set to C<-1>.
3893
3894 This call is intended for programs that want to efficiently
3895 list a directory contents without making many round-trips.
3896 See also C<guestfs_lxattrlist> for a similarly efficient call
3897 for getting extended attributes.  Very long directory listings
3898 might cause the protocol message size to be exceeded, causing
3899 this call to fail.  The caller must split up such requests
3900 into smaller groups of names.");
3901
3902   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3903    [], (* XXX *)
3904    "lgetxattr on multiple files",
3905    "\
3906 This call allows you to get the extended attributes
3907 of multiple files, where all files are in the directory C<path>.
3908 C<names> is the list of files from this directory.
3909
3910 On return you get a flat list of xattr structs which must be
3911 interpreted sequentially.  The first xattr struct always has a zero-length
3912 C<attrname>.  C<attrval> in this struct is zero-length
3913 to indicate there was an error doing C<lgetxattr> for this
3914 file, I<or> is a C string which is a decimal number
3915 (the number of following attributes for this file, which could
3916 be C<\"0\">).  Then after the first xattr struct are the
3917 zero or more attributes for the first named file.
3918 This repeats for the second and subsequent files.
3919
3920 This call is intended for programs that want to efficiently
3921 list a directory contents without making many round-trips.
3922 See also C<guestfs_lstatlist> for a similarly efficient call
3923 for getting standard stats.  Very long directory listings
3924 might cause the protocol message size to be exceeded, causing
3925 this call to fail.  The caller must split up such requests
3926 into smaller groups of names.");
3927
3928   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3929    [], (* XXX *)
3930    "readlink on multiple files",
3931    "\
3932 This call allows you to do a C<readlink> operation
3933 on multiple files, where all files are in the directory C<path>.
3934 C<names> is the list of files from this directory.
3935
3936 On return you get a list of strings, with a one-to-one
3937 correspondence to the C<names> list.  Each string is the
3938 value of the symbol link.
3939
3940 If the C<readlink(2)> operation fails on any name, then
3941 the corresponding result string is the empty string C<\"\">.
3942 However the whole operation is completed even if there
3943 were C<readlink(2)> errors, and so you can call this
3944 function with names where you don't know if they are
3945 symbolic links already (albeit slightly less efficient).
3946
3947 This call is intended for programs that want to efficiently
3948 list a directory contents without making many round-trips.
3949 Very long directory listings might cause the protocol
3950 message size to be exceeded, causing
3951 this call to fail.  The caller must split up such requests
3952 into smaller groups of names.");
3953
3954   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3955    [InitISOFS, Always, TestOutputBuffer (
3956       [["pread"; "/known-4"; "1"; "3"]], "\n");
3957     InitISOFS, Always, TestOutputBuffer (
3958       [["pread"; "/empty"; "0"; "100"]], "")],
3959    "read part of a file",
3960    "\
3961 This command lets you read part of a file.  It reads C<count>
3962 bytes of the file, starting at C<offset>, from file C<path>.
3963
3964 This may read fewer bytes than requested.  For further details
3965 see the L<pread(2)> system call.");
3966
3967   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3968    [InitEmpty, Always, TestRun (
3969       [["part_init"; "/dev/sda"; "gpt"]])],
3970    "create an empty partition table",
3971    "\
3972 This creates an empty partition table on C<device> of one of the
3973 partition types listed below.  Usually C<parttype> should be
3974 either C<msdos> or C<gpt> (for large disks).
3975
3976 Initially there are no partitions.  Following this, you should
3977 call C<guestfs_part_add> for each partition required.
3978
3979 Possible values for C<parttype> are:
3980
3981 =over 4
3982
3983 =item B<efi> | B<gpt>
3984
3985 Intel EFI / GPT partition table.
3986
3987 This is recommended for >= 2 TB partitions that will be accessed
3988 from Linux and Intel-based Mac OS X.  It also has limited backwards
3989 compatibility with the C<mbr> format.
3990
3991 =item B<mbr> | B<msdos>
3992
3993 The standard PC \"Master Boot Record\" (MBR) format used
3994 by MS-DOS and Windows.  This partition type will B<only> work
3995 for device sizes up to 2 TB.  For large disks we recommend
3996 using C<gpt>.
3997
3998 =back
3999
4000 Other partition table types that may work but are not
4001 supported include:
4002
4003 =over 4
4004
4005 =item B<aix>
4006
4007 AIX disk labels.
4008
4009 =item B<amiga> | B<rdb>
4010
4011 Amiga \"Rigid Disk Block\" format.
4012
4013 =item B<bsd>
4014
4015 BSD disk labels.
4016
4017 =item B<dasd>
4018
4019 DASD, used on IBM mainframes.
4020
4021 =item B<dvh>
4022
4023 MIPS/SGI volumes.
4024
4025 =item B<mac>
4026
4027 Old Mac partition format.  Modern Macs use C<gpt>.
4028
4029 =item B<pc98>
4030
4031 NEC PC-98 format, common in Japan apparently.
4032
4033 =item B<sun>
4034
4035 Sun disk labels.
4036
4037 =back");
4038
4039   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4040    [InitEmpty, Always, TestRun (
4041       [["part_init"; "/dev/sda"; "mbr"];
4042        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4043     InitEmpty, Always, TestRun (
4044       [["part_init"; "/dev/sda"; "gpt"];
4045        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4046        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4047     InitEmpty, Always, TestRun (
4048       [["part_init"; "/dev/sda"; "mbr"];
4049        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4050        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4051        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4052        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4053    "add a partition to the device",
4054    "\
4055 This command adds a partition to C<device>.  If there is no partition
4056 table on the device, call C<guestfs_part_init> first.
4057
4058 The C<prlogex> parameter is the type of partition.  Normally you
4059 should pass C<p> or C<primary> here, but MBR partition tables also
4060 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4061 types.
4062
4063 C<startsect> and C<endsect> are the start and end of the partition
4064 in I<sectors>.  C<endsect> may be negative, which means it counts
4065 backwards from the end of the disk (C<-1> is the last sector).
4066
4067 Creating a partition which covers the whole disk is not so easy.
4068 Use C<guestfs_part_disk> to do that.");
4069
4070   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4071    [InitEmpty, Always, TestRun (
4072       [["part_disk"; "/dev/sda"; "mbr"]]);
4073     InitEmpty, Always, TestRun (
4074       [["part_disk"; "/dev/sda"; "gpt"]])],
4075    "partition whole disk with a single primary partition",
4076    "\
4077 This command is simply a combination of C<guestfs_part_init>
4078 followed by C<guestfs_part_add> to create a single primary partition
4079 covering the whole disk.
4080
4081 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4082 but other possible values are described in C<guestfs_part_init>.");
4083
4084   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4085    [InitEmpty, Always, TestRun (
4086       [["part_disk"; "/dev/sda"; "mbr"];
4087        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4088    "make a partition bootable",
4089    "\
4090 This sets the bootable flag on partition numbered C<partnum> on
4091 device C<device>.  Note that partitions are numbered from 1.
4092
4093 The bootable flag is used by some PC BIOSes to determine which
4094 partition to boot from.  It is by no means universally recognized,
4095 and in any case if your operating system installed a boot
4096 sector on the device itself, then that takes precedence.");
4097
4098   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4099    [InitEmpty, Always, TestRun (
4100       [["part_disk"; "/dev/sda"; "gpt"];
4101        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4102    "set partition name",
4103    "\
4104 This sets the partition name on partition numbered C<partnum> on
4105 device C<device>.  Note that partitions are numbered from 1.
4106
4107 The partition name can only be set on certain types of partition
4108 table.  This works on C<gpt> but not on C<mbr> partitions.");
4109
4110   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4111    [], (* XXX Add a regression test for this. *)
4112    "list partitions on a device",
4113    "\
4114 This command parses the partition table on C<device> and
4115 returns the list of partitions found.
4116
4117 The fields in the returned structure are:
4118
4119 =over 4
4120
4121 =item B<part_num>
4122
4123 Partition number, counting from 1.
4124
4125 =item B<part_start>
4126
4127 Start of the partition I<in bytes>.  To get sectors you have to
4128 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4129
4130 =item B<part_end>
4131
4132 End of the partition in bytes.
4133
4134 =item B<part_size>
4135
4136 Size of the partition in bytes.
4137
4138 =back");
4139
4140   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4141    [InitEmpty, Always, TestOutput (
4142       [["part_disk"; "/dev/sda"; "gpt"];
4143        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4144    "get the partition table type",
4145    "\
4146 This command examines the partition table on C<device> and
4147 returns the partition table type (format) being used.
4148
4149 Common return values include: C<msdos> (a DOS/Windows style MBR
4150 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4151 values are possible, although unusual.  See C<guestfs_part_init>
4152 for a full list.");
4153
4154   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4155    [InitBasicFS, Always, TestOutputBuffer (
4156       [["fill"; "0x63"; "10"; "/test"];
4157        ["read_file"; "/test"]], "cccccccccc")],
4158    "fill a file with octets",
4159    "\
4160 This command creates a new file called C<path>.  The initial
4161 content of the file is C<len> octets of C<c>, where C<c>
4162 must be a number in the range C<[0..255]>.
4163
4164 To fill a file with zero bytes (sparsely), it is
4165 much more efficient to use C<guestfs_truncate_size>.");
4166
4167   ("available", (RErr, [StringList "groups"]), 216, [],
4168    [InitNone, Always, TestRun [["available"; ""]]],
4169    "test availability of some parts of the API",
4170    "\
4171 This command is used to check the availability of some
4172 groups of functionality in the appliance, which not all builds of
4173 the libguestfs appliance will be able to provide.
4174
4175 The libguestfs groups, and the functions that those
4176 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4177
4178 The argument C<groups> is a list of group names, eg:
4179 C<[\"inotify\", \"augeas\"]> would check for the availability of
4180 the Linux inotify functions and Augeas (configuration file
4181 editing) functions.
4182
4183 The command returns no error if I<all> requested groups are available.
4184
4185 It fails with an error if one or more of the requested
4186 groups is unavailable in the appliance.
4187
4188 If an unknown group name is included in the
4189 list of groups then an error is always returned.
4190
4191 I<Notes:>
4192
4193 =over 4
4194
4195 =item *
4196
4197 You must call C<guestfs_launch> before calling this function.
4198
4199 The reason is because we don't know what groups are
4200 supported by the appliance/daemon until it is running and can
4201 be queried.
4202
4203 =item *
4204
4205 If a group of functions is available, this does not necessarily
4206 mean that they will work.  You still have to check for errors
4207 when calling individual API functions even if they are
4208 available.
4209
4210 =item *
4211
4212 It is usually the job of distro packagers to build
4213 complete functionality into the libguestfs appliance.
4214 Upstream libguestfs, if built from source with all
4215 requirements satisfied, will support everything.
4216
4217 =item *
4218
4219 This call was added in version C<1.0.80>.  In previous
4220 versions of libguestfs all you could do would be to speculatively
4221 execute a command to find out if the daemon implemented it.
4222 See also C<guestfs_version>.
4223
4224 =back");
4225
4226   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4227    [InitBasicFS, Always, TestOutputBuffer (
4228       [["write_file"; "/src"; "hello, world"; "0"];
4229        ["dd"; "/src"; "/dest"];
4230        ["read_file"; "/dest"]], "hello, world")],
4231    "copy from source to destination using dd",
4232    "\
4233 This command copies from one source device or file C<src>
4234 to another destination device or file C<dest>.  Normally you
4235 would use this to copy to or from a device or partition, for
4236 example to duplicate a filesystem.
4237
4238 If the destination is a device, it must be as large or larger
4239 than the source file or device, otherwise the copy will fail.
4240 This command cannot do partial copies.");
4241
4242   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4243    [InitBasicFS, Always, TestOutputInt (
4244       [["write_file"; "/file"; "hello, world"; "0"];
4245        ["filesize"; "/file"]], 12)],
4246    "return the size of the file in bytes",
4247    "\
4248 This command returns the size of C<file> in bytes.
4249
4250 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4251 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4252 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4253
4254   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4255    [InitBasicFSonLVM, Always, TestOutputList (
4256       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4257        ["lvs"]], ["/dev/VG/LV2"])],
4258    "rename an LVM logical volume",
4259    "\
4260 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4261
4262   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4263    [InitBasicFSonLVM, Always, TestOutputList (
4264       [["umount"; "/"];
4265        ["vg_activate"; "false"; "VG"];
4266        ["vgrename"; "VG"; "VG2"];
4267        ["vg_activate"; "true"; "VG2"];
4268        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4269        ["vgs"]], ["VG2"])],
4270    "rename an LVM volume group",
4271    "\
4272 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4273
4274   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4275    [InitISOFS, Always, TestOutputBuffer (
4276       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4277    "list the contents of a single file in an initrd",
4278    "\
4279 This command unpacks the file C<filename> from the initrd file
4280 called C<initrdpath>.  The filename must be given I<without> the
4281 initial C</> character.
4282
4283 For example, in guestfish you could use the following command
4284 to examine the boot script (usually called C</init>)
4285 contained in a Linux initrd or initramfs image:
4286
4287  initrd-cat /boot/initrd-<version>.img init
4288
4289 See also C<guestfs_initrd_list>.");
4290
4291 ]
4292
4293 let all_functions = non_daemon_functions @ daemon_functions
4294
4295 (* In some places we want the functions to be displayed sorted
4296  * alphabetically, so this is useful:
4297  *)
4298 let all_functions_sorted =
4299   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4300                compare n1 n2) all_functions
4301
4302 (* Field types for structures. *)
4303 type field =
4304   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4305   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4306   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4307   | FUInt32
4308   | FInt32
4309   | FUInt64
4310   | FInt64
4311   | FBytes                      (* Any int measure that counts bytes. *)
4312   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4313   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4314
4315 (* Because we generate extra parsing code for LVM command line tools,
4316  * we have to pull out the LVM columns separately here.
4317  *)
4318 let lvm_pv_cols = [
4319   "pv_name", FString;
4320   "pv_uuid", FUUID;
4321   "pv_fmt", FString;
4322   "pv_size", FBytes;
4323   "dev_size", FBytes;
4324   "pv_free", FBytes;
4325   "pv_used", FBytes;
4326   "pv_attr", FString (* XXX *);
4327   "pv_pe_count", FInt64;
4328   "pv_pe_alloc_count", FInt64;
4329   "pv_tags", FString;
4330   "pe_start", FBytes;
4331   "pv_mda_count", FInt64;
4332   "pv_mda_free", FBytes;
4333   (* Not in Fedora 10:
4334      "pv_mda_size", FBytes;
4335   *)
4336 ]
4337 let lvm_vg_cols = [
4338   "vg_name", FString;
4339   "vg_uuid", FUUID;
4340   "vg_fmt", FString;
4341   "vg_attr", FString (* XXX *);
4342   "vg_size", FBytes;
4343   "vg_free", FBytes;
4344   "vg_sysid", FString;
4345   "vg_extent_size", FBytes;
4346   "vg_extent_count", FInt64;
4347   "vg_free_count", FInt64;
4348   "max_lv", FInt64;
4349   "max_pv", FInt64;
4350   "pv_count", FInt64;
4351   "lv_count", FInt64;
4352   "snap_count", FInt64;
4353   "vg_seqno", FInt64;
4354   "vg_tags", FString;
4355   "vg_mda_count", FInt64;
4356   "vg_mda_free", FBytes;
4357   (* Not in Fedora 10:
4358      "vg_mda_size", FBytes;
4359   *)
4360 ]
4361 let lvm_lv_cols = [
4362   "lv_name", FString;
4363   "lv_uuid", FUUID;
4364   "lv_attr", FString (* XXX *);
4365   "lv_major", FInt64;
4366   "lv_minor", FInt64;
4367   "lv_kernel_major", FInt64;
4368   "lv_kernel_minor", FInt64;
4369   "lv_size", FBytes;
4370   "seg_count", FInt64;
4371   "origin", FString;
4372   "snap_percent", FOptPercent;
4373   "copy_percent", FOptPercent;
4374   "move_pv", FString;
4375   "lv_tags", FString;
4376   "mirror_log", FString;
4377   "modules", FString;
4378 ]
4379
4380 (* Names and fields in all structures (in RStruct and RStructList)
4381  * that we support.
4382  *)
4383 let structs = [
4384   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4385    * not use this struct in any new code.
4386    *)
4387   "int_bool", [
4388     "i", FInt32;                (* for historical compatibility *)
4389     "b", FInt32;                (* for historical compatibility *)
4390   ];
4391
4392   (* LVM PVs, VGs, LVs. *)
4393   "lvm_pv", lvm_pv_cols;
4394   "lvm_vg", lvm_vg_cols;
4395   "lvm_lv", lvm_lv_cols;
4396
4397   (* Column names and types from stat structures.
4398    * NB. Can't use things like 'st_atime' because glibc header files
4399    * define some of these as macros.  Ugh.
4400    *)
4401   "stat", [
4402     "dev", FInt64;
4403     "ino", FInt64;
4404     "mode", FInt64;
4405     "nlink", FInt64;
4406     "uid", FInt64;
4407     "gid", FInt64;
4408     "rdev", FInt64;
4409     "size", FInt64;
4410     "blksize", FInt64;
4411     "blocks", FInt64;
4412     "atime", FInt64;
4413     "mtime", FInt64;
4414     "ctime", FInt64;
4415   ];
4416   "statvfs", [
4417     "bsize", FInt64;
4418     "frsize", FInt64;
4419     "blocks", FInt64;
4420     "bfree", FInt64;
4421     "bavail", FInt64;
4422     "files", FInt64;
4423     "ffree", FInt64;
4424     "favail", FInt64;
4425     "fsid", FInt64;
4426     "flag", FInt64;
4427     "namemax", FInt64;
4428   ];
4429
4430   (* Column names in dirent structure. *)
4431   "dirent", [
4432     "ino", FInt64;
4433     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4434     "ftyp", FChar;
4435     "name", FString;
4436   ];
4437
4438   (* Version numbers. *)
4439   "version", [
4440     "major", FInt64;
4441     "minor", FInt64;
4442     "release", FInt64;
4443     "extra", FString;
4444   ];
4445
4446   (* Extended attribute. *)
4447   "xattr", [
4448     "attrname", FString;
4449     "attrval", FBuffer;
4450   ];
4451
4452   (* Inotify events. *)
4453   "inotify_event", [
4454     "in_wd", FInt64;
4455     "in_mask", FUInt32;
4456     "in_cookie", FUInt32;
4457     "in_name", FString;
4458   ];
4459
4460   (* Partition table entry. *)
4461   "partition", [
4462     "part_num", FInt32;
4463     "part_start", FBytes;
4464     "part_end", FBytes;
4465     "part_size", FBytes;
4466   ];
4467 ] (* end of structs *)
4468
4469 (* Ugh, Java has to be different ..
4470  * These names are also used by the Haskell bindings.
4471  *)
4472 let java_structs = [
4473   "int_bool", "IntBool";
4474   "lvm_pv", "PV";
4475   "lvm_vg", "VG";
4476   "lvm_lv", "LV";
4477   "stat", "Stat";
4478   "statvfs", "StatVFS";
4479   "dirent", "Dirent";
4480   "version", "Version";
4481   "xattr", "XAttr";
4482   "inotify_event", "INotifyEvent";
4483   "partition", "Partition";
4484 ]
4485
4486 (* What structs are actually returned. *)
4487 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4488
4489 (* Returns a list of RStruct/RStructList structs that are returned
4490  * by any function.  Each element of returned list is a pair:
4491  *
4492  * (structname, RStructOnly)
4493  *    == there exists function which returns RStruct (_, structname)
4494  * (structname, RStructListOnly)
4495  *    == there exists function which returns RStructList (_, structname)
4496  * (structname, RStructAndList)
4497  *    == there are functions returning both RStruct (_, structname)
4498  *                                      and RStructList (_, structname)
4499  *)
4500 let rstructs_used_by functions =
4501   (* ||| is a "logical OR" for rstructs_used_t *)
4502   let (|||) a b =
4503     match a, b with
4504     | RStructAndList, _
4505     | _, RStructAndList -> RStructAndList
4506     | RStructOnly, RStructListOnly
4507     | RStructListOnly, RStructOnly -> RStructAndList
4508     | RStructOnly, RStructOnly -> RStructOnly
4509     | RStructListOnly, RStructListOnly -> RStructListOnly
4510   in
4511
4512   let h = Hashtbl.create 13 in
4513
4514   (* if elem->oldv exists, update entry using ||| operator,
4515    * else just add elem->newv to the hash
4516    *)
4517   let update elem newv =
4518     try  let oldv = Hashtbl.find h elem in
4519          Hashtbl.replace h elem (newv ||| oldv)
4520     with Not_found -> Hashtbl.add h elem newv
4521   in
4522
4523   List.iter (
4524     fun (_, style, _, _, _, _, _) ->
4525       match fst style with
4526       | RStruct (_, structname) -> update structname RStructOnly
4527       | RStructList (_, structname) -> update structname RStructListOnly
4528       | _ -> ()
4529   ) functions;
4530
4531   (* return key->values as a list of (key,value) *)
4532   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4533
4534 (* Used for testing language bindings. *)
4535 type callt =
4536   | CallString of string
4537   | CallOptString of string option
4538   | CallStringList of string list
4539   | CallInt of int
4540   | CallInt64 of int64
4541   | CallBool of bool
4542
4543 (* Used to memoize the result of pod2text. *)
4544 let pod2text_memo_filename = "src/.pod2text.data"
4545 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4546   try
4547     let chan = open_in pod2text_memo_filename in
4548     let v = input_value chan in
4549     close_in chan;
4550     v
4551   with
4552     _ -> Hashtbl.create 13
4553 let pod2text_memo_updated () =
4554   let chan = open_out pod2text_memo_filename in
4555   output_value chan pod2text_memo;
4556   close_out chan
4557
4558 (* Useful functions.
4559  * Note we don't want to use any external OCaml libraries which
4560  * makes this a bit harder than it should be.
4561  *)
4562 module StringMap = Map.Make (String)
4563
4564 let failwithf fs = ksprintf failwith fs
4565
4566 let unique = let i = ref 0 in fun () -> incr i; !i
4567
4568 let replace_char s c1 c2 =
4569   let s2 = String.copy s in
4570   let r = ref false in
4571   for i = 0 to String.length s2 - 1 do
4572     if String.unsafe_get s2 i = c1 then (
4573       String.unsafe_set s2 i c2;
4574       r := true
4575     )
4576   done;
4577   if not !r then s else s2
4578
4579 let isspace c =
4580   c = ' '
4581   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4582
4583 let triml ?(test = isspace) str =
4584   let i = ref 0 in
4585   let n = ref (String.length str) in
4586   while !n > 0 && test str.[!i]; do
4587     decr n;
4588     incr i
4589   done;
4590   if !i = 0 then str
4591   else String.sub str !i !n
4592
4593 let trimr ?(test = isspace) str =
4594   let n = ref (String.length str) in
4595   while !n > 0 && test str.[!n-1]; do
4596     decr n
4597   done;
4598   if !n = String.length str then str
4599   else String.sub str 0 !n
4600
4601 let trim ?(test = isspace) str =
4602   trimr ~test (triml ~test str)
4603
4604 let rec find s sub =
4605   let len = String.length s in
4606   let sublen = String.length sub in
4607   let rec loop i =
4608     if i <= len-sublen then (
4609       let rec loop2 j =
4610         if j < sublen then (
4611           if s.[i+j] = sub.[j] then loop2 (j+1)
4612           else -1
4613         ) else
4614           i (* found *)
4615       in
4616       let r = loop2 0 in
4617       if r = -1 then loop (i+1) else r
4618     ) else
4619       -1 (* not found *)
4620   in
4621   loop 0
4622
4623 let rec replace_str s s1 s2 =
4624   let len = String.length s in
4625   let sublen = String.length s1 in
4626   let i = find s s1 in
4627   if i = -1 then s
4628   else (
4629     let s' = String.sub s 0 i in
4630     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4631     s' ^ s2 ^ replace_str s'' s1 s2
4632   )
4633
4634 let rec string_split sep str =
4635   let len = String.length str in
4636   let seplen = String.length sep in
4637   let i = find str sep in
4638   if i = -1 then [str]
4639   else (
4640     let s' = String.sub str 0 i in
4641     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4642     s' :: string_split sep s''
4643   )
4644
4645 let files_equal n1 n2 =
4646   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4647   match Sys.command cmd with
4648   | 0 -> true
4649   | 1 -> false
4650   | i -> failwithf "%s: failed with error code %d" cmd i
4651
4652 let rec filter_map f = function
4653   | [] -> []
4654   | x :: xs ->
4655       match f x with
4656       | Some y -> y :: filter_map f xs
4657       | None -> filter_map f xs
4658
4659 let rec find_map f = function
4660   | [] -> raise Not_found
4661   | x :: xs ->
4662       match f x with
4663       | Some y -> y
4664       | None -> find_map f xs
4665
4666 let iteri f xs =
4667   let rec loop i = function
4668     | [] -> ()
4669     | x :: xs -> f i x; loop (i+1) xs
4670   in
4671   loop 0 xs
4672
4673 let mapi f xs =
4674   let rec loop i = function
4675     | [] -> []
4676     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4677   in
4678   loop 0 xs
4679
4680 let count_chars c str =
4681   let count = ref 0 in
4682   for i = 0 to String.length str - 1 do
4683     if c = String.unsafe_get str i then incr count
4684   done;
4685   !count
4686
4687 let name_of_argt = function
4688   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4689   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4690   | FileIn n | FileOut n -> n
4691
4692 let java_name_of_struct typ =
4693   try List.assoc typ java_structs
4694   with Not_found ->
4695     failwithf
4696       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4697
4698 let cols_of_struct typ =
4699   try List.assoc typ structs
4700   with Not_found ->
4701     failwithf "cols_of_struct: unknown struct %s" typ
4702
4703 let seq_of_test = function
4704   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4705   | TestOutputListOfDevices (s, _)
4706   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4707   | TestOutputTrue s | TestOutputFalse s
4708   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4709   | TestOutputStruct (s, _)
4710   | TestLastFail s -> s
4711
4712 (* Handling for function flags. *)
4713 let protocol_limit_warning =
4714   "Because of the message protocol, there is a transfer limit
4715 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4716
4717 let danger_will_robinson =
4718   "B<This command is dangerous.  Without careful use you
4719 can easily destroy all your data>."
4720
4721 let deprecation_notice flags =
4722   try
4723     let alt =
4724       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4725     let txt =
4726       sprintf "This function is deprecated.
4727 In new code, use the C<%s> call instead.
4728
4729 Deprecated functions will not be removed from the API, but the
4730 fact that they are deprecated indicates that there are problems
4731 with correct use of these functions." alt in
4732     Some txt
4733   with
4734     Not_found -> None
4735
4736 (* Create list of optional groups. *)
4737 let optgroups =
4738   let h = Hashtbl.create 13 in
4739   List.iter (
4740     fun (name, _, _, flags, _, _, _) ->
4741       List.iter (
4742         function
4743         | Optional group ->
4744             let names = try Hashtbl.find h group with Not_found -> [] in
4745             Hashtbl.replace h group (name :: names)
4746         | _ -> ()
4747       ) flags
4748   ) daemon_functions;
4749   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4750   let groups =
4751     List.map (
4752       fun group -> group, List.sort compare (Hashtbl.find h group)
4753     ) groups in
4754   List.sort (fun x y -> compare (fst x) (fst y)) groups
4755
4756 (* Check function names etc. for consistency. *)
4757 let check_functions () =
4758   let contains_uppercase str =
4759     let len = String.length str in
4760     let rec loop i =
4761       if i >= len then false
4762       else (
4763         let c = str.[i] in
4764         if c >= 'A' && c <= 'Z' then true
4765         else loop (i+1)
4766       )
4767     in
4768     loop 0
4769   in
4770
4771   (* Check function names. *)
4772   List.iter (
4773     fun (name, _, _, _, _, _, _) ->
4774       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4775         failwithf "function name %s does not need 'guestfs' prefix" name;
4776       if name = "" then
4777         failwithf "function name is empty";
4778       if name.[0] < 'a' || name.[0] > 'z' then
4779         failwithf "function name %s must start with lowercase a-z" name;
4780       if String.contains name '-' then
4781         failwithf "function name %s should not contain '-', use '_' instead."
4782           name
4783   ) all_functions;
4784
4785   (* Check function parameter/return names. *)
4786   List.iter (
4787     fun (name, style, _, _, _, _, _) ->
4788       let check_arg_ret_name n =
4789         if contains_uppercase n then
4790           failwithf "%s param/ret %s should not contain uppercase chars"
4791             name n;
4792         if String.contains n '-' || String.contains n '_' then
4793           failwithf "%s param/ret %s should not contain '-' or '_'"
4794             name n;
4795         if n = "value" then
4796           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;
4797         if n = "int" || n = "char" || n = "short" || n = "long" then
4798           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4799         if n = "i" || n = "n" then
4800           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4801         if n = "argv" || n = "args" then
4802           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4803
4804         (* List Haskell, OCaml and C keywords here.
4805          * http://www.haskell.org/haskellwiki/Keywords
4806          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4807          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4808          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4809          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4810          * Omitting _-containing words, since they're handled above.
4811          * Omitting the OCaml reserved word, "val", is ok,
4812          * and saves us from renaming several parameters.
4813          *)
4814         let reserved = [
4815           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4816           "char"; "class"; "const"; "constraint"; "continue"; "data";
4817           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4818           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4819           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4820           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4821           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4822           "interface";
4823           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4824           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4825           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4826           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4827           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4828           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4829           "volatile"; "when"; "where"; "while";
4830           ] in
4831         if List.mem n reserved then
4832           failwithf "%s has param/ret using reserved word %s" name n;
4833       in
4834
4835       (match fst style with
4836        | RErr -> ()
4837        | RInt n | RInt64 n | RBool n
4838        | RConstString n | RConstOptString n | RString n
4839        | RStringList n | RStruct (n, _) | RStructList (n, _)
4840        | RHashtable n | RBufferOut n ->
4841            check_arg_ret_name n
4842       );
4843       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4844   ) all_functions;
4845
4846   (* Check short descriptions. *)
4847   List.iter (
4848     fun (name, _, _, _, _, shortdesc, _) ->
4849       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4850         failwithf "short description of %s should begin with lowercase." name;
4851       let c = shortdesc.[String.length shortdesc-1] in
4852       if c = '\n' || c = '.' then
4853         failwithf "short description of %s should not end with . or \\n." name
4854   ) all_functions;
4855
4856   (* Check long dscriptions. *)
4857   List.iter (
4858     fun (name, _, _, _, _, _, longdesc) ->
4859       if longdesc.[String.length longdesc-1] = '\n' then
4860         failwithf "long description of %s should not end with \\n." name
4861   ) all_functions;
4862
4863   (* Check proc_nrs. *)
4864   List.iter (
4865     fun (name, _, proc_nr, _, _, _, _) ->
4866       if proc_nr <= 0 then
4867         failwithf "daemon function %s should have proc_nr > 0" name
4868   ) daemon_functions;
4869
4870   List.iter (
4871     fun (name, _, proc_nr, _, _, _, _) ->
4872       if proc_nr <> -1 then
4873         failwithf "non-daemon function %s should have proc_nr -1" name
4874   ) non_daemon_functions;
4875
4876   let proc_nrs =
4877     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4878       daemon_functions in
4879   let proc_nrs =
4880     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4881   let rec loop = function
4882     | [] -> ()
4883     | [_] -> ()
4884     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4885         loop rest
4886     | (name1,nr1) :: (name2,nr2) :: _ ->
4887         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4888           name1 name2 nr1 nr2
4889   in
4890   loop proc_nrs;
4891
4892   (* Check tests. *)
4893   List.iter (
4894     function
4895       (* Ignore functions that have no tests.  We generate a
4896        * warning when the user does 'make check' instead.
4897        *)
4898     | name, _, _, _, [], _, _ -> ()
4899     | name, _, _, _, tests, _, _ ->
4900         let funcs =
4901           List.map (
4902             fun (_, _, test) ->
4903               match seq_of_test test with
4904               | [] ->
4905                   failwithf "%s has a test containing an empty sequence" name
4906               | cmds -> List.map List.hd cmds
4907           ) tests in
4908         let funcs = List.flatten funcs in
4909
4910         let tested = List.mem name funcs in
4911
4912         if not tested then
4913           failwithf "function %s has tests but does not test itself" name
4914   ) all_functions
4915
4916 (* 'pr' prints to the current output file. *)
4917 let chan = ref Pervasives.stdout
4918 let lines = ref 0
4919 let pr fs =
4920   ksprintf
4921     (fun str ->
4922        let i = count_chars '\n' str in
4923        lines := !lines + i;
4924        output_string !chan str
4925     ) fs
4926
4927 let copyright_years =
4928   let this_year = 1900 + (localtime (time ())).tm_year in
4929   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4930
4931 (* Generate a header block in a number of standard styles. *)
4932 type comment_style =
4933     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4934 type license = GPLv2plus | LGPLv2plus
4935
4936 let generate_header ?(extra_inputs = []) comment license =
4937   let inputs = "src/generator.ml" :: extra_inputs in
4938   let c = match comment with
4939     | CStyle ->         pr "/* "; " *"
4940     | CPlusPlusStyle -> pr "// "; "//"
4941     | HashStyle ->      pr "# ";  "#"
4942     | OCamlStyle ->     pr "(* "; " *"
4943     | HaskellStyle ->   pr "{- "; "  " in
4944   pr "libguestfs generated file\n";
4945   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4946   List.iter (pr "%s   %s\n" c) inputs;
4947   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4948   pr "%s\n" c;
4949   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4950   pr "%s\n" c;
4951   (match license with
4952    | GPLv2plus ->
4953        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4954        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4955        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4956        pr "%s (at your option) any later version.\n" c;
4957        pr "%s\n" c;
4958        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4959        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4960        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4961        pr "%s GNU General Public License for more details.\n" c;
4962        pr "%s\n" c;
4963        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4964        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4965        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4966
4967    | LGPLv2plus ->
4968        pr "%s This library is free software; you can redistribute it and/or\n" c;
4969        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4970        pr "%s License as published by the Free Software Foundation; either\n" c;
4971        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4972        pr "%s\n" c;
4973        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4974        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4975        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4976        pr "%s Lesser General Public License for more details.\n" c;
4977        pr "%s\n" c;
4978        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4979        pr "%s License along with this library; if not, write to the Free Software\n" c;
4980        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4981   );
4982   (match comment with
4983    | CStyle -> pr " */\n"
4984    | CPlusPlusStyle
4985    | HashStyle -> ()
4986    | OCamlStyle -> pr " *)\n"
4987    | HaskellStyle -> pr "-}\n"
4988   );
4989   pr "\n"
4990
4991 (* Start of main code generation functions below this line. *)
4992
4993 (* Generate the pod documentation for the C API. *)
4994 let rec generate_actions_pod () =
4995   List.iter (
4996     fun (shortname, style, _, flags, _, _, longdesc) ->
4997       if not (List.mem NotInDocs flags) then (
4998         let name = "guestfs_" ^ shortname in
4999         pr "=head2 %s\n\n" name;
5000         pr " ";
5001         generate_prototype ~extern:false ~handle:"handle" name style;
5002         pr "\n\n";
5003         pr "%s\n\n" longdesc;
5004         (match fst style with
5005          | RErr ->
5006              pr "This function returns 0 on success or -1 on error.\n\n"
5007          | RInt _ ->
5008              pr "On error this function returns -1.\n\n"
5009          | RInt64 _ ->
5010              pr "On error this function returns -1.\n\n"
5011          | RBool _ ->
5012              pr "This function returns a C truth value on success or -1 on error.\n\n"
5013          | RConstString _ ->
5014              pr "This function returns a string, or NULL on error.
5015 The string is owned by the guest handle and must I<not> be freed.\n\n"
5016          | RConstOptString _ ->
5017              pr "This function returns a string which may be NULL.
5018 There is way to return an error from this function.
5019 The string is owned by the guest handle and must I<not> be freed.\n\n"
5020          | RString _ ->
5021              pr "This function returns a string, or NULL on error.
5022 I<The caller must free the returned string after use>.\n\n"
5023          | RStringList _ ->
5024              pr "This function returns a NULL-terminated array of strings
5025 (like L<environ(3)>), or NULL if there was an error.
5026 I<The caller must free the strings and the array after use>.\n\n"
5027          | RStruct (_, typ) ->
5028              pr "This function returns a C<struct guestfs_%s *>,
5029 or NULL if there was an error.
5030 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5031          | RStructList (_, typ) ->
5032              pr "This function returns a C<struct guestfs_%s_list *>
5033 (see E<lt>guestfs-structs.hE<gt>),
5034 or NULL if there was an error.
5035 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5036          | RHashtable _ ->
5037              pr "This function returns a NULL-terminated array of
5038 strings, or NULL if there was an error.
5039 The array of strings will always have length C<2n+1>, where
5040 C<n> keys and values alternate, followed by the trailing NULL entry.
5041 I<The caller must free the strings and the array after use>.\n\n"
5042          | RBufferOut _ ->
5043              pr "This function returns a buffer, or NULL on error.
5044 The size of the returned buffer is written to C<*size_r>.
5045 I<The caller must free the returned buffer after use>.\n\n"
5046         );
5047         if List.mem ProtocolLimitWarning flags then
5048           pr "%s\n\n" protocol_limit_warning;
5049         if List.mem DangerWillRobinson flags then
5050           pr "%s\n\n" danger_will_robinson;
5051         match deprecation_notice flags with
5052         | None -> ()
5053         | Some txt -> pr "%s\n\n" txt
5054       )
5055   ) all_functions_sorted
5056
5057 and generate_structs_pod () =
5058   (* Structs documentation. *)
5059   List.iter (
5060     fun (typ, cols) ->
5061       pr "=head2 guestfs_%s\n" typ;
5062       pr "\n";
5063       pr " struct guestfs_%s {\n" typ;
5064       List.iter (
5065         function
5066         | name, FChar -> pr "   char %s;\n" name
5067         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5068         | name, FInt32 -> pr "   int32_t %s;\n" name
5069         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5070         | name, FInt64 -> pr "   int64_t %s;\n" name
5071         | name, FString -> pr "   char *%s;\n" name
5072         | name, FBuffer ->
5073             pr "   /* The next two fields describe a byte array. */\n";
5074             pr "   uint32_t %s_len;\n" name;
5075             pr "   char *%s;\n" name
5076         | name, FUUID ->
5077             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5078             pr "   char %s[32];\n" name
5079         | name, FOptPercent ->
5080             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5081             pr "   float %s;\n" name
5082       ) cols;
5083       pr " };\n";
5084       pr " \n";
5085       pr " struct guestfs_%s_list {\n" typ;
5086       pr "   uint32_t len; /* Number of elements in list. */\n";
5087       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5088       pr " };\n";
5089       pr " \n";
5090       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5091       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5092         typ typ;
5093       pr "\n"
5094   ) structs
5095
5096 and generate_availability_pod () =
5097   (* Availability documentation. *)
5098   pr "=over 4\n";
5099   pr "\n";
5100   List.iter (
5101     fun (group, functions) ->
5102       pr "=item B<%s>\n" group;
5103       pr "\n";
5104       pr "The following functions:\n";
5105       List.iter (pr "L</guestfs_%s>\n") functions;
5106       pr "\n"
5107   ) optgroups;
5108   pr "=back\n";
5109   pr "\n"
5110
5111 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5112  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5113  *
5114  * We have to use an underscore instead of a dash because otherwise
5115  * rpcgen generates incorrect code.
5116  *
5117  * This header is NOT exported to clients, but see also generate_structs_h.
5118  *)
5119 and generate_xdr () =
5120   generate_header CStyle LGPLv2plus;
5121
5122   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5123   pr "typedef string str<>;\n";
5124   pr "\n";
5125
5126   (* Internal structures. *)
5127   List.iter (
5128     function
5129     | typ, cols ->
5130         pr "struct guestfs_int_%s {\n" typ;
5131         List.iter (function
5132                    | name, FChar -> pr "  char %s;\n" name
5133                    | name, FString -> pr "  string %s<>;\n" name
5134                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5135                    | name, FUUID -> pr "  opaque %s[32];\n" name
5136                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5137                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5138                    | name, FOptPercent -> pr "  float %s;\n" name
5139                   ) cols;
5140         pr "};\n";
5141         pr "\n";
5142         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5143         pr "\n";
5144   ) structs;
5145
5146   List.iter (
5147     fun (shortname, style, _, _, _, _, _) ->
5148       let name = "guestfs_" ^ shortname in
5149
5150       (match snd style with
5151        | [] -> ()
5152        | args ->
5153            pr "struct %s_args {\n" name;
5154            List.iter (
5155              function
5156              | Pathname n | Device n | Dev_or_Path n | String n ->
5157                  pr "  string %s<>;\n" n
5158              | OptString n -> pr "  str *%s;\n" n
5159              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5160              | Bool n -> pr "  bool %s;\n" n
5161              | Int n -> pr "  int %s;\n" n
5162              | Int64 n -> pr "  hyper %s;\n" n
5163              | FileIn _ | FileOut _ -> ()
5164            ) args;
5165            pr "};\n\n"
5166       );
5167       (match fst style with
5168        | RErr -> ()
5169        | RInt n ->
5170            pr "struct %s_ret {\n" name;
5171            pr "  int %s;\n" n;
5172            pr "};\n\n"
5173        | RInt64 n ->
5174            pr "struct %s_ret {\n" name;
5175            pr "  hyper %s;\n" n;
5176            pr "};\n\n"
5177        | RBool n ->
5178            pr "struct %s_ret {\n" name;
5179            pr "  bool %s;\n" n;
5180            pr "};\n\n"
5181        | RConstString _ | RConstOptString _ ->
5182            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5183        | RString n ->
5184            pr "struct %s_ret {\n" name;
5185            pr "  string %s<>;\n" n;
5186            pr "};\n\n"
5187        | RStringList n ->
5188            pr "struct %s_ret {\n" name;
5189            pr "  str %s<>;\n" n;
5190            pr "};\n\n"
5191        | RStruct (n, typ) ->
5192            pr "struct %s_ret {\n" name;
5193            pr "  guestfs_int_%s %s;\n" typ n;
5194            pr "};\n\n"
5195        | RStructList (n, typ) ->
5196            pr "struct %s_ret {\n" name;
5197            pr "  guestfs_int_%s_list %s;\n" typ n;
5198            pr "};\n\n"
5199        | RHashtable n ->
5200            pr "struct %s_ret {\n" name;
5201            pr "  str %s<>;\n" n;
5202            pr "};\n\n"
5203        | RBufferOut n ->
5204            pr "struct %s_ret {\n" name;
5205            pr "  opaque %s<>;\n" n;
5206            pr "};\n\n"
5207       );
5208   ) daemon_functions;
5209
5210   (* Table of procedure numbers. *)
5211   pr "enum guestfs_procedure {\n";
5212   List.iter (
5213     fun (shortname, _, proc_nr, _, _, _, _) ->
5214       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5215   ) daemon_functions;
5216   pr "  GUESTFS_PROC_NR_PROCS\n";
5217   pr "};\n";
5218   pr "\n";
5219
5220   (* Having to choose a maximum message size is annoying for several
5221    * reasons (it limits what we can do in the API), but it (a) makes
5222    * the protocol a lot simpler, and (b) provides a bound on the size
5223    * of the daemon which operates in limited memory space.
5224    *)
5225   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5226   pr "\n";
5227
5228   (* Message header, etc. *)
5229   pr "\
5230 /* The communication protocol is now documented in the guestfs(3)
5231  * manpage.
5232  */
5233
5234 const GUESTFS_PROGRAM = 0x2000F5F5;
5235 const GUESTFS_PROTOCOL_VERSION = 1;
5236
5237 /* These constants must be larger than any possible message length. */
5238 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5239 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5240
5241 enum guestfs_message_direction {
5242   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5243   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5244 };
5245
5246 enum guestfs_message_status {
5247   GUESTFS_STATUS_OK = 0,
5248   GUESTFS_STATUS_ERROR = 1
5249 };
5250
5251 const GUESTFS_ERROR_LEN = 256;
5252
5253 struct guestfs_message_error {
5254   string error_message<GUESTFS_ERROR_LEN>;
5255 };
5256
5257 struct guestfs_message_header {
5258   unsigned prog;                     /* GUESTFS_PROGRAM */
5259   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5260   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5261   guestfs_message_direction direction;
5262   unsigned serial;                   /* message serial number */
5263   guestfs_message_status status;
5264 };
5265
5266 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5267
5268 struct guestfs_chunk {
5269   int cancel;                        /* if non-zero, transfer is cancelled */
5270   /* data size is 0 bytes if the transfer has finished successfully */
5271   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5272 };
5273 "
5274
5275 (* Generate the guestfs-structs.h file. *)
5276 and generate_structs_h () =
5277   generate_header CStyle LGPLv2plus;
5278
5279   (* This is a public exported header file containing various
5280    * structures.  The structures are carefully written to have
5281    * exactly the same in-memory format as the XDR structures that
5282    * we use on the wire to the daemon.  The reason for creating
5283    * copies of these structures here is just so we don't have to
5284    * export the whole of guestfs_protocol.h (which includes much
5285    * unrelated and XDR-dependent stuff that we don't want to be
5286    * public, or required by clients).
5287    *
5288    * To reiterate, we will pass these structures to and from the
5289    * client with a simple assignment or memcpy, so the format
5290    * must be identical to what rpcgen / the RFC defines.
5291    *)
5292
5293   (* Public structures. *)
5294   List.iter (
5295     fun (typ, cols) ->
5296       pr "struct guestfs_%s {\n" typ;
5297       List.iter (
5298         function
5299         | name, FChar -> pr "  char %s;\n" name
5300         | name, FString -> pr "  char *%s;\n" name
5301         | name, FBuffer ->
5302             pr "  uint32_t %s_len;\n" name;
5303             pr "  char *%s;\n" name
5304         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5305         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5306         | name, FInt32 -> pr "  int32_t %s;\n" name
5307         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5308         | name, FInt64 -> pr "  int64_t %s;\n" name
5309         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5310       ) cols;
5311       pr "};\n";
5312       pr "\n";
5313       pr "struct guestfs_%s_list {\n" typ;
5314       pr "  uint32_t len;\n";
5315       pr "  struct guestfs_%s *val;\n" typ;
5316       pr "};\n";
5317       pr "\n";
5318       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5319       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5320       pr "\n"
5321   ) structs
5322
5323 (* Generate the guestfs-actions.h file. *)
5324 and generate_actions_h () =
5325   generate_header CStyle LGPLv2plus;
5326   List.iter (
5327     fun (shortname, style, _, _, _, _, _) ->
5328       let name = "guestfs_" ^ shortname in
5329       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5330         name style
5331   ) all_functions
5332
5333 (* Generate the guestfs-internal-actions.h file. *)
5334 and generate_internal_actions_h () =
5335   generate_header CStyle LGPLv2plus;
5336   List.iter (
5337     fun (shortname, style, _, _, _, _, _) ->
5338       let name = "guestfs__" ^ shortname in
5339       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5340         name style
5341   ) non_daemon_functions
5342
5343 (* Generate the client-side dispatch stubs. *)
5344 and generate_client_actions () =
5345   generate_header CStyle LGPLv2plus;
5346
5347   pr "\
5348 #include <stdio.h>
5349 #include <stdlib.h>
5350 #include <stdint.h>
5351 #include <inttypes.h>
5352
5353 #include \"guestfs.h\"
5354 #include \"guestfs-internal.h\"
5355 #include \"guestfs-internal-actions.h\"
5356 #include \"guestfs_protocol.h\"
5357
5358 #define error guestfs_error
5359 //#define perrorf guestfs_perrorf
5360 #define safe_malloc guestfs_safe_malloc
5361 #define safe_realloc guestfs_safe_realloc
5362 //#define safe_strdup guestfs_safe_strdup
5363 #define safe_memdup guestfs_safe_memdup
5364
5365 /* Check the return message from a call for validity. */
5366 static int
5367 check_reply_header (guestfs_h *g,
5368                     const struct guestfs_message_header *hdr,
5369                     unsigned int proc_nr, unsigned int serial)
5370 {
5371   if (hdr->prog != GUESTFS_PROGRAM) {
5372     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5373     return -1;
5374   }
5375   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5376     error (g, \"wrong protocol version (%%d/%%d)\",
5377            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5378     return -1;
5379   }
5380   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5381     error (g, \"unexpected message direction (%%d/%%d)\",
5382            hdr->direction, GUESTFS_DIRECTION_REPLY);
5383     return -1;
5384   }
5385   if (hdr->proc != proc_nr) {
5386     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5387     return -1;
5388   }
5389   if (hdr->serial != serial) {
5390     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5391     return -1;
5392   }
5393
5394   return 0;
5395 }
5396
5397 /* Check we are in the right state to run a high-level action. */
5398 static int
5399 check_state (guestfs_h *g, const char *caller)
5400 {
5401   if (!guestfs__is_ready (g)) {
5402     if (guestfs__is_config (g) || guestfs__is_launching (g))
5403       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5404         caller);
5405     else
5406       error (g, \"%%s called from the wrong state, %%d != READY\",
5407         caller, guestfs__get_state (g));
5408     return -1;
5409   }
5410   return 0;
5411 }
5412
5413 ";
5414
5415   (* Generate code to generate guestfish call traces. *)
5416   let trace_call shortname style =
5417     pr "  if (guestfs__get_trace (g)) {\n";
5418
5419     let needs_i =
5420       List.exists (function
5421                    | StringList _ | DeviceList _ -> true
5422                    | _ -> false) (snd style) in
5423     if needs_i then (
5424       pr "    int i;\n";
5425       pr "\n"
5426     );
5427
5428     pr "    printf (\"%s\");\n" shortname;
5429     List.iter (
5430       function
5431       | String n                        (* strings *)
5432       | Device n
5433       | Pathname n
5434       | Dev_or_Path n
5435       | FileIn n
5436       | FileOut n ->
5437           (* guestfish doesn't support string escaping, so neither do we *)
5438           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5439       | OptString n ->                  (* string option *)
5440           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5441           pr "    else printf (\" null\");\n"
5442       | StringList n
5443       | DeviceList n ->                 (* string list *)
5444           pr "    putchar (' ');\n";
5445           pr "    putchar ('\"');\n";
5446           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5447           pr "      if (i > 0) putchar (' ');\n";
5448           pr "      fputs (%s[i], stdout);\n" n;
5449           pr "    }\n";
5450           pr "    putchar ('\"');\n";
5451       | Bool n ->                       (* boolean *)
5452           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5453       | Int n ->                        (* int *)
5454           pr "    printf (\" %%d\", %s);\n" n
5455       | Int64 n ->
5456           pr "    printf (\" %%\" PRIi64, %s);\n" n
5457     ) (snd style);
5458     pr "    putchar ('\\n');\n";
5459     pr "  }\n";
5460     pr "\n";
5461   in
5462
5463   (* For non-daemon functions, generate a wrapper around each function. *)
5464   List.iter (
5465     fun (shortname, style, _, _, _, _, _) ->
5466       let name = "guestfs_" ^ shortname in
5467
5468       generate_prototype ~extern:false ~semicolon:false ~newline:true
5469         ~handle:"g" name style;
5470       pr "{\n";
5471       trace_call shortname style;
5472       pr "  return guestfs__%s " shortname;
5473       generate_c_call_args ~handle:"g" style;
5474       pr ";\n";
5475       pr "}\n";
5476       pr "\n"
5477   ) non_daemon_functions;
5478
5479   (* Client-side stubs for each function. *)
5480   List.iter (
5481     fun (shortname, style, _, _, _, _, _) ->
5482       let name = "guestfs_" ^ shortname in
5483
5484       (* Generate the action stub. *)
5485       generate_prototype ~extern:false ~semicolon:false ~newline:true
5486         ~handle:"g" name style;
5487
5488       let error_code =
5489         match fst style with
5490         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5491         | RConstString _ | RConstOptString _ ->
5492             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5493         | RString _ | RStringList _
5494         | RStruct _ | RStructList _
5495         | RHashtable _ | RBufferOut _ ->
5496             "NULL" in
5497
5498       pr "{\n";
5499
5500       (match snd style with
5501        | [] -> ()
5502        | _ -> pr "  struct %s_args args;\n" name
5503       );
5504
5505       pr "  guestfs_message_header hdr;\n";
5506       pr "  guestfs_message_error err;\n";
5507       let has_ret =
5508         match fst style with
5509         | RErr -> false
5510         | RConstString _ | RConstOptString _ ->
5511             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5512         | RInt _ | RInt64 _
5513         | RBool _ | RString _ | RStringList _
5514         | RStruct _ | RStructList _
5515         | RHashtable _ | RBufferOut _ ->
5516             pr "  struct %s_ret ret;\n" name;
5517             true in
5518
5519       pr "  int serial;\n";
5520       pr "  int r;\n";
5521       pr "\n";
5522       trace_call shortname style;
5523       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5524       pr "  guestfs___set_busy (g);\n";
5525       pr "\n";
5526
5527       (* Send the main header and arguments. *)
5528       (match snd style with
5529        | [] ->
5530            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5531              (String.uppercase shortname)
5532        | args ->
5533            List.iter (
5534              function
5535              | Pathname n | Device n | Dev_or_Path n | String n ->
5536                  pr "  args.%s = (char *) %s;\n" n n
5537              | OptString n ->
5538                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5539              | StringList n | DeviceList n ->
5540                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5541                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5542              | Bool n ->
5543                  pr "  args.%s = %s;\n" n n
5544              | Int n ->
5545                  pr "  args.%s = %s;\n" n n
5546              | Int64 n ->
5547                  pr "  args.%s = %s;\n" n n
5548              | FileIn _ | FileOut _ -> ()
5549            ) args;
5550            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5551              (String.uppercase shortname);
5552            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5553              name;
5554       );
5555       pr "  if (serial == -1) {\n";
5556       pr "    guestfs___end_busy (g);\n";
5557       pr "    return %s;\n" error_code;
5558       pr "  }\n";
5559       pr "\n";
5560
5561       (* Send any additional files (FileIn) requested. *)
5562       let need_read_reply_label = ref false in
5563       List.iter (
5564         function
5565         | FileIn n ->
5566             pr "  r = guestfs___send_file (g, %s);\n" n;
5567             pr "  if (r == -1) {\n";
5568             pr "    guestfs___end_busy (g);\n";
5569             pr "    return %s;\n" error_code;
5570             pr "  }\n";
5571             pr "  if (r == -2) /* daemon cancelled */\n";
5572             pr "    goto read_reply;\n";
5573             need_read_reply_label := true;
5574             pr "\n";
5575         | _ -> ()
5576       ) (snd style);
5577
5578       (* Wait for the reply from the remote end. *)
5579       if !need_read_reply_label then pr " read_reply:\n";
5580       pr "  memset (&hdr, 0, sizeof hdr);\n";
5581       pr "  memset (&err, 0, sizeof err);\n";
5582       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5583       pr "\n";
5584       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5585       if not has_ret then
5586         pr "NULL, NULL"
5587       else
5588         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5589       pr ");\n";
5590
5591       pr "  if (r == -1) {\n";
5592       pr "    guestfs___end_busy (g);\n";
5593       pr "    return %s;\n" error_code;
5594       pr "  }\n";
5595       pr "\n";
5596
5597       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5598         (String.uppercase shortname);
5599       pr "    guestfs___end_busy (g);\n";
5600       pr "    return %s;\n" error_code;
5601       pr "  }\n";
5602       pr "\n";
5603
5604       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5605       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5606       pr "    free (err.error_message);\n";
5607       pr "    guestfs___end_busy (g);\n";
5608       pr "    return %s;\n" error_code;
5609       pr "  }\n";
5610       pr "\n";
5611
5612       (* Expecting to receive further files (FileOut)? *)
5613       List.iter (
5614         function
5615         | FileOut n ->
5616             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5617             pr "    guestfs___end_busy (g);\n";
5618             pr "    return %s;\n" error_code;
5619             pr "  }\n";
5620             pr "\n";
5621         | _ -> ()
5622       ) (snd style);
5623
5624       pr "  guestfs___end_busy (g);\n";
5625
5626       (match fst style with
5627        | RErr -> pr "  return 0;\n"
5628        | RInt n | RInt64 n | RBool n ->
5629            pr "  return ret.%s;\n" n
5630        | RConstString _ | RConstOptString _ ->
5631            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5632        | RString n ->
5633            pr "  return ret.%s; /* caller will free */\n" n
5634        | RStringList n | RHashtable n ->
5635            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5636            pr "  ret.%s.%s_val =\n" n n;
5637            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5638            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5639              n n;
5640            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5641            pr "  return ret.%s.%s_val;\n" n n
5642        | RStruct (n, _) ->
5643            pr "  /* caller will free this */\n";
5644            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5645        | RStructList (n, _) ->
5646            pr "  /* caller will free this */\n";
5647            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5648        | RBufferOut n ->
5649            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5650            pr "   * _val might be NULL here.  To make the API saner for\n";
5651            pr "   * callers, we turn this case into a unique pointer (using\n";
5652            pr "   * malloc(1)).\n";
5653            pr "   */\n";
5654            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5655            pr "    *size_r = ret.%s.%s_len;\n" n n;
5656            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5657            pr "  } else {\n";
5658            pr "    free (ret.%s.%s_val);\n" n n;
5659            pr "    char *p = safe_malloc (g, 1);\n";
5660            pr "    *size_r = ret.%s.%s_len;\n" n n;
5661            pr "    return p;\n";
5662            pr "  }\n";
5663       );
5664
5665       pr "}\n\n"
5666   ) daemon_functions;
5667
5668   (* Functions to free structures. *)
5669   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5670   pr " * structure format is identical to the XDR format.  See note in\n";
5671   pr " * generator.ml.\n";
5672   pr " */\n";
5673   pr "\n";
5674
5675   List.iter (
5676     fun (typ, _) ->
5677       pr "void\n";
5678       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5679       pr "{\n";
5680       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5681       pr "  free (x);\n";
5682       pr "}\n";
5683       pr "\n";
5684
5685       pr "void\n";
5686       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5687       pr "{\n";
5688       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5689       pr "  free (x);\n";
5690       pr "}\n";
5691       pr "\n";
5692
5693   ) structs;
5694
5695 (* Generate daemon/actions.h. *)
5696 and generate_daemon_actions_h () =
5697   generate_header CStyle GPLv2plus;
5698
5699   pr "#include \"../src/guestfs_protocol.h\"\n";
5700   pr "\n";
5701
5702   List.iter (
5703     fun (name, style, _, _, _, _, _) ->
5704       generate_prototype
5705         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5706         name style;
5707   ) daemon_functions
5708
5709 (* Generate the linker script which controls the visibility of
5710  * symbols in the public ABI and ensures no other symbols get
5711  * exported accidentally.
5712  *)
5713 and generate_linker_script () =
5714   generate_header HashStyle GPLv2plus;
5715
5716   let globals = [
5717     "guestfs_create";
5718     "guestfs_close";
5719     "guestfs_get_error_handler";
5720     "guestfs_get_out_of_memory_handler";
5721     "guestfs_last_error";
5722     "guestfs_set_error_handler";
5723     "guestfs_set_launch_done_callback";
5724     "guestfs_set_log_message_callback";
5725     "guestfs_set_out_of_memory_handler";
5726     "guestfs_set_subprocess_quit_callback";
5727
5728     (* Unofficial parts of the API: the bindings code use these
5729      * functions, so it is useful to export them.
5730      *)
5731     "guestfs_safe_calloc";
5732     "guestfs_safe_malloc";
5733   ] in
5734   let functions =
5735     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5736       all_functions in
5737   let structs =
5738     List.concat (
5739       List.map (fun (typ, _) ->
5740                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5741         structs
5742     ) in
5743   let globals = List.sort compare (globals @ functions @ structs) in
5744
5745   pr "{\n";
5746   pr "    global:\n";
5747   List.iter (pr "        %s;\n") globals;
5748   pr "\n";
5749
5750   pr "    local:\n";
5751   pr "        *;\n";
5752   pr "};\n"
5753
5754 (* Generate the server-side stubs. *)
5755 and generate_daemon_actions () =
5756   generate_header CStyle GPLv2plus;
5757
5758   pr "#include <config.h>\n";
5759   pr "\n";
5760   pr "#include <stdio.h>\n";
5761   pr "#include <stdlib.h>\n";
5762   pr "#include <string.h>\n";
5763   pr "#include <inttypes.h>\n";
5764   pr "#include <rpc/types.h>\n";
5765   pr "#include <rpc/xdr.h>\n";
5766   pr "\n";
5767   pr "#include \"daemon.h\"\n";
5768   pr "#include \"c-ctype.h\"\n";
5769   pr "#include \"../src/guestfs_protocol.h\"\n";
5770   pr "#include \"actions.h\"\n";
5771   pr "\n";
5772
5773   List.iter (
5774     fun (name, style, _, _, _, _, _) ->
5775       (* Generate server-side stubs. *)
5776       pr "static void %s_stub (XDR *xdr_in)\n" name;
5777       pr "{\n";
5778       let error_code =
5779         match fst style with
5780         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5781         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5782         | RBool _ -> pr "  int r;\n"; "-1"
5783         | RConstString _ | RConstOptString _ ->
5784             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5785         | RString _ -> pr "  char *r;\n"; "NULL"
5786         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5787         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5788         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5789         | RBufferOut _ ->
5790             pr "  size_t size = 1;\n";
5791             pr "  char *r;\n";
5792             "NULL" in
5793
5794       (match snd style with
5795        | [] -> ()
5796        | args ->
5797            pr "  struct guestfs_%s_args args;\n" name;
5798            List.iter (
5799              function
5800              | Device n | Dev_or_Path n
5801              | Pathname n
5802              | String n -> ()
5803              | OptString n -> pr "  char *%s;\n" n
5804              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5805              | Bool n -> pr "  int %s;\n" n
5806              | Int n -> pr "  int %s;\n" n
5807              | Int64 n -> pr "  int64_t %s;\n" n
5808              | FileIn _ | FileOut _ -> ()
5809            ) args
5810       );
5811       pr "\n";
5812
5813       (match snd style with
5814        | [] -> ()
5815        | args ->
5816            pr "  memset (&args, 0, sizeof args);\n";
5817            pr "\n";
5818            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5819            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5820            pr "    return;\n";
5821            pr "  }\n";
5822            let pr_args n =
5823              pr "  char *%s = args.%s;\n" n n
5824            in
5825            let pr_list_handling_code n =
5826              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5827              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5828              pr "  if (%s == NULL) {\n" n;
5829              pr "    reply_with_perror (\"realloc\");\n";
5830              pr "    goto done;\n";
5831              pr "  }\n";
5832              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5833              pr "  args.%s.%s_val = %s;\n" n n n;
5834            in
5835            List.iter (
5836              function
5837              | Pathname n ->
5838                  pr_args n;
5839                  pr "  ABS_PATH (%s, goto done);\n" n;
5840              | Device n ->
5841                  pr_args n;
5842                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5843              | Dev_or_Path n ->
5844                  pr_args n;
5845                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5846              | String n -> pr_args n
5847              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5848              | StringList n ->
5849                  pr_list_handling_code n;
5850              | DeviceList n ->
5851                  pr_list_handling_code n;
5852                  pr "  /* Ensure that each is a device,\n";
5853                  pr "   * and perform device name translation. */\n";
5854                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5855                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5856                  pr "  }\n";
5857              | Bool n -> pr "  %s = args.%s;\n" n n
5858              | Int n -> pr "  %s = args.%s;\n" n n
5859              | Int64 n -> pr "  %s = args.%s;\n" n n
5860              | FileIn _ | FileOut _ -> ()
5861            ) args;
5862            pr "\n"
5863       );
5864
5865
5866       (* this is used at least for do_equal *)
5867       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5868         (* Emit NEED_ROOT just once, even when there are two or
5869            more Pathname args *)
5870         pr "  NEED_ROOT (goto done);\n";
5871       );
5872
5873       (* Don't want to call the impl with any FileIn or FileOut
5874        * parameters, since these go "outside" the RPC protocol.
5875        *)
5876       let args' =
5877         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5878           (snd style) in
5879       pr "  r = do_%s " name;
5880       generate_c_call_args (fst style, args');
5881       pr ";\n";
5882
5883       (match fst style with
5884        | RErr | RInt _ | RInt64 _ | RBool _
5885        | RConstString _ | RConstOptString _
5886        | RString _ | RStringList _ | RHashtable _
5887        | RStruct (_, _) | RStructList (_, _) ->
5888            pr "  if (r == %s)\n" error_code;
5889            pr "    /* do_%s has already called reply_with_error */\n" name;
5890            pr "    goto done;\n";
5891            pr "\n"
5892        | RBufferOut _ ->
5893            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5894            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5895            pr "   */\n";
5896            pr "  if (size == 1 && r == %s)\n" error_code;
5897            pr "    /* do_%s has already called reply_with_error */\n" name;
5898            pr "    goto done;\n";
5899            pr "\n"
5900       );
5901
5902       (* If there are any FileOut parameters, then the impl must
5903        * send its own reply.
5904        *)
5905       let no_reply =
5906         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5907       if no_reply then
5908         pr "  /* do_%s has already sent a reply */\n" name
5909       else (
5910         match fst style with
5911         | RErr -> pr "  reply (NULL, NULL);\n"
5912         | RInt n | RInt64 n | RBool n ->
5913             pr "  struct guestfs_%s_ret ret;\n" name;
5914             pr "  ret.%s = r;\n" n;
5915             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5916               name
5917         | RConstString _ | RConstOptString _ ->
5918             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5919         | RString n ->
5920             pr "  struct guestfs_%s_ret ret;\n" name;
5921             pr "  ret.%s = r;\n" n;
5922             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5923               name;
5924             pr "  free (r);\n"
5925         | RStringList n | RHashtable n ->
5926             pr "  struct guestfs_%s_ret ret;\n" name;
5927             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5928             pr "  ret.%s.%s_val = r;\n" n n;
5929             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5930               name;
5931             pr "  free_strings (r);\n"
5932         | RStruct (n, _) ->
5933             pr "  struct guestfs_%s_ret ret;\n" name;
5934             pr "  ret.%s = *r;\n" n;
5935             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5936               name;
5937             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5938               name
5939         | RStructList (n, _) ->
5940             pr "  struct guestfs_%s_ret ret;\n" name;
5941             pr "  ret.%s = *r;\n" n;
5942             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5943               name;
5944             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5945               name
5946         | RBufferOut n ->
5947             pr "  struct guestfs_%s_ret ret;\n" name;
5948             pr "  ret.%s.%s_val = r;\n" n n;
5949             pr "  ret.%s.%s_len = size;\n" n n;
5950             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5951               name;
5952             pr "  free (r);\n"
5953       );
5954
5955       (* Free the args. *)
5956       (match snd style with
5957        | [] ->
5958            pr "done: ;\n";
5959        | _ ->
5960            pr "done:\n";
5961            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5962              name
5963       );
5964
5965       pr "}\n\n";
5966   ) daemon_functions;
5967
5968   (* Dispatch function. *)
5969   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5970   pr "{\n";
5971   pr "  switch (proc_nr) {\n";
5972
5973   List.iter (
5974     fun (name, style, _, _, _, _, _) ->
5975       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5976       pr "      %s_stub (xdr_in);\n" name;
5977       pr "      break;\n"
5978   ) daemon_functions;
5979
5980   pr "    default:\n";
5981   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";
5982   pr "  }\n";
5983   pr "}\n";
5984   pr "\n";
5985
5986   (* LVM columns and tokenization functions. *)
5987   (* XXX This generates crap code.  We should rethink how we
5988    * do this parsing.
5989    *)
5990   List.iter (
5991     function
5992     | typ, cols ->
5993         pr "static const char *lvm_%s_cols = \"%s\";\n"
5994           typ (String.concat "," (List.map fst cols));
5995         pr "\n";
5996
5997         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5998         pr "{\n";
5999         pr "  char *tok, *p, *next;\n";
6000         pr "  int i, j;\n";
6001         pr "\n";
6002         (*
6003           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6004           pr "\n";
6005         *)
6006         pr "  if (!str) {\n";
6007         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6008         pr "    return -1;\n";
6009         pr "  }\n";
6010         pr "  if (!*str || c_isspace (*str)) {\n";
6011         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6012         pr "    return -1;\n";
6013         pr "  }\n";
6014         pr "  tok = str;\n";
6015         List.iter (
6016           fun (name, coltype) ->
6017             pr "  if (!tok) {\n";
6018             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6019             pr "    return -1;\n";
6020             pr "  }\n";
6021             pr "  p = strchrnul (tok, ',');\n";
6022             pr "  if (*p) next = p+1; else next = NULL;\n";
6023             pr "  *p = '\\0';\n";
6024             (match coltype with
6025              | FString ->
6026                  pr "  r->%s = strdup (tok);\n" name;
6027                  pr "  if (r->%s == NULL) {\n" name;
6028                  pr "    perror (\"strdup\");\n";
6029                  pr "    return -1;\n";
6030                  pr "  }\n"
6031              | FUUID ->
6032                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6033                  pr "    if (tok[j] == '\\0') {\n";
6034                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6035                  pr "      return -1;\n";
6036                  pr "    } else if (tok[j] != '-')\n";
6037                  pr "      r->%s[i++] = tok[j];\n" name;
6038                  pr "  }\n";
6039              | FBytes ->
6040                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6041                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6042                  pr "    return -1;\n";
6043                  pr "  }\n";
6044              | FInt64 ->
6045                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6046                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6047                  pr "    return -1;\n";
6048                  pr "  }\n";
6049              | FOptPercent ->
6050                  pr "  if (tok[0] == '\\0')\n";
6051                  pr "    r->%s = -1;\n" name;
6052                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6053                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6054                  pr "    return -1;\n";
6055                  pr "  }\n";
6056              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6057                  assert false (* can never be an LVM column *)
6058             );
6059             pr "  tok = next;\n";
6060         ) cols;
6061
6062         pr "  if (tok != NULL) {\n";
6063         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6064         pr "    return -1;\n";
6065         pr "  }\n";
6066         pr "  return 0;\n";
6067         pr "}\n";
6068         pr "\n";
6069
6070         pr "guestfs_int_lvm_%s_list *\n" typ;
6071         pr "parse_command_line_%ss (void)\n" typ;
6072         pr "{\n";
6073         pr "  char *out, *err;\n";
6074         pr "  char *p, *pend;\n";
6075         pr "  int r, i;\n";
6076         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6077         pr "  void *newp;\n";
6078         pr "\n";
6079         pr "  ret = malloc (sizeof *ret);\n";
6080         pr "  if (!ret) {\n";
6081         pr "    reply_with_perror (\"malloc\");\n";
6082         pr "    return NULL;\n";
6083         pr "  }\n";
6084         pr "\n";
6085         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6086         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6087         pr "\n";
6088         pr "  r = command (&out, &err,\n";
6089         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
6090         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6091         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6092         pr "  if (r == -1) {\n";
6093         pr "    reply_with_error (\"%%s\", err);\n";
6094         pr "    free (out);\n";
6095         pr "    free (err);\n";
6096         pr "    free (ret);\n";
6097         pr "    return NULL;\n";
6098         pr "  }\n";
6099         pr "\n";
6100         pr "  free (err);\n";
6101         pr "\n";
6102         pr "  /* Tokenize each line of the output. */\n";
6103         pr "  p = out;\n";
6104         pr "  i = 0;\n";
6105         pr "  while (p) {\n";
6106         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6107         pr "    if (pend) {\n";
6108         pr "      *pend = '\\0';\n";
6109         pr "      pend++;\n";
6110         pr "    }\n";
6111         pr "\n";
6112         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6113         pr "      p++;\n";
6114         pr "\n";
6115         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6116         pr "      p = pend;\n";
6117         pr "      continue;\n";
6118         pr "    }\n";
6119         pr "\n";
6120         pr "    /* Allocate some space to store this next entry. */\n";
6121         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6122         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6123         pr "    if (newp == NULL) {\n";
6124         pr "      reply_with_perror (\"realloc\");\n";
6125         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6126         pr "      free (ret);\n";
6127         pr "      free (out);\n";
6128         pr "      return NULL;\n";
6129         pr "    }\n";
6130         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6131         pr "\n";
6132         pr "    /* Tokenize the next entry. */\n";
6133         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6134         pr "    if (r == -1) {\n";
6135         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6136         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6137         pr "      free (ret);\n";
6138         pr "      free (out);\n";
6139         pr "      return NULL;\n";
6140         pr "    }\n";
6141         pr "\n";
6142         pr "    ++i;\n";
6143         pr "    p = pend;\n";
6144         pr "  }\n";
6145         pr "\n";
6146         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6147         pr "\n";
6148         pr "  free (out);\n";
6149         pr "  return ret;\n";
6150         pr "}\n"
6151
6152   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6153
6154 (* Generate a list of function names, for debugging in the daemon.. *)
6155 and generate_daemon_names () =
6156   generate_header CStyle GPLv2plus;
6157
6158   pr "#include <config.h>\n";
6159   pr "\n";
6160   pr "#include \"daemon.h\"\n";
6161   pr "\n";
6162
6163   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6164   pr "const char *function_names[] = {\n";
6165   List.iter (
6166     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6167   ) daemon_functions;
6168   pr "};\n";
6169
6170 (* Generate the optional groups for the daemon to implement
6171  * guestfs_available.
6172  *)
6173 and generate_daemon_optgroups_c () =
6174   generate_header CStyle GPLv2plus;
6175
6176   pr "#include <config.h>\n";
6177   pr "\n";
6178   pr "#include \"daemon.h\"\n";
6179   pr "#include \"optgroups.h\"\n";
6180   pr "\n";
6181
6182   pr "struct optgroup optgroups[] = {\n";
6183   List.iter (
6184     fun (group, _) ->
6185       pr "  { \"%s\", optgroup_%s_available },\n" group group
6186   ) optgroups;
6187   pr "  { NULL, NULL }\n";
6188   pr "};\n"
6189
6190 and generate_daemon_optgroups_h () =
6191   generate_header CStyle GPLv2plus;
6192
6193   List.iter (
6194     fun (group, _) ->
6195       pr "extern int optgroup_%s_available (void);\n" group
6196   ) optgroups
6197
6198 (* Generate the tests. *)
6199 and generate_tests () =
6200   generate_header CStyle GPLv2plus;
6201
6202   pr "\
6203 #include <stdio.h>
6204 #include <stdlib.h>
6205 #include <string.h>
6206 #include <unistd.h>
6207 #include <sys/types.h>
6208 #include <fcntl.h>
6209
6210 #include \"guestfs.h\"
6211 #include \"guestfs-internal.h\"
6212
6213 static guestfs_h *g;
6214 static int suppress_error = 0;
6215
6216 static void print_error (guestfs_h *g, void *data, const char *msg)
6217 {
6218   if (!suppress_error)
6219     fprintf (stderr, \"%%s\\n\", msg);
6220 }
6221
6222 /* FIXME: nearly identical code appears in fish.c */
6223 static void print_strings (char *const *argv)
6224 {
6225   int argc;
6226
6227   for (argc = 0; argv[argc] != NULL; ++argc)
6228     printf (\"\\t%%s\\n\", argv[argc]);
6229 }
6230
6231 /*
6232 static void print_table (char const *const *argv)
6233 {
6234   int i;
6235
6236   for (i = 0; argv[i] != NULL; i += 2)
6237     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6238 }
6239 */
6240
6241 ";
6242
6243   (* Generate a list of commands which are not tested anywhere. *)
6244   pr "static void no_test_warnings (void)\n";
6245   pr "{\n";
6246
6247   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6248   List.iter (
6249     fun (_, _, _, _, tests, _, _) ->
6250       let tests = filter_map (
6251         function
6252         | (_, (Always|If _|Unless _), test) -> Some test
6253         | (_, Disabled, _) -> None
6254       ) tests in
6255       let seq = List.concat (List.map seq_of_test tests) in
6256       let cmds_tested = List.map List.hd seq in
6257       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6258   ) all_functions;
6259
6260   List.iter (
6261     fun (name, _, _, _, _, _, _) ->
6262       if not (Hashtbl.mem hash name) then
6263         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6264   ) all_functions;
6265
6266   pr "}\n";
6267   pr "\n";
6268
6269   (* Generate the actual tests.  Note that we generate the tests
6270    * in reverse order, deliberately, so that (in general) the
6271    * newest tests run first.  This makes it quicker and easier to
6272    * debug them.
6273    *)
6274   let test_names =
6275     List.map (
6276       fun (name, _, _, flags, tests, _, _) ->
6277         mapi (generate_one_test name flags) tests
6278     ) (List.rev all_functions) in
6279   let test_names = List.concat test_names in
6280   let nr_tests = List.length test_names in
6281
6282   pr "\
6283 int main (int argc, char *argv[])
6284 {
6285   char c = 0;
6286   unsigned long int n_failed = 0;
6287   const char *filename;
6288   int fd;
6289   int nr_tests, test_num = 0;
6290
6291   setbuf (stdout, NULL);
6292
6293   no_test_warnings ();
6294
6295   g = guestfs_create ();
6296   if (g == NULL) {
6297     printf (\"guestfs_create FAILED\\n\");
6298     exit (EXIT_FAILURE);
6299   }
6300
6301   guestfs_set_error_handler (g, print_error, NULL);
6302
6303   guestfs_set_path (g, \"../appliance\");
6304
6305   filename = \"test1.img\";
6306   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6307   if (fd == -1) {
6308     perror (filename);
6309     exit (EXIT_FAILURE);
6310   }
6311   if (lseek (fd, %d, SEEK_SET) == -1) {
6312     perror (\"lseek\");
6313     close (fd);
6314     unlink (filename);
6315     exit (EXIT_FAILURE);
6316   }
6317   if (write (fd, &c, 1) == -1) {
6318     perror (\"write\");
6319     close (fd);
6320     unlink (filename);
6321     exit (EXIT_FAILURE);
6322   }
6323   if (close (fd) == -1) {
6324     perror (filename);
6325     unlink (filename);
6326     exit (EXIT_FAILURE);
6327   }
6328   if (guestfs_add_drive (g, filename) == -1) {
6329     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6330     exit (EXIT_FAILURE);
6331   }
6332
6333   filename = \"test2.img\";
6334   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6335   if (fd == -1) {
6336     perror (filename);
6337     exit (EXIT_FAILURE);
6338   }
6339   if (lseek (fd, %d, SEEK_SET) == -1) {
6340     perror (\"lseek\");
6341     close (fd);
6342     unlink (filename);
6343     exit (EXIT_FAILURE);
6344   }
6345   if (write (fd, &c, 1) == -1) {
6346     perror (\"write\");
6347     close (fd);
6348     unlink (filename);
6349     exit (EXIT_FAILURE);
6350   }
6351   if (close (fd) == -1) {
6352     perror (filename);
6353     unlink (filename);
6354     exit (EXIT_FAILURE);
6355   }
6356   if (guestfs_add_drive (g, filename) == -1) {
6357     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6358     exit (EXIT_FAILURE);
6359   }
6360
6361   filename = \"test3.img\";
6362   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6363   if (fd == -1) {
6364     perror (filename);
6365     exit (EXIT_FAILURE);
6366   }
6367   if (lseek (fd, %d, SEEK_SET) == -1) {
6368     perror (\"lseek\");
6369     close (fd);
6370     unlink (filename);
6371     exit (EXIT_FAILURE);
6372   }
6373   if (write (fd, &c, 1) == -1) {
6374     perror (\"write\");
6375     close (fd);
6376     unlink (filename);
6377     exit (EXIT_FAILURE);
6378   }
6379   if (close (fd) == -1) {
6380     perror (filename);
6381     unlink (filename);
6382     exit (EXIT_FAILURE);
6383   }
6384   if (guestfs_add_drive (g, filename) == -1) {
6385     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6386     exit (EXIT_FAILURE);
6387   }
6388
6389   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6390     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6391     exit (EXIT_FAILURE);
6392   }
6393
6394   if (guestfs_launch (g) == -1) {
6395     printf (\"guestfs_launch FAILED\\n\");
6396     exit (EXIT_FAILURE);
6397   }
6398
6399   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6400   alarm (600);
6401
6402   /* Cancel previous alarm. */
6403   alarm (0);
6404
6405   nr_tests = %d;
6406
6407 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6408
6409   iteri (
6410     fun i test_name ->
6411       pr "  test_num++;\n";
6412       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6413       pr "  if (%s () == -1) {\n" test_name;
6414       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6415       pr "    n_failed++;\n";
6416       pr "  }\n";
6417   ) test_names;
6418   pr "\n";
6419
6420   pr "  guestfs_close (g);\n";
6421   pr "  unlink (\"test1.img\");\n";
6422   pr "  unlink (\"test2.img\");\n";
6423   pr "  unlink (\"test3.img\");\n";
6424   pr "\n";
6425
6426   pr "  if (n_failed > 0) {\n";
6427   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6428   pr "    exit (EXIT_FAILURE);\n";
6429   pr "  }\n";
6430   pr "\n";
6431
6432   pr "  exit (EXIT_SUCCESS);\n";
6433   pr "}\n"
6434
6435 and generate_one_test name flags i (init, prereq, test) =
6436   let test_name = sprintf "test_%s_%d" name i in
6437
6438   pr "\
6439 static int %s_skip (void)
6440 {
6441   const char *str;
6442
6443   str = getenv (\"TEST_ONLY\");
6444   if (str)
6445     return strstr (str, \"%s\") == NULL;
6446   str = getenv (\"SKIP_%s\");
6447   if (str && STREQ (str, \"1\")) return 1;
6448   str = getenv (\"SKIP_TEST_%s\");
6449   if (str && STREQ (str, \"1\")) return 1;
6450   return 0;
6451 }
6452
6453 " test_name name (String.uppercase test_name) (String.uppercase name);
6454
6455   (match prereq with
6456    | Disabled | Always -> ()
6457    | If code | Unless code ->
6458        pr "static int %s_prereq (void)\n" test_name;
6459        pr "{\n";
6460        pr "  %s\n" code;
6461        pr "}\n";
6462        pr "\n";
6463   );
6464
6465   pr "\
6466 static int %s (void)
6467 {
6468   if (%s_skip ()) {
6469     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6470     return 0;
6471   }
6472
6473 " test_name test_name test_name;
6474
6475   (* Optional functions should only be tested if the relevant
6476    * support is available in the daemon.
6477    *)
6478   List.iter (
6479     function
6480     | Optional group ->
6481         pr "  {\n";
6482         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6483         pr "    int r;\n";
6484         pr "    suppress_error = 1;\n";
6485         pr "    r = guestfs_available (g, (char **) groups);\n";
6486         pr "    suppress_error = 0;\n";
6487         pr "    if (r == -1) {\n";
6488         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6489         pr "      return 0;\n";
6490         pr "    }\n";
6491         pr "  }\n";
6492     | _ -> ()
6493   ) flags;
6494
6495   (match prereq with
6496    | Disabled ->
6497        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6498    | If _ ->
6499        pr "  if (! %s_prereq ()) {\n" test_name;
6500        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6501        pr "    return 0;\n";
6502        pr "  }\n";
6503        pr "\n";
6504        generate_one_test_body name i test_name init test;
6505    | Unless _ ->
6506        pr "  if (%s_prereq ()) {\n" test_name;
6507        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6508        pr "    return 0;\n";
6509        pr "  }\n";
6510        pr "\n";
6511        generate_one_test_body name i test_name init test;
6512    | Always ->
6513        generate_one_test_body name i test_name init test
6514   );
6515
6516   pr "  return 0;\n";
6517   pr "}\n";
6518   pr "\n";
6519   test_name
6520
6521 and generate_one_test_body name i test_name init test =
6522   (match init with
6523    | InitNone (* XXX at some point, InitNone and InitEmpty became
6524                * folded together as the same thing.  Really we should
6525                * make InitNone do nothing at all, but the tests may
6526                * need to be checked to make sure this is OK.
6527                *)
6528    | InitEmpty ->
6529        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6530        List.iter (generate_test_command_call test_name)
6531          [["blockdev_setrw"; "/dev/sda"];
6532           ["umount_all"];
6533           ["lvm_remove_all"]]
6534    | InitPartition ->
6535        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6536        List.iter (generate_test_command_call test_name)
6537          [["blockdev_setrw"; "/dev/sda"];
6538           ["umount_all"];
6539           ["lvm_remove_all"];
6540           ["part_disk"; "/dev/sda"; "mbr"]]
6541    | InitBasicFS ->
6542        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6543        List.iter (generate_test_command_call test_name)
6544          [["blockdev_setrw"; "/dev/sda"];
6545           ["umount_all"];
6546           ["lvm_remove_all"];
6547           ["part_disk"; "/dev/sda"; "mbr"];
6548           ["mkfs"; "ext2"; "/dev/sda1"];
6549           ["mount_options"; ""; "/dev/sda1"; "/"]]
6550    | InitBasicFSonLVM ->
6551        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6552          test_name;
6553        List.iter (generate_test_command_call test_name)
6554          [["blockdev_setrw"; "/dev/sda"];
6555           ["umount_all"];
6556           ["lvm_remove_all"];
6557           ["part_disk"; "/dev/sda"; "mbr"];
6558           ["pvcreate"; "/dev/sda1"];
6559           ["vgcreate"; "VG"; "/dev/sda1"];
6560           ["lvcreate"; "LV"; "VG"; "8"];
6561           ["mkfs"; "ext2"; "/dev/VG/LV"];
6562           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6563    | InitISOFS ->
6564        pr "  /* InitISOFS for %s */\n" test_name;
6565        List.iter (generate_test_command_call test_name)
6566          [["blockdev_setrw"; "/dev/sda"];
6567           ["umount_all"];
6568           ["lvm_remove_all"];
6569           ["mount_ro"; "/dev/sdd"; "/"]]
6570   );
6571
6572   let get_seq_last = function
6573     | [] ->
6574         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6575           test_name
6576     | seq ->
6577         let seq = List.rev seq in
6578         List.rev (List.tl seq), List.hd seq
6579   in
6580
6581   match test with
6582   | TestRun seq ->
6583       pr "  /* TestRun for %s (%d) */\n" name i;
6584       List.iter (generate_test_command_call test_name) seq
6585   | TestOutput (seq, expected) ->
6586       pr "  /* TestOutput for %s (%d) */\n" name i;
6587       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6588       let seq, last = get_seq_last seq in
6589       let test () =
6590         pr "    if (STRNEQ (r, expected)) {\n";
6591         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6592         pr "      return -1;\n";
6593         pr "    }\n"
6594       in
6595       List.iter (generate_test_command_call test_name) seq;
6596       generate_test_command_call ~test test_name last
6597   | TestOutputList (seq, expected) ->
6598       pr "  /* TestOutputList for %s (%d) */\n" name i;
6599       let seq, last = get_seq_last seq in
6600       let test () =
6601         iteri (
6602           fun i str ->
6603             pr "    if (!r[%d]) {\n" i;
6604             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6605             pr "      print_strings (r);\n";
6606             pr "      return -1;\n";
6607             pr "    }\n";
6608             pr "    {\n";
6609             pr "      const char *expected = \"%s\";\n" (c_quote str);
6610             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6611             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6612             pr "        return -1;\n";
6613             pr "      }\n";
6614             pr "    }\n"
6615         ) expected;
6616         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6617         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6618           test_name;
6619         pr "      print_strings (r);\n";
6620         pr "      return -1;\n";
6621         pr "    }\n"
6622       in
6623       List.iter (generate_test_command_call test_name) seq;
6624       generate_test_command_call ~test test_name last
6625   | TestOutputListOfDevices (seq, expected) ->
6626       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6627       let seq, last = get_seq_last seq in
6628       let test () =
6629         iteri (
6630           fun i str ->
6631             pr "    if (!r[%d]) {\n" i;
6632             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6633             pr "      print_strings (r);\n";
6634             pr "      return -1;\n";
6635             pr "    }\n";
6636             pr "    {\n";
6637             pr "      const char *expected = \"%s\";\n" (c_quote str);
6638             pr "      r[%d][5] = 's';\n" i;
6639             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6640             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6641             pr "        return -1;\n";
6642             pr "      }\n";
6643             pr "    }\n"
6644         ) expected;
6645         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6646         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6647           test_name;
6648         pr "      print_strings (r);\n";
6649         pr "      return -1;\n";
6650         pr "    }\n"
6651       in
6652       List.iter (generate_test_command_call test_name) seq;
6653       generate_test_command_call ~test test_name last
6654   | TestOutputInt (seq, expected) ->
6655       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6656       let seq, last = get_seq_last seq in
6657       let test () =
6658         pr "    if (r != %d) {\n" expected;
6659         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6660           test_name expected;
6661         pr "               (int) r);\n";
6662         pr "      return -1;\n";
6663         pr "    }\n"
6664       in
6665       List.iter (generate_test_command_call test_name) seq;
6666       generate_test_command_call ~test test_name last
6667   | TestOutputIntOp (seq, op, expected) ->
6668       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6669       let seq, last = get_seq_last seq in
6670       let test () =
6671         pr "    if (! (r %s %d)) {\n" op expected;
6672         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6673           test_name op expected;
6674         pr "               (int) r);\n";
6675         pr "      return -1;\n";
6676         pr "    }\n"
6677       in
6678       List.iter (generate_test_command_call test_name) seq;
6679       generate_test_command_call ~test test_name last
6680   | TestOutputTrue seq ->
6681       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6682       let seq, last = get_seq_last seq in
6683       let test () =
6684         pr "    if (!r) {\n";
6685         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6686           test_name;
6687         pr "      return -1;\n";
6688         pr "    }\n"
6689       in
6690       List.iter (generate_test_command_call test_name) seq;
6691       generate_test_command_call ~test test_name last
6692   | TestOutputFalse seq ->
6693       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6694       let seq, last = get_seq_last seq in
6695       let test () =
6696         pr "    if (r) {\n";
6697         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6698           test_name;
6699         pr "      return -1;\n";
6700         pr "    }\n"
6701       in
6702       List.iter (generate_test_command_call test_name) seq;
6703       generate_test_command_call ~test test_name last
6704   | TestOutputLength (seq, expected) ->
6705       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6706       let seq, last = get_seq_last seq in
6707       let test () =
6708         pr "    int j;\n";
6709         pr "    for (j = 0; j < %d; ++j)\n" expected;
6710         pr "      if (r[j] == NULL) {\n";
6711         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6712           test_name;
6713         pr "        print_strings (r);\n";
6714         pr "        return -1;\n";
6715         pr "      }\n";
6716         pr "    if (r[j] != NULL) {\n";
6717         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6718           test_name;
6719         pr "      print_strings (r);\n";
6720         pr "      return -1;\n";
6721         pr "    }\n"
6722       in
6723       List.iter (generate_test_command_call test_name) seq;
6724       generate_test_command_call ~test test_name last
6725   | TestOutputBuffer (seq, expected) ->
6726       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6727       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6728       let seq, last = get_seq_last seq in
6729       let len = String.length expected in
6730       let test () =
6731         pr "    if (size != %d) {\n" len;
6732         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6733         pr "      return -1;\n";
6734         pr "    }\n";
6735         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6736         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6737         pr "      return -1;\n";
6738         pr "    }\n"
6739       in
6740       List.iter (generate_test_command_call test_name) seq;
6741       generate_test_command_call ~test test_name last
6742   | TestOutputStruct (seq, checks) ->
6743       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6744       let seq, last = get_seq_last seq in
6745       let test () =
6746         List.iter (
6747           function
6748           | CompareWithInt (field, expected) ->
6749               pr "    if (r->%s != %d) {\n" field expected;
6750               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6751                 test_name field expected;
6752               pr "               (int) r->%s);\n" field;
6753               pr "      return -1;\n";
6754               pr "    }\n"
6755           | CompareWithIntOp (field, op, expected) ->
6756               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6757               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6758                 test_name field op expected;
6759               pr "               (int) r->%s);\n" field;
6760               pr "      return -1;\n";
6761               pr "    }\n"
6762           | CompareWithString (field, expected) ->
6763               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6764               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6765                 test_name field expected;
6766               pr "               r->%s);\n" field;
6767               pr "      return -1;\n";
6768               pr "    }\n"
6769           | CompareFieldsIntEq (field1, field2) ->
6770               pr "    if (r->%s != r->%s) {\n" field1 field2;
6771               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6772                 test_name field1 field2;
6773               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6774               pr "      return -1;\n";
6775               pr "    }\n"
6776           | CompareFieldsStrEq (field1, field2) ->
6777               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6778               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6779                 test_name field1 field2;
6780               pr "               r->%s, r->%s);\n" field1 field2;
6781               pr "      return -1;\n";
6782               pr "    }\n"
6783         ) checks
6784       in
6785       List.iter (generate_test_command_call test_name) seq;
6786       generate_test_command_call ~test test_name last
6787   | TestLastFail seq ->
6788       pr "  /* TestLastFail for %s (%d) */\n" name i;
6789       let seq, last = get_seq_last seq in
6790       List.iter (generate_test_command_call test_name) seq;
6791       generate_test_command_call test_name ~expect_error:true last
6792
6793 (* Generate the code to run a command, leaving the result in 'r'.
6794  * If you expect to get an error then you should set expect_error:true.
6795  *)
6796 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6797   match cmd with
6798   | [] -> assert false
6799   | name :: args ->
6800       (* Look up the command to find out what args/ret it has. *)
6801       let style =
6802         try
6803           let _, style, _, _, _, _, _ =
6804             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6805           style
6806         with Not_found ->
6807           failwithf "%s: in test, command %s was not found" test_name name in
6808
6809       if List.length (snd style) <> List.length args then
6810         failwithf "%s: in test, wrong number of args given to %s"
6811           test_name name;
6812
6813       pr "  {\n";
6814
6815       List.iter (
6816         function
6817         | OptString n, "NULL" -> ()
6818         | Pathname n, arg
6819         | Device n, arg
6820         | Dev_or_Path n, arg
6821         | String n, arg
6822         | OptString n, arg ->
6823             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6824         | Int _, _
6825         | Int64 _, _
6826         | Bool _, _
6827         | FileIn _, _ | FileOut _, _ -> ()
6828         | StringList n, "" | DeviceList n, "" ->
6829             pr "    const char *const %s[1] = { NULL };\n" n
6830         | StringList n, arg | DeviceList n, arg ->
6831             let strs = string_split " " arg in
6832             iteri (
6833               fun i str ->
6834                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6835             ) strs;
6836             pr "    const char *const %s[] = {\n" n;
6837             iteri (
6838               fun i _ -> pr "      %s_%d,\n" n i
6839             ) strs;
6840             pr "      NULL\n";
6841             pr "    };\n";
6842       ) (List.combine (snd style) args);
6843
6844       let error_code =
6845         match fst style with
6846         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6847         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6848         | RConstString _ | RConstOptString _ ->
6849             pr "    const char *r;\n"; "NULL"
6850         | RString _ -> pr "    char *r;\n"; "NULL"
6851         | RStringList _ | RHashtable _ ->
6852             pr "    char **r;\n";
6853             pr "    int i;\n";
6854             "NULL"
6855         | RStruct (_, typ) ->
6856             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6857         | RStructList (_, typ) ->
6858             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6859         | RBufferOut _ ->
6860             pr "    char *r;\n";
6861             pr "    size_t size;\n";
6862             "NULL" in
6863
6864       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6865       pr "    r = guestfs_%s (g" name;
6866
6867       (* Generate the parameters. *)
6868       List.iter (
6869         function
6870         | OptString _, "NULL" -> pr ", NULL"
6871         | Pathname n, _
6872         | Device n, _ | Dev_or_Path n, _
6873         | String n, _
6874         | OptString n, _ ->
6875             pr ", %s" n
6876         | FileIn _, arg | FileOut _, arg ->
6877             pr ", \"%s\"" (c_quote arg)
6878         | StringList n, _ | DeviceList n, _ ->
6879             pr ", (char **) %s" n
6880         | Int _, arg ->
6881             let i =
6882               try int_of_string arg
6883               with Failure "int_of_string" ->
6884                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6885             pr ", %d" i
6886         | Int64 _, arg ->
6887             let i =
6888               try Int64.of_string arg
6889               with Failure "int_of_string" ->
6890                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6891             pr ", %Ld" i
6892         | Bool _, arg ->
6893             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6894       ) (List.combine (snd style) args);
6895
6896       (match fst style with
6897        | RBufferOut _ -> pr ", &size"
6898        | _ -> ()
6899       );
6900
6901       pr ");\n";
6902
6903       if not expect_error then
6904         pr "    if (r == %s)\n" error_code
6905       else
6906         pr "    if (r != %s)\n" error_code;
6907       pr "      return -1;\n";
6908
6909       (* Insert the test code. *)
6910       (match test with
6911        | None -> ()
6912        | Some f -> f ()
6913       );
6914
6915       (match fst style with
6916        | RErr | RInt _ | RInt64 _ | RBool _
6917        | RConstString _ | RConstOptString _ -> ()
6918        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6919        | RStringList _ | RHashtable _ ->
6920            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6921            pr "      free (r[i]);\n";
6922            pr "    free (r);\n"
6923        | RStruct (_, typ) ->
6924            pr "    guestfs_free_%s (r);\n" typ
6925        | RStructList (_, typ) ->
6926            pr "    guestfs_free_%s_list (r);\n" typ
6927       );
6928
6929       pr "  }\n"
6930
6931 and c_quote str =
6932   let str = replace_str str "\r" "\\r" in
6933   let str = replace_str str "\n" "\\n" in
6934   let str = replace_str str "\t" "\\t" in
6935   let str = replace_str str "\000" "\\0" in
6936   str
6937
6938 (* Generate a lot of different functions for guestfish. *)
6939 and generate_fish_cmds () =
6940   generate_header CStyle GPLv2plus;
6941
6942   let all_functions =
6943     List.filter (
6944       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6945     ) all_functions in
6946   let all_functions_sorted =
6947     List.filter (
6948       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6949     ) all_functions_sorted in
6950
6951   pr "#include <config.h>\n";
6952   pr "\n";
6953   pr "#include <stdio.h>\n";
6954   pr "#include <stdlib.h>\n";
6955   pr "#include <string.h>\n";
6956   pr "#include <inttypes.h>\n";
6957   pr "\n";
6958   pr "#include <guestfs.h>\n";
6959   pr "#include \"c-ctype.h\"\n";
6960   pr "#include \"full-write.h\"\n";
6961   pr "#include \"xstrtol.h\"\n";
6962   pr "#include \"fish.h\"\n";
6963   pr "\n";
6964
6965   (* list_commands function, which implements guestfish -h *)
6966   pr "void list_commands (void)\n";
6967   pr "{\n";
6968   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6969   pr "  list_builtin_commands ();\n";
6970   List.iter (
6971     fun (name, _, _, flags, _, shortdesc, _) ->
6972       let name = replace_char name '_' '-' in
6973       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6974         name shortdesc
6975   ) all_functions_sorted;
6976   pr "  printf (\"    %%s\\n\",";
6977   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6978   pr "}\n";
6979   pr "\n";
6980
6981   (* display_command function, which implements guestfish -h cmd *)
6982   pr "void display_command (const char *cmd)\n";
6983   pr "{\n";
6984   List.iter (
6985     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6986       let name2 = replace_char name '_' '-' in
6987       let alias =
6988         try find_map (function FishAlias n -> Some n | _ -> None) flags
6989         with Not_found -> name in
6990       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6991       let synopsis =
6992         match snd style with
6993         | [] -> name2
6994         | args ->
6995             sprintf "%s %s"
6996               name2 (String.concat " " (List.map name_of_argt args)) in
6997
6998       let warnings =
6999         if List.mem ProtocolLimitWarning flags then
7000           ("\n\n" ^ protocol_limit_warning)
7001         else "" in
7002
7003       (* For DangerWillRobinson commands, we should probably have
7004        * guestfish prompt before allowing you to use them (especially
7005        * in interactive mode). XXX
7006        *)
7007       let warnings =
7008         warnings ^
7009           if List.mem DangerWillRobinson flags then
7010             ("\n\n" ^ danger_will_robinson)
7011           else "" in
7012
7013       let warnings =
7014         warnings ^
7015           match deprecation_notice flags with
7016           | None -> ""
7017           | Some txt -> "\n\n" ^ txt in
7018
7019       let describe_alias =
7020         if name <> alias then
7021           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7022         else "" in
7023
7024       pr "  if (";
7025       pr "STRCASEEQ (cmd, \"%s\")" name;
7026       if name <> name2 then
7027         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7028       if name <> alias then
7029         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7030       pr ")\n";
7031       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7032         name2 shortdesc
7033         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7034          "=head1 DESCRIPTION\n\n" ^
7035          longdesc ^ warnings ^ describe_alias);
7036       pr "  else\n"
7037   ) all_functions;
7038   pr "    display_builtin_command (cmd);\n";
7039   pr "}\n";
7040   pr "\n";
7041
7042   let emit_print_list_function typ =
7043     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7044       typ typ typ;
7045     pr "{\n";
7046     pr "  unsigned int i;\n";
7047     pr "\n";
7048     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7049     pr "    printf (\"[%%d] = {\\n\", i);\n";
7050     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7051     pr "    printf (\"}\\n\");\n";
7052     pr "  }\n";
7053     pr "}\n";
7054     pr "\n";
7055   in
7056
7057   (* print_* functions *)
7058   List.iter (
7059     fun (typ, cols) ->
7060       let needs_i =
7061         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7062
7063       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7064       pr "{\n";
7065       if needs_i then (
7066         pr "  unsigned int i;\n";
7067         pr "\n"
7068       );
7069       List.iter (
7070         function
7071         | name, FString ->
7072             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7073         | name, FUUID ->
7074             pr "  printf (\"%%s%s: \", indent);\n" name;
7075             pr "  for (i = 0; i < 32; ++i)\n";
7076             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7077             pr "  printf (\"\\n\");\n"
7078         | name, FBuffer ->
7079             pr "  printf (\"%%s%s: \", indent);\n" name;
7080             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7081             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7082             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7083             pr "    else\n";
7084             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7085             pr "  printf (\"\\n\");\n"
7086         | name, (FUInt64|FBytes) ->
7087             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7088               name typ name
7089         | name, FInt64 ->
7090             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7091               name typ name
7092         | name, FUInt32 ->
7093             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7094               name typ name
7095         | name, FInt32 ->
7096             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7097               name typ name
7098         | name, FChar ->
7099             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7100               name typ name
7101         | name, FOptPercent ->
7102             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7103               typ name name typ name;
7104             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7105       ) cols;
7106       pr "}\n";
7107       pr "\n";
7108   ) structs;
7109
7110   (* Emit a print_TYPE_list function definition only if that function is used. *)
7111   List.iter (
7112     function
7113     | typ, (RStructListOnly | RStructAndList) ->
7114         (* generate the function for typ *)
7115         emit_print_list_function typ
7116     | typ, _ -> () (* empty *)
7117   ) (rstructs_used_by all_functions);
7118
7119   (* Emit a print_TYPE function definition only if that function is used. *)
7120   List.iter (
7121     function
7122     | typ, (RStructOnly | RStructAndList) ->
7123         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7124         pr "{\n";
7125         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7126         pr "}\n";
7127         pr "\n";
7128     | typ, _ -> () (* empty *)
7129   ) (rstructs_used_by all_functions);
7130
7131   (* run_<action> actions *)
7132   List.iter (
7133     fun (name, style, _, flags, _, _, _) ->
7134       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7135       pr "{\n";
7136       (match fst style with
7137        | RErr
7138        | RInt _
7139        | RBool _ -> pr "  int r;\n"
7140        | RInt64 _ -> pr "  int64_t r;\n"
7141        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7142        | RString _ -> pr "  char *r;\n"
7143        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7144        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7145        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7146        | RBufferOut _ ->
7147            pr "  char *r;\n";
7148            pr "  size_t size;\n";
7149       );
7150       List.iter (
7151         function
7152         | Device n
7153         | String n
7154         | OptString n
7155         | FileIn n
7156         | FileOut n -> pr "  const char *%s;\n" n
7157         | Pathname n
7158         | Dev_or_Path n -> pr "  char *%s;\n" n
7159         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7160         | Bool n -> pr "  int %s;\n" n
7161         | Int n -> pr "  int %s;\n" n
7162         | Int64 n -> pr "  int64_t %s;\n" n
7163       ) (snd style);
7164
7165       (* Check and convert parameters. *)
7166       let argc_expected = List.length (snd style) in
7167       pr "  if (argc != %d) {\n" argc_expected;
7168       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7169         argc_expected;
7170       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7171       pr "    return -1;\n";
7172       pr "  }\n";
7173
7174       let parse_integer fn fntyp rtyp range name i =
7175         pr "  {\n";
7176         pr "    strtol_error xerr;\n";
7177         pr "    %s r;\n" fntyp;
7178         pr "\n";
7179         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7180         pr "    if (xerr != LONGINT_OK) {\n";
7181         pr "      fprintf (stderr,\n";
7182         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7183         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7184         pr "      return -1;\n";
7185         pr "    }\n";
7186         (match range with
7187          | None -> ()
7188          | Some (min, max, comment) ->
7189              pr "    /* %s */\n" comment;
7190              pr "    if (r < %s || r > %s) {\n" min max;
7191              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7192                name;
7193              pr "      return -1;\n";
7194              pr "    }\n";
7195              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7196         );
7197         pr "    %s = r;\n" name;
7198         pr "  }\n";
7199       in
7200
7201       iteri (
7202         fun i ->
7203           function
7204           | Device name
7205           | String name ->
7206               pr "  %s = argv[%d];\n" name i
7207           | Pathname name
7208           | Dev_or_Path name ->
7209               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7210               pr "  if (%s == NULL) return -1;\n" name
7211           | OptString name ->
7212               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7213                 name i i
7214           | FileIn name ->
7215               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7216                 name i i
7217           | FileOut name ->
7218               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7219                 name i i
7220           | StringList name | DeviceList name ->
7221               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7222               pr "  if (%s == NULL) return -1;\n" name;
7223           | Bool name ->
7224               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7225           | Int name ->
7226               let range =
7227                 let min = "(-(2LL<<30))"
7228                 and max = "((2LL<<30)-1)"
7229                 and comment =
7230                   "The Int type in the generator is a signed 31 bit int." in
7231                 Some (min, max, comment) in
7232               parse_integer "xstrtoll" "long long" "int" range name i
7233           | Int64 name ->
7234               parse_integer "xstrtoll" "long long" "int64_t" None name i
7235       ) (snd style);
7236
7237       (* Call C API function. *)
7238       let fn =
7239         try find_map (function FishAction n -> Some n | _ -> None) flags
7240         with Not_found -> sprintf "guestfs_%s" name in
7241       pr "  r = %s " fn;
7242       generate_c_call_args ~handle:"g" style;
7243       pr ";\n";
7244
7245       List.iter (
7246         function
7247         | Device name | String name
7248         | OptString name | FileIn name | FileOut name | Bool name
7249         | Int name | Int64 name -> ()
7250         | Pathname name | Dev_or_Path name ->
7251             pr "  free (%s);\n" name
7252         | StringList name | DeviceList name ->
7253             pr "  free_strings (%s);\n" name
7254       ) (snd style);
7255
7256       (* Check return value for errors and display command results. *)
7257       (match fst style with
7258        | RErr -> pr "  return r;\n"
7259        | RInt _ ->
7260            pr "  if (r == -1) return -1;\n";
7261            pr "  printf (\"%%d\\n\", r);\n";
7262            pr "  return 0;\n"
7263        | RInt64 _ ->
7264            pr "  if (r == -1) return -1;\n";
7265            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7266            pr "  return 0;\n"
7267        | RBool _ ->
7268            pr "  if (r == -1) return -1;\n";
7269            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7270            pr "  return 0;\n"
7271        | RConstString _ ->
7272            pr "  if (r == NULL) return -1;\n";
7273            pr "  printf (\"%%s\\n\", r);\n";
7274            pr "  return 0;\n"
7275        | RConstOptString _ ->
7276            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7277            pr "  return 0;\n"
7278        | RString _ ->
7279            pr "  if (r == NULL) return -1;\n";
7280            pr "  printf (\"%%s\\n\", r);\n";
7281            pr "  free (r);\n";
7282            pr "  return 0;\n"
7283        | RStringList _ ->
7284            pr "  if (r == NULL) return -1;\n";
7285            pr "  print_strings (r);\n";
7286            pr "  free_strings (r);\n";
7287            pr "  return 0;\n"
7288        | RStruct (_, typ) ->
7289            pr "  if (r == NULL) return -1;\n";
7290            pr "  print_%s (r);\n" typ;
7291            pr "  guestfs_free_%s (r);\n" typ;
7292            pr "  return 0;\n"
7293        | RStructList (_, typ) ->
7294            pr "  if (r == NULL) return -1;\n";
7295            pr "  print_%s_list (r);\n" typ;
7296            pr "  guestfs_free_%s_list (r);\n" typ;
7297            pr "  return 0;\n"
7298        | RHashtable _ ->
7299            pr "  if (r == NULL) return -1;\n";
7300            pr "  print_table (r);\n";
7301            pr "  free_strings (r);\n";
7302            pr "  return 0;\n"
7303        | RBufferOut _ ->
7304            pr "  if (r == NULL) return -1;\n";
7305            pr "  if (full_write (1, r, size) != size) {\n";
7306            pr "    perror (\"write\");\n";
7307            pr "    free (r);\n";
7308            pr "    return -1;\n";
7309            pr "  }\n";
7310            pr "  free (r);\n";
7311            pr "  return 0;\n"
7312       );
7313       pr "}\n";
7314       pr "\n"
7315   ) all_functions;
7316
7317   (* run_action function *)
7318   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7319   pr "{\n";
7320   List.iter (
7321     fun (name, _, _, flags, _, _, _) ->
7322       let name2 = replace_char name '_' '-' in
7323       let alias =
7324         try find_map (function FishAlias n -> Some n | _ -> None) flags
7325         with Not_found -> name in
7326       pr "  if (";
7327       pr "STRCASEEQ (cmd, \"%s\")" name;
7328       if name <> name2 then
7329         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7330       if name <> alias then
7331         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7332       pr ")\n";
7333       pr "    return run_%s (cmd, argc, argv);\n" name;
7334       pr "  else\n";
7335   ) all_functions;
7336   pr "    {\n";
7337   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7338   pr "      return -1;\n";
7339   pr "    }\n";
7340   pr "  return 0;\n";
7341   pr "}\n";
7342   pr "\n"
7343
7344 (* Readline completion for guestfish. *)
7345 and generate_fish_completion () =
7346   generate_header CStyle GPLv2plus;
7347
7348   let all_functions =
7349     List.filter (
7350       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7351     ) all_functions in
7352
7353   pr "\
7354 #include <config.h>
7355
7356 #include <stdio.h>
7357 #include <stdlib.h>
7358 #include <string.h>
7359
7360 #ifdef HAVE_LIBREADLINE
7361 #include <readline/readline.h>
7362 #endif
7363
7364 #include \"fish.h\"
7365
7366 #ifdef HAVE_LIBREADLINE
7367
7368 static const char *const commands[] = {
7369   BUILTIN_COMMANDS_FOR_COMPLETION,
7370 ";
7371
7372   (* Get the commands, including the aliases.  They don't need to be
7373    * sorted - the generator() function just does a dumb linear search.
7374    *)
7375   let commands =
7376     List.map (
7377       fun (name, _, _, flags, _, _, _) ->
7378         let name2 = replace_char name '_' '-' in
7379         let alias =
7380           try find_map (function FishAlias n -> Some n | _ -> None) flags
7381           with Not_found -> name in
7382
7383         if name <> alias then [name2; alias] else [name2]
7384     ) all_functions in
7385   let commands = List.flatten commands in
7386
7387   List.iter (pr "  \"%s\",\n") commands;
7388
7389   pr "  NULL
7390 };
7391
7392 static char *
7393 generator (const char *text, int state)
7394 {
7395   static int index, len;
7396   const char *name;
7397
7398   if (!state) {
7399     index = 0;
7400     len = strlen (text);
7401   }
7402
7403   rl_attempted_completion_over = 1;
7404
7405   while ((name = commands[index]) != NULL) {
7406     index++;
7407     if (STRCASEEQLEN (name, text, len))
7408       return strdup (name);
7409   }
7410
7411   return NULL;
7412 }
7413
7414 #endif /* HAVE_LIBREADLINE */
7415
7416 char **do_completion (const char *text, int start, int end)
7417 {
7418   char **matches = NULL;
7419
7420 #ifdef HAVE_LIBREADLINE
7421   rl_completion_append_character = ' ';
7422
7423   if (start == 0)
7424     matches = rl_completion_matches (text, generator);
7425   else if (complete_dest_paths)
7426     matches = rl_completion_matches (text, complete_dest_paths_generator);
7427 #endif
7428
7429   return matches;
7430 }
7431 ";
7432
7433 (* Generate the POD documentation for guestfish. *)
7434 and generate_fish_actions_pod () =
7435   let all_functions_sorted =
7436     List.filter (
7437       fun (_, _, _, flags, _, _, _) ->
7438         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7439     ) all_functions_sorted in
7440
7441   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7442
7443   List.iter (
7444     fun (name, style, _, flags, _, _, longdesc) ->
7445       let longdesc =
7446         Str.global_substitute rex (
7447           fun s ->
7448             let sub =
7449               try Str.matched_group 1 s
7450               with Not_found ->
7451                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7452             "C<" ^ replace_char sub '_' '-' ^ ">"
7453         ) longdesc in
7454       let name = replace_char name '_' '-' in
7455       let alias =
7456         try find_map (function FishAlias n -> Some n | _ -> None) flags
7457         with Not_found -> name in
7458
7459       pr "=head2 %s" name;
7460       if name <> alias then
7461         pr " | %s" alias;
7462       pr "\n";
7463       pr "\n";
7464       pr " %s" name;
7465       List.iter (
7466         function
7467         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7468         | OptString n -> pr " %s" n
7469         | StringList n | DeviceList n -> pr " '%s ...'" n
7470         | Bool _ -> pr " true|false"
7471         | Int n -> pr " %s" n
7472         | Int64 n -> pr " %s" n
7473         | FileIn n | FileOut n -> pr " (%s|-)" n
7474       ) (snd style);
7475       pr "\n";
7476       pr "\n";
7477       pr "%s\n\n" longdesc;
7478
7479       if List.exists (function FileIn _ | FileOut _ -> true
7480                       | _ -> false) (snd style) then
7481         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7482
7483       if List.mem ProtocolLimitWarning flags then
7484         pr "%s\n\n" protocol_limit_warning;
7485
7486       if List.mem DangerWillRobinson flags then
7487         pr "%s\n\n" danger_will_robinson;
7488
7489       match deprecation_notice flags with
7490       | None -> ()
7491       | Some txt -> pr "%s\n\n" txt
7492   ) all_functions_sorted
7493
7494 (* Generate a C function prototype. *)
7495 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7496     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7497     ?(prefix = "")
7498     ?handle name style =
7499   if extern then pr "extern ";
7500   if static then pr "static ";
7501   (match fst style with
7502    | RErr -> pr "int "
7503    | RInt _ -> pr "int "
7504    | RInt64 _ -> pr "int64_t "
7505    | RBool _ -> pr "int "
7506    | RConstString _ | RConstOptString _ -> pr "const char *"
7507    | RString _ | RBufferOut _ -> pr "char *"
7508    | RStringList _ | RHashtable _ -> pr "char **"
7509    | RStruct (_, typ) ->
7510        if not in_daemon then pr "struct guestfs_%s *" typ
7511        else pr "guestfs_int_%s *" typ
7512    | RStructList (_, typ) ->
7513        if not in_daemon then pr "struct guestfs_%s_list *" typ
7514        else pr "guestfs_int_%s_list *" typ
7515   );
7516   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7517   pr "%s%s (" prefix name;
7518   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7519     pr "void"
7520   else (
7521     let comma = ref false in
7522     (match handle with
7523      | None -> ()
7524      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7525     );
7526     let next () =
7527       if !comma then (
7528         if single_line then pr ", " else pr ",\n\t\t"
7529       );
7530       comma := true
7531     in
7532     List.iter (
7533       function
7534       | Pathname n
7535       | Device n | Dev_or_Path n
7536       | String n
7537       | OptString n ->
7538           next ();
7539           pr "const char *%s" n
7540       | StringList n | DeviceList n ->
7541           next ();
7542           pr "char *const *%s" n
7543       | Bool n -> next (); pr "int %s" n
7544       | Int n -> next (); pr "int %s" n
7545       | Int64 n -> next (); pr "int64_t %s" n
7546       | FileIn n
7547       | FileOut n ->
7548           if not in_daemon then (next (); pr "const char *%s" n)
7549     ) (snd style);
7550     if is_RBufferOut then (next (); pr "size_t *size_r");
7551   );
7552   pr ")";
7553   if semicolon then pr ";";
7554   if newline then pr "\n"
7555
7556 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7557 and generate_c_call_args ?handle ?(decl = false) style =
7558   pr "(";
7559   let comma = ref false in
7560   let next () =
7561     if !comma then pr ", ";
7562     comma := true
7563   in
7564   (match handle with
7565    | None -> ()
7566    | Some handle -> pr "%s" handle; comma := true
7567   );
7568   List.iter (
7569     fun arg ->
7570       next ();
7571       pr "%s" (name_of_argt arg)
7572   ) (snd style);
7573   (* For RBufferOut calls, add implicit &size parameter. *)
7574   if not decl then (
7575     match fst style with
7576     | RBufferOut _ ->
7577         next ();
7578         pr "&size"
7579     | _ -> ()
7580   );
7581   pr ")"
7582
7583 (* Generate the OCaml bindings interface. *)
7584 and generate_ocaml_mli () =
7585   generate_header OCamlStyle LGPLv2plus;
7586
7587   pr "\
7588 (** For API documentation you should refer to the C API
7589     in the guestfs(3) manual page.  The OCaml API uses almost
7590     exactly the same calls. *)
7591
7592 type t
7593 (** A [guestfs_h] handle. *)
7594
7595 exception Error of string
7596 (** This exception is raised when there is an error. *)
7597
7598 exception Handle_closed of string
7599 (** This exception is raised if you use a {!Guestfs.t} handle
7600     after calling {!close} on it.  The string is the name of
7601     the function. *)
7602
7603 val create : unit -> t
7604 (** Create a {!Guestfs.t} handle. *)
7605
7606 val close : t -> unit
7607 (** Close the {!Guestfs.t} handle and free up all resources used
7608     by it immediately.
7609
7610     Handles are closed by the garbage collector when they become
7611     unreferenced, but callers can call this in order to provide
7612     predictable cleanup. *)
7613
7614 ";
7615   generate_ocaml_structure_decls ();
7616
7617   (* The actions. *)
7618   List.iter (
7619     fun (name, style, _, _, _, shortdesc, _) ->
7620       generate_ocaml_prototype name style;
7621       pr "(** %s *)\n" shortdesc;
7622       pr "\n"
7623   ) all_functions_sorted
7624
7625 (* Generate the OCaml bindings implementation. *)
7626 and generate_ocaml_ml () =
7627   generate_header OCamlStyle LGPLv2plus;
7628
7629   pr "\
7630 type t
7631
7632 exception Error of string
7633 exception Handle_closed of string
7634
7635 external create : unit -> t = \"ocaml_guestfs_create\"
7636 external close : t -> unit = \"ocaml_guestfs_close\"
7637
7638 (* Give the exceptions names, so they can be raised from the C code. *)
7639 let () =
7640   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7641   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7642
7643 ";
7644
7645   generate_ocaml_structure_decls ();
7646
7647   (* The actions. *)
7648   List.iter (
7649     fun (name, style, _, _, _, shortdesc, _) ->
7650       generate_ocaml_prototype ~is_external:true name style;
7651   ) all_functions_sorted
7652
7653 (* Generate the OCaml bindings C implementation. *)
7654 and generate_ocaml_c () =
7655   generate_header CStyle LGPLv2plus;
7656
7657   pr "\
7658 #include <stdio.h>
7659 #include <stdlib.h>
7660 #include <string.h>
7661
7662 #include <caml/config.h>
7663 #include <caml/alloc.h>
7664 #include <caml/callback.h>
7665 #include <caml/fail.h>
7666 #include <caml/memory.h>
7667 #include <caml/mlvalues.h>
7668 #include <caml/signals.h>
7669
7670 #include <guestfs.h>
7671
7672 #include \"guestfs_c.h\"
7673
7674 /* Copy a hashtable of string pairs into an assoc-list.  We return
7675  * the list in reverse order, but hashtables aren't supposed to be
7676  * ordered anyway.
7677  */
7678 static CAMLprim value
7679 copy_table (char * const * argv)
7680 {
7681   CAMLparam0 ();
7682   CAMLlocal5 (rv, pairv, kv, vv, cons);
7683   int i;
7684
7685   rv = Val_int (0);
7686   for (i = 0; argv[i] != NULL; i += 2) {
7687     kv = caml_copy_string (argv[i]);
7688     vv = caml_copy_string (argv[i+1]);
7689     pairv = caml_alloc (2, 0);
7690     Store_field (pairv, 0, kv);
7691     Store_field (pairv, 1, vv);
7692     cons = caml_alloc (2, 0);
7693     Store_field (cons, 1, rv);
7694     rv = cons;
7695     Store_field (cons, 0, pairv);
7696   }
7697
7698   CAMLreturn (rv);
7699 }
7700
7701 ";
7702
7703   (* Struct copy functions. *)
7704
7705   let emit_ocaml_copy_list_function typ =
7706     pr "static CAMLprim value\n";
7707     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7708     pr "{\n";
7709     pr "  CAMLparam0 ();\n";
7710     pr "  CAMLlocal2 (rv, v);\n";
7711     pr "  unsigned int i;\n";
7712     pr "\n";
7713     pr "  if (%ss->len == 0)\n" typ;
7714     pr "    CAMLreturn (Atom (0));\n";
7715     pr "  else {\n";
7716     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7717     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7718     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7719     pr "      caml_modify (&Field (rv, i), v);\n";
7720     pr "    }\n";
7721     pr "    CAMLreturn (rv);\n";
7722     pr "  }\n";
7723     pr "}\n";
7724     pr "\n";
7725   in
7726
7727   List.iter (
7728     fun (typ, cols) ->
7729       let has_optpercent_col =
7730         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7731
7732       pr "static CAMLprim value\n";
7733       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7734       pr "{\n";
7735       pr "  CAMLparam0 ();\n";
7736       if has_optpercent_col then
7737         pr "  CAMLlocal3 (rv, v, v2);\n"
7738       else
7739         pr "  CAMLlocal2 (rv, v);\n";
7740       pr "\n";
7741       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7742       iteri (
7743         fun i col ->
7744           (match col with
7745            | name, FString ->
7746                pr "  v = caml_copy_string (%s->%s);\n" typ name
7747            | name, FBuffer ->
7748                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7749                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7750                  typ name typ name
7751            | name, FUUID ->
7752                pr "  v = caml_alloc_string (32);\n";
7753                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7754            | name, (FBytes|FInt64|FUInt64) ->
7755                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7756            | name, (FInt32|FUInt32) ->
7757                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7758            | name, FOptPercent ->
7759                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7760                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7761                pr "    v = caml_alloc (1, 0);\n";
7762                pr "    Store_field (v, 0, v2);\n";
7763                pr "  } else /* None */\n";
7764                pr "    v = Val_int (0);\n";
7765            | name, FChar ->
7766                pr "  v = Val_int (%s->%s);\n" typ name
7767           );
7768           pr "  Store_field (rv, %d, v);\n" i
7769       ) cols;
7770       pr "  CAMLreturn (rv);\n";
7771       pr "}\n";
7772       pr "\n";
7773   ) structs;
7774
7775   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7776   List.iter (
7777     function
7778     | typ, (RStructListOnly | RStructAndList) ->
7779         (* generate the function for typ *)
7780         emit_ocaml_copy_list_function typ
7781     | typ, _ -> () (* empty *)
7782   ) (rstructs_used_by all_functions);
7783
7784   (* The wrappers. *)
7785   List.iter (
7786     fun (name, style, _, _, _, _, _) ->
7787       pr "/* Automatically generated wrapper for function\n";
7788       pr " * ";
7789       generate_ocaml_prototype name style;
7790       pr " */\n";
7791       pr "\n";
7792
7793       let params =
7794         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7795
7796       let needs_extra_vs =
7797         match fst style with RConstOptString _ -> true | _ -> false in
7798
7799       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7800       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7801       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7802       pr "\n";
7803
7804       pr "CAMLprim value\n";
7805       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7806       List.iter (pr ", value %s") (List.tl params);
7807       pr ")\n";
7808       pr "{\n";
7809
7810       (match params with
7811        | [p1; p2; p3; p4; p5] ->
7812            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7813        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7814            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7815            pr "  CAMLxparam%d (%s);\n"
7816              (List.length rest) (String.concat ", " rest)
7817        | ps ->
7818            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7819       );
7820       if not needs_extra_vs then
7821         pr "  CAMLlocal1 (rv);\n"
7822       else
7823         pr "  CAMLlocal3 (rv, v, v2);\n";
7824       pr "\n";
7825
7826       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7827       pr "  if (g == NULL)\n";
7828       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7829       pr "\n";
7830
7831       List.iter (
7832         function
7833         | Pathname n
7834         | Device n | Dev_or_Path n
7835         | String n
7836         | FileIn n
7837         | FileOut n ->
7838             pr "  const char *%s = String_val (%sv);\n" n n
7839         | OptString n ->
7840             pr "  const char *%s =\n" n;
7841             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7842               n n
7843         | StringList n | DeviceList n ->
7844             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7845         | Bool n ->
7846             pr "  int %s = Bool_val (%sv);\n" n n
7847         | Int n ->
7848             pr "  int %s = Int_val (%sv);\n" n n
7849         | Int64 n ->
7850             pr "  int64_t %s = Int64_val (%sv);\n" n n
7851       ) (snd style);
7852       let error_code =
7853         match fst style with
7854         | RErr -> pr "  int r;\n"; "-1"
7855         | RInt _ -> pr "  int r;\n"; "-1"
7856         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7857         | RBool _ -> pr "  int r;\n"; "-1"
7858         | RConstString _ | RConstOptString _ ->
7859             pr "  const char *r;\n"; "NULL"
7860         | RString _ -> pr "  char *r;\n"; "NULL"
7861         | RStringList _ ->
7862             pr "  int i;\n";
7863             pr "  char **r;\n";
7864             "NULL"
7865         | RStruct (_, typ) ->
7866             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7867         | RStructList (_, typ) ->
7868             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7869         | RHashtable _ ->
7870             pr "  int i;\n";
7871             pr "  char **r;\n";
7872             "NULL"
7873         | RBufferOut _ ->
7874             pr "  char *r;\n";
7875             pr "  size_t size;\n";
7876             "NULL" in
7877       pr "\n";
7878
7879       pr "  caml_enter_blocking_section ();\n";
7880       pr "  r = guestfs_%s " name;
7881       generate_c_call_args ~handle:"g" style;
7882       pr ";\n";
7883       pr "  caml_leave_blocking_section ();\n";
7884
7885       List.iter (
7886         function
7887         | StringList n | DeviceList n ->
7888             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7889         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7890         | Bool _ | Int _ | Int64 _
7891         | FileIn _ | FileOut _ -> ()
7892       ) (snd style);
7893
7894       pr "  if (r == %s)\n" error_code;
7895       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7896       pr "\n";
7897
7898       (match fst style with
7899        | RErr -> pr "  rv = Val_unit;\n"
7900        | RInt _ -> pr "  rv = Val_int (r);\n"
7901        | RInt64 _ ->
7902            pr "  rv = caml_copy_int64 (r);\n"
7903        | RBool _ -> pr "  rv = Val_bool (r);\n"
7904        | RConstString _ ->
7905            pr "  rv = caml_copy_string (r);\n"
7906        | RConstOptString _ ->
7907            pr "  if (r) { /* Some string */\n";
7908            pr "    v = caml_alloc (1, 0);\n";
7909            pr "    v2 = caml_copy_string (r);\n";
7910            pr "    Store_field (v, 0, v2);\n";
7911            pr "  } else /* None */\n";
7912            pr "    v = Val_int (0);\n";
7913        | RString _ ->
7914            pr "  rv = caml_copy_string (r);\n";
7915            pr "  free (r);\n"
7916        | RStringList _ ->
7917            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7918            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7919            pr "  free (r);\n"
7920        | RStruct (_, typ) ->
7921            pr "  rv = copy_%s (r);\n" typ;
7922            pr "  guestfs_free_%s (r);\n" typ;
7923        | RStructList (_, typ) ->
7924            pr "  rv = copy_%s_list (r);\n" typ;
7925            pr "  guestfs_free_%s_list (r);\n" typ;
7926        | RHashtable _ ->
7927            pr "  rv = copy_table (r);\n";
7928            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7929            pr "  free (r);\n";
7930        | RBufferOut _ ->
7931            pr "  rv = caml_alloc_string (size);\n";
7932            pr "  memcpy (String_val (rv), r, size);\n";
7933       );
7934
7935       pr "  CAMLreturn (rv);\n";
7936       pr "}\n";
7937       pr "\n";
7938
7939       if List.length params > 5 then (
7940         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7941         pr "CAMLprim value ";
7942         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7943         pr "CAMLprim value\n";
7944         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7945         pr "{\n";
7946         pr "  return ocaml_guestfs_%s (argv[0]" name;
7947         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7948         pr ");\n";
7949         pr "}\n";
7950         pr "\n"
7951       )
7952   ) all_functions_sorted
7953
7954 and generate_ocaml_structure_decls () =
7955   List.iter (
7956     fun (typ, cols) ->
7957       pr "type %s = {\n" typ;
7958       List.iter (
7959         function
7960         | name, FString -> pr "  %s : string;\n" name
7961         | name, FBuffer -> pr "  %s : string;\n" name
7962         | name, FUUID -> pr "  %s : string;\n" name
7963         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7964         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7965         | name, FChar -> pr "  %s : char;\n" name
7966         | name, FOptPercent -> pr "  %s : float option;\n" name
7967       ) cols;
7968       pr "}\n";
7969       pr "\n"
7970   ) structs
7971
7972 and generate_ocaml_prototype ?(is_external = false) name style =
7973   if is_external then pr "external " else pr "val ";
7974   pr "%s : t -> " name;
7975   List.iter (
7976     function
7977     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7978     | OptString _ -> pr "string option -> "
7979     | StringList _ | DeviceList _ -> pr "string array -> "
7980     | Bool _ -> pr "bool -> "
7981     | Int _ -> pr "int -> "
7982     | Int64 _ -> pr "int64 -> "
7983   ) (snd style);
7984   (match fst style with
7985    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7986    | RInt _ -> pr "int"
7987    | RInt64 _ -> pr "int64"
7988    | RBool _ -> pr "bool"
7989    | RConstString _ -> pr "string"
7990    | RConstOptString _ -> pr "string option"
7991    | RString _ | RBufferOut _ -> pr "string"
7992    | RStringList _ -> pr "string array"
7993    | RStruct (_, typ) -> pr "%s" typ
7994    | RStructList (_, typ) -> pr "%s array" typ
7995    | RHashtable _ -> pr "(string * string) list"
7996   );
7997   if is_external then (
7998     pr " = ";
7999     if List.length (snd style) + 1 > 5 then
8000       pr "\"ocaml_guestfs_%s_byte\" " name;
8001     pr "\"ocaml_guestfs_%s\"" name
8002   );
8003   pr "\n"
8004
8005 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8006 and generate_perl_xs () =
8007   generate_header CStyle LGPLv2plus;
8008
8009   pr "\
8010 #include \"EXTERN.h\"
8011 #include \"perl.h\"
8012 #include \"XSUB.h\"
8013
8014 #include <guestfs.h>
8015
8016 #ifndef PRId64
8017 #define PRId64 \"lld\"
8018 #endif
8019
8020 static SV *
8021 my_newSVll(long long val) {
8022 #ifdef USE_64_BIT_ALL
8023   return newSViv(val);
8024 #else
8025   char buf[100];
8026   int len;
8027   len = snprintf(buf, 100, \"%%\" PRId64, val);
8028   return newSVpv(buf, len);
8029 #endif
8030 }
8031
8032 #ifndef PRIu64
8033 #define PRIu64 \"llu\"
8034 #endif
8035
8036 static SV *
8037 my_newSVull(unsigned long long val) {
8038 #ifdef USE_64_BIT_ALL
8039   return newSVuv(val);
8040 #else
8041   char buf[100];
8042   int len;
8043   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8044   return newSVpv(buf, len);
8045 #endif
8046 }
8047
8048 /* http://www.perlmonks.org/?node_id=680842 */
8049 static char **
8050 XS_unpack_charPtrPtr (SV *arg) {
8051   char **ret;
8052   AV *av;
8053   I32 i;
8054
8055   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8056     croak (\"array reference expected\");
8057
8058   av = (AV *)SvRV (arg);
8059   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8060   if (!ret)
8061     croak (\"malloc failed\");
8062
8063   for (i = 0; i <= av_len (av); i++) {
8064     SV **elem = av_fetch (av, i, 0);
8065
8066     if (!elem || !*elem)
8067       croak (\"missing element in list\");
8068
8069     ret[i] = SvPV_nolen (*elem);
8070   }
8071
8072   ret[i] = NULL;
8073
8074   return ret;
8075 }
8076
8077 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8078
8079 PROTOTYPES: ENABLE
8080
8081 guestfs_h *
8082 _create ()
8083    CODE:
8084       RETVAL = guestfs_create ();
8085       if (!RETVAL)
8086         croak (\"could not create guestfs handle\");
8087       guestfs_set_error_handler (RETVAL, NULL, NULL);
8088  OUTPUT:
8089       RETVAL
8090
8091 void
8092 DESTROY (g)
8093       guestfs_h *g;
8094  PPCODE:
8095       guestfs_close (g);
8096
8097 ";
8098
8099   List.iter (
8100     fun (name, style, _, _, _, _, _) ->
8101       (match fst style with
8102        | RErr -> pr "void\n"
8103        | RInt _ -> pr "SV *\n"
8104        | RInt64 _ -> pr "SV *\n"
8105        | RBool _ -> pr "SV *\n"
8106        | RConstString _ -> pr "SV *\n"
8107        | RConstOptString _ -> pr "SV *\n"
8108        | RString _ -> pr "SV *\n"
8109        | RBufferOut _ -> pr "SV *\n"
8110        | RStringList _
8111        | RStruct _ | RStructList _
8112        | RHashtable _ ->
8113            pr "void\n" (* all lists returned implictly on the stack *)
8114       );
8115       (* Call and arguments. *)
8116       pr "%s " name;
8117       generate_c_call_args ~handle:"g" ~decl:true style;
8118       pr "\n";
8119       pr "      guestfs_h *g;\n";
8120       iteri (
8121         fun i ->
8122           function
8123           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8124               pr "      char *%s;\n" n
8125           | OptString n ->
8126               (* http://www.perlmonks.org/?node_id=554277
8127                * Note that the implicit handle argument means we have
8128                * to add 1 to the ST(x) operator.
8129                *)
8130               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8131           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8132           | Bool n -> pr "      int %s;\n" n
8133           | Int n -> pr "      int %s;\n" n
8134           | Int64 n -> pr "      int64_t %s;\n" n
8135       ) (snd style);
8136
8137       let do_cleanups () =
8138         List.iter (
8139           function
8140           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8141           | Bool _ | Int _ | Int64 _
8142           | FileIn _ | FileOut _ -> ()
8143           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8144         ) (snd style)
8145       in
8146
8147       (* Code. *)
8148       (match fst style with
8149        | RErr ->
8150            pr "PREINIT:\n";
8151            pr "      int r;\n";
8152            pr " PPCODE:\n";
8153            pr "      r = guestfs_%s " name;
8154            generate_c_call_args ~handle:"g" style;
8155            pr ";\n";
8156            do_cleanups ();
8157            pr "      if (r == -1)\n";
8158            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8159        | RInt n
8160        | RBool n ->
8161            pr "PREINIT:\n";
8162            pr "      int %s;\n" n;
8163            pr "   CODE:\n";
8164            pr "      %s = guestfs_%s " n name;
8165            generate_c_call_args ~handle:"g" style;
8166            pr ";\n";
8167            do_cleanups ();
8168            pr "      if (%s == -1)\n" n;
8169            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8170            pr "      RETVAL = newSViv (%s);\n" n;
8171            pr " OUTPUT:\n";
8172            pr "      RETVAL\n"
8173        | RInt64 n ->
8174            pr "PREINIT:\n";
8175            pr "      int64_t %s;\n" n;
8176            pr "   CODE:\n";
8177            pr "      %s = guestfs_%s " n name;
8178            generate_c_call_args ~handle:"g" style;
8179            pr ";\n";
8180            do_cleanups ();
8181            pr "      if (%s == -1)\n" n;
8182            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8183            pr "      RETVAL = my_newSVll (%s);\n" n;
8184            pr " OUTPUT:\n";
8185            pr "      RETVAL\n"
8186        | RConstString n ->
8187            pr "PREINIT:\n";
8188            pr "      const char *%s;\n" n;
8189            pr "   CODE:\n";
8190            pr "      %s = guestfs_%s " n name;
8191            generate_c_call_args ~handle:"g" style;
8192            pr ";\n";
8193            do_cleanups ();
8194            pr "      if (%s == NULL)\n" n;
8195            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8196            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8197            pr " OUTPUT:\n";
8198            pr "      RETVAL\n"
8199        | RConstOptString n ->
8200            pr "PREINIT:\n";
8201            pr "      const char *%s;\n" n;
8202            pr "   CODE:\n";
8203            pr "      %s = guestfs_%s " n name;
8204            generate_c_call_args ~handle:"g" style;
8205            pr ";\n";
8206            do_cleanups ();
8207            pr "      if (%s == NULL)\n" n;
8208            pr "        RETVAL = &PL_sv_undef;\n";
8209            pr "      else\n";
8210            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8211            pr " OUTPUT:\n";
8212            pr "      RETVAL\n"
8213        | RString n ->
8214            pr "PREINIT:\n";
8215            pr "      char *%s;\n" n;
8216            pr "   CODE:\n";
8217            pr "      %s = guestfs_%s " n name;
8218            generate_c_call_args ~handle:"g" style;
8219            pr ";\n";
8220            do_cleanups ();
8221            pr "      if (%s == NULL)\n" n;
8222            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8223            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8224            pr "      free (%s);\n" n;
8225            pr " OUTPUT:\n";
8226            pr "      RETVAL\n"
8227        | RStringList n | RHashtable n ->
8228            pr "PREINIT:\n";
8229            pr "      char **%s;\n" n;
8230            pr "      int i, n;\n";
8231            pr " PPCODE:\n";
8232            pr "      %s = guestfs_%s " n name;
8233            generate_c_call_args ~handle:"g" style;
8234            pr ";\n";
8235            do_cleanups ();
8236            pr "      if (%s == NULL)\n" n;
8237            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8238            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8239            pr "      EXTEND (SP, n);\n";
8240            pr "      for (i = 0; i < n; ++i) {\n";
8241            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8242            pr "        free (%s[i]);\n" n;
8243            pr "      }\n";
8244            pr "      free (%s);\n" n;
8245        | RStruct (n, typ) ->
8246            let cols = cols_of_struct typ in
8247            generate_perl_struct_code typ cols name style n do_cleanups
8248        | RStructList (n, typ) ->
8249            let cols = cols_of_struct typ in
8250            generate_perl_struct_list_code typ cols name style n do_cleanups
8251        | RBufferOut n ->
8252            pr "PREINIT:\n";
8253            pr "      char *%s;\n" n;
8254            pr "      size_t size;\n";
8255            pr "   CODE:\n";
8256            pr "      %s = guestfs_%s " n name;
8257            generate_c_call_args ~handle:"g" style;
8258            pr ";\n";
8259            do_cleanups ();
8260            pr "      if (%s == NULL)\n" n;
8261            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8262            pr "      RETVAL = newSVpv (%s, size);\n" n;
8263            pr "      free (%s);\n" n;
8264            pr " OUTPUT:\n";
8265            pr "      RETVAL\n"
8266       );
8267
8268       pr "\n"
8269   ) all_functions
8270
8271 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8272   pr "PREINIT:\n";
8273   pr "      struct guestfs_%s_list *%s;\n" typ n;
8274   pr "      int i;\n";
8275   pr "      HV *hv;\n";
8276   pr " PPCODE:\n";
8277   pr "      %s = guestfs_%s " n name;
8278   generate_c_call_args ~handle:"g" style;
8279   pr ";\n";
8280   do_cleanups ();
8281   pr "      if (%s == NULL)\n" n;
8282   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8283   pr "      EXTEND (SP, %s->len);\n" n;
8284   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8285   pr "        hv = newHV ();\n";
8286   List.iter (
8287     function
8288     | name, FString ->
8289         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8290           name (String.length name) n name
8291     | name, FUUID ->
8292         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8293           name (String.length name) n name
8294     | name, FBuffer ->
8295         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8296           name (String.length name) n name n name
8297     | name, (FBytes|FUInt64) ->
8298         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8299           name (String.length name) n name
8300     | name, FInt64 ->
8301         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8302           name (String.length name) n name
8303     | name, (FInt32|FUInt32) ->
8304         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8305           name (String.length name) n name
8306     | name, FChar ->
8307         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8308           name (String.length name) n name
8309     | name, FOptPercent ->
8310         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8311           name (String.length name) n name
8312   ) cols;
8313   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8314   pr "      }\n";
8315   pr "      guestfs_free_%s_list (%s);\n" typ n
8316
8317 and generate_perl_struct_code typ cols name style n do_cleanups =
8318   pr "PREINIT:\n";
8319   pr "      struct guestfs_%s *%s;\n" typ n;
8320   pr " PPCODE:\n";
8321   pr "      %s = guestfs_%s " n name;
8322   generate_c_call_args ~handle:"g" style;
8323   pr ";\n";
8324   do_cleanups ();
8325   pr "      if (%s == NULL)\n" n;
8326   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8327   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8328   List.iter (
8329     fun ((name, _) as col) ->
8330       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8331
8332       match col with
8333       | name, FString ->
8334           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8335             n name
8336       | name, FBuffer ->
8337           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8338             n name n name
8339       | name, FUUID ->
8340           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8341             n name
8342       | name, (FBytes|FUInt64) ->
8343           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8344             n name
8345       | name, FInt64 ->
8346           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8347             n name
8348       | name, (FInt32|FUInt32) ->
8349           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8350             n name
8351       | name, FChar ->
8352           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8353             n name
8354       | name, FOptPercent ->
8355           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8356             n name
8357   ) cols;
8358   pr "      free (%s);\n" n
8359
8360 (* Generate Sys/Guestfs.pm. *)
8361 and generate_perl_pm () =
8362   generate_header HashStyle LGPLv2plus;
8363
8364   pr "\
8365 =pod
8366
8367 =head1 NAME
8368
8369 Sys::Guestfs - Perl bindings for libguestfs
8370
8371 =head1 SYNOPSIS
8372
8373  use Sys::Guestfs;
8374
8375  my $h = Sys::Guestfs->new ();
8376  $h->add_drive ('guest.img');
8377  $h->launch ();
8378  $h->mount ('/dev/sda1', '/');
8379  $h->touch ('/hello');
8380  $h->sync ();
8381
8382 =head1 DESCRIPTION
8383
8384 The C<Sys::Guestfs> module provides a Perl XS binding to the
8385 libguestfs API for examining and modifying virtual machine
8386 disk images.
8387
8388 Amongst the things this is good for: making batch configuration
8389 changes to guests, getting disk used/free statistics (see also:
8390 virt-df), migrating between virtualization systems (see also:
8391 virt-p2v), performing partial backups, performing partial guest
8392 clones, cloning guests and changing registry/UUID/hostname info, and
8393 much else besides.
8394
8395 Libguestfs uses Linux kernel and qemu code, and can access any type of
8396 guest filesystem that Linux and qemu can, including but not limited
8397 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8398 schemes, qcow, qcow2, vmdk.
8399
8400 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8401 LVs, what filesystem is in each LV, etc.).  It can also run commands
8402 in the context of the guest.  Also you can access filesystems over
8403 FUSE.
8404
8405 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8406 functions for using libguestfs from Perl, including integration
8407 with libvirt.
8408
8409 =head1 ERRORS
8410
8411 All errors turn into calls to C<croak> (see L<Carp(3)>).
8412
8413 =head1 METHODS
8414
8415 =over 4
8416
8417 =cut
8418
8419 package Sys::Guestfs;
8420
8421 use strict;
8422 use warnings;
8423
8424 require XSLoader;
8425 XSLoader::load ('Sys::Guestfs');
8426
8427 =item $h = Sys::Guestfs->new ();
8428
8429 Create a new guestfs handle.
8430
8431 =cut
8432
8433 sub new {
8434   my $proto = shift;
8435   my $class = ref ($proto) || $proto;
8436
8437   my $self = Sys::Guestfs::_create ();
8438   bless $self, $class;
8439   return $self;
8440 }
8441
8442 ";
8443
8444   (* Actions.  We only need to print documentation for these as
8445    * they are pulled in from the XS code automatically.
8446    *)
8447   List.iter (
8448     fun (name, style, _, flags, _, _, longdesc) ->
8449       if not (List.mem NotInDocs flags) then (
8450         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8451         pr "=item ";
8452         generate_perl_prototype name style;
8453         pr "\n\n";
8454         pr "%s\n\n" longdesc;
8455         if List.mem ProtocolLimitWarning flags then
8456           pr "%s\n\n" protocol_limit_warning;
8457         if List.mem DangerWillRobinson flags then
8458           pr "%s\n\n" danger_will_robinson;
8459         match deprecation_notice flags with
8460         | None -> ()
8461         | Some txt -> pr "%s\n\n" txt
8462       )
8463   ) all_functions_sorted;
8464
8465   (* End of file. *)
8466   pr "\
8467 =cut
8468
8469 1;
8470
8471 =back
8472
8473 =head1 COPYRIGHT
8474
8475 Copyright (C) %s Red Hat Inc.
8476
8477 =head1 LICENSE
8478
8479 Please see the file COPYING.LIB for the full license.
8480
8481 =head1 SEE ALSO
8482
8483 L<guestfs(3)>,
8484 L<guestfish(1)>,
8485 L<http://libguestfs.org>,
8486 L<Sys::Guestfs::Lib(3)>.
8487
8488 =cut
8489 " copyright_years
8490
8491 and generate_perl_prototype name style =
8492   (match fst style with
8493    | RErr -> ()
8494    | RBool n
8495    | RInt n
8496    | RInt64 n
8497    | RConstString n
8498    | RConstOptString n
8499    | RString n
8500    | RBufferOut n -> pr "$%s = " n
8501    | RStruct (n,_)
8502    | RHashtable n -> pr "%%%s = " n
8503    | RStringList n
8504    | RStructList (n,_) -> pr "@%s = " n
8505   );
8506   pr "$h->%s (" name;
8507   let comma = ref false in
8508   List.iter (
8509     fun arg ->
8510       if !comma then pr ", ";
8511       comma := true;
8512       match arg with
8513       | Pathname n | Device n | Dev_or_Path n | String n
8514       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8515           pr "$%s" n
8516       | StringList n | DeviceList n ->
8517           pr "\\@%s" n
8518   ) (snd style);
8519   pr ");"
8520
8521 (* Generate Python C module. *)
8522 and generate_python_c () =
8523   generate_header CStyle LGPLv2plus;
8524
8525   pr "\
8526 #include <Python.h>
8527
8528 #include <stdio.h>
8529 #include <stdlib.h>
8530 #include <assert.h>
8531
8532 #include \"guestfs.h\"
8533
8534 typedef struct {
8535   PyObject_HEAD
8536   guestfs_h *g;
8537 } Pyguestfs_Object;
8538
8539 static guestfs_h *
8540 get_handle (PyObject *obj)
8541 {
8542   assert (obj);
8543   assert (obj != Py_None);
8544   return ((Pyguestfs_Object *) obj)->g;
8545 }
8546
8547 static PyObject *
8548 put_handle (guestfs_h *g)
8549 {
8550   assert (g);
8551   return
8552     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8553 }
8554
8555 /* This list should be freed (but not the strings) after use. */
8556 static char **
8557 get_string_list (PyObject *obj)
8558 {
8559   int i, len;
8560   char **r;
8561
8562   assert (obj);
8563
8564   if (!PyList_Check (obj)) {
8565     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8566     return NULL;
8567   }
8568
8569   len = PyList_Size (obj);
8570   r = malloc (sizeof (char *) * (len+1));
8571   if (r == NULL) {
8572     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8573     return NULL;
8574   }
8575
8576   for (i = 0; i < len; ++i)
8577     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8578   r[len] = NULL;
8579
8580   return r;
8581 }
8582
8583 static PyObject *
8584 put_string_list (char * const * const argv)
8585 {
8586   PyObject *list;
8587   int argc, i;
8588
8589   for (argc = 0; argv[argc] != NULL; ++argc)
8590     ;
8591
8592   list = PyList_New (argc);
8593   for (i = 0; i < argc; ++i)
8594     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8595
8596   return list;
8597 }
8598
8599 static PyObject *
8600 put_table (char * const * const argv)
8601 {
8602   PyObject *list, *item;
8603   int argc, i;
8604
8605   for (argc = 0; argv[argc] != NULL; ++argc)
8606     ;
8607
8608   list = PyList_New (argc >> 1);
8609   for (i = 0; i < argc; i += 2) {
8610     item = PyTuple_New (2);
8611     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8612     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8613     PyList_SetItem (list, i >> 1, item);
8614   }
8615
8616   return list;
8617 }
8618
8619 static void
8620 free_strings (char **argv)
8621 {
8622   int argc;
8623
8624   for (argc = 0; argv[argc] != NULL; ++argc)
8625     free (argv[argc]);
8626   free (argv);
8627 }
8628
8629 static PyObject *
8630 py_guestfs_create (PyObject *self, PyObject *args)
8631 {
8632   guestfs_h *g;
8633
8634   g = guestfs_create ();
8635   if (g == NULL) {
8636     PyErr_SetString (PyExc_RuntimeError,
8637                      \"guestfs.create: failed to allocate handle\");
8638     return NULL;
8639   }
8640   guestfs_set_error_handler (g, NULL, NULL);
8641   return put_handle (g);
8642 }
8643
8644 static PyObject *
8645 py_guestfs_close (PyObject *self, PyObject *args)
8646 {
8647   PyObject *py_g;
8648   guestfs_h *g;
8649
8650   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8651     return NULL;
8652   g = get_handle (py_g);
8653
8654   guestfs_close (g);
8655
8656   Py_INCREF (Py_None);
8657   return Py_None;
8658 }
8659
8660 ";
8661
8662   let emit_put_list_function typ =
8663     pr "static PyObject *\n";
8664     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8665     pr "{\n";
8666     pr "  PyObject *list;\n";
8667     pr "  int i;\n";
8668     pr "\n";
8669     pr "  list = PyList_New (%ss->len);\n" typ;
8670     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8671     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8672     pr "  return list;\n";
8673     pr "};\n";
8674     pr "\n"
8675   in
8676
8677   (* Structures, turned into Python dictionaries. *)
8678   List.iter (
8679     fun (typ, cols) ->
8680       pr "static PyObject *\n";
8681       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8682       pr "{\n";
8683       pr "  PyObject *dict;\n";
8684       pr "\n";
8685       pr "  dict = PyDict_New ();\n";
8686       List.iter (
8687         function
8688         | name, FString ->
8689             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8690             pr "                        PyString_FromString (%s->%s));\n"
8691               typ name
8692         | name, FBuffer ->
8693             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8694             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8695               typ name typ name
8696         | name, FUUID ->
8697             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8698             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8699               typ name
8700         | name, (FBytes|FUInt64) ->
8701             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8702             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8703               typ name
8704         | name, FInt64 ->
8705             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8706             pr "                        PyLong_FromLongLong (%s->%s));\n"
8707               typ name
8708         | name, FUInt32 ->
8709             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8710             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8711               typ name
8712         | name, FInt32 ->
8713             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8714             pr "                        PyLong_FromLong (%s->%s));\n"
8715               typ name
8716         | name, FOptPercent ->
8717             pr "  if (%s->%s >= 0)\n" typ name;
8718             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8719             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8720               typ name;
8721             pr "  else {\n";
8722             pr "    Py_INCREF (Py_None);\n";
8723             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8724             pr "  }\n"
8725         | name, FChar ->
8726             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8727             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8728       ) cols;
8729       pr "  return dict;\n";
8730       pr "};\n";
8731       pr "\n";
8732
8733   ) structs;
8734
8735   (* Emit a put_TYPE_list function definition only if that function is used. *)
8736   List.iter (
8737     function
8738     | typ, (RStructListOnly | RStructAndList) ->
8739         (* generate the function for typ *)
8740         emit_put_list_function typ
8741     | typ, _ -> () (* empty *)
8742   ) (rstructs_used_by all_functions);
8743
8744   (* Python wrapper functions. *)
8745   List.iter (
8746     fun (name, style, _, _, _, _, _) ->
8747       pr "static PyObject *\n";
8748       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8749       pr "{\n";
8750
8751       pr "  PyObject *py_g;\n";
8752       pr "  guestfs_h *g;\n";
8753       pr "  PyObject *py_r;\n";
8754
8755       let error_code =
8756         match fst style with
8757         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8758         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8759         | RConstString _ | RConstOptString _ ->
8760             pr "  const char *r;\n"; "NULL"
8761         | RString _ -> pr "  char *r;\n"; "NULL"
8762         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8763         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8764         | RStructList (_, typ) ->
8765             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8766         | RBufferOut _ ->
8767             pr "  char *r;\n";
8768             pr "  size_t size;\n";
8769             "NULL" in
8770
8771       List.iter (
8772         function
8773         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8774             pr "  const char *%s;\n" n
8775         | OptString n -> pr "  const char *%s;\n" n
8776         | StringList n | DeviceList n ->
8777             pr "  PyObject *py_%s;\n" n;
8778             pr "  char **%s;\n" n
8779         | Bool n -> pr "  int %s;\n" n
8780         | Int n -> pr "  int %s;\n" n
8781         | Int64 n -> pr "  long long %s;\n" n
8782       ) (snd style);
8783
8784       pr "\n";
8785
8786       (* Convert the parameters. *)
8787       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8788       List.iter (
8789         function
8790         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8791         | OptString _ -> pr "z"
8792         | StringList _ | DeviceList _ -> pr "O"
8793         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8794         | Int _ -> pr "i"
8795         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8796                              * emulate C's int/long/long long in Python?
8797                              *)
8798       ) (snd style);
8799       pr ":guestfs_%s\",\n" name;
8800       pr "                         &py_g";
8801       List.iter (
8802         function
8803         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8804         | OptString n -> pr ", &%s" n
8805         | StringList n | DeviceList n -> pr ", &py_%s" n
8806         | Bool n -> pr ", &%s" n
8807         | Int n -> pr ", &%s" n
8808         | Int64 n -> pr ", &%s" n
8809       ) (snd style);
8810
8811       pr "))\n";
8812       pr "    return NULL;\n";
8813
8814       pr "  g = get_handle (py_g);\n";
8815       List.iter (
8816         function
8817         | Pathname _ | Device _ | Dev_or_Path _ | String _
8818         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8819         | StringList n | DeviceList n ->
8820             pr "  %s = get_string_list (py_%s);\n" n n;
8821             pr "  if (!%s) return NULL;\n" n
8822       ) (snd style);
8823
8824       pr "\n";
8825
8826       pr "  r = guestfs_%s " name;
8827       generate_c_call_args ~handle:"g" style;
8828       pr ";\n";
8829
8830       List.iter (
8831         function
8832         | Pathname _ | Device _ | Dev_or_Path _ | String _
8833         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8834         | StringList n | DeviceList n ->
8835             pr "  free (%s);\n" n
8836       ) (snd style);
8837
8838       pr "  if (r == %s) {\n" error_code;
8839       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8840       pr "    return NULL;\n";
8841       pr "  }\n";
8842       pr "\n";
8843
8844       (match fst style with
8845        | RErr ->
8846            pr "  Py_INCREF (Py_None);\n";
8847            pr "  py_r = Py_None;\n"
8848        | RInt _
8849        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8850        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8851        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8852        | RConstOptString _ ->
8853            pr "  if (r)\n";
8854            pr "    py_r = PyString_FromString (r);\n";
8855            pr "  else {\n";
8856            pr "    Py_INCREF (Py_None);\n";
8857            pr "    py_r = Py_None;\n";
8858            pr "  }\n"
8859        | RString _ ->
8860            pr "  py_r = PyString_FromString (r);\n";
8861            pr "  free (r);\n"
8862        | RStringList _ ->
8863            pr "  py_r = put_string_list (r);\n";
8864            pr "  free_strings (r);\n"
8865        | RStruct (_, typ) ->
8866            pr "  py_r = put_%s (r);\n" typ;
8867            pr "  guestfs_free_%s (r);\n" typ
8868        | RStructList (_, typ) ->
8869            pr "  py_r = put_%s_list (r);\n" typ;
8870            pr "  guestfs_free_%s_list (r);\n" typ
8871        | RHashtable n ->
8872            pr "  py_r = put_table (r);\n";
8873            pr "  free_strings (r);\n"
8874        | RBufferOut _ ->
8875            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8876            pr "  free (r);\n"
8877       );
8878
8879       pr "  return py_r;\n";
8880       pr "}\n";
8881       pr "\n"
8882   ) all_functions;
8883
8884   (* Table of functions. *)
8885   pr "static PyMethodDef methods[] = {\n";
8886   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8887   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8888   List.iter (
8889     fun (name, _, _, _, _, _, _) ->
8890       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8891         name name
8892   ) all_functions;
8893   pr "  { NULL, NULL, 0, NULL }\n";
8894   pr "};\n";
8895   pr "\n";
8896
8897   (* Init function. *)
8898   pr "\
8899 void
8900 initlibguestfsmod (void)
8901 {
8902   static int initialized = 0;
8903
8904   if (initialized) return;
8905   Py_InitModule ((char *) \"libguestfsmod\", methods);
8906   initialized = 1;
8907 }
8908 "
8909
8910 (* Generate Python module. *)
8911 and generate_python_py () =
8912   generate_header HashStyle LGPLv2plus;
8913
8914   pr "\
8915 u\"\"\"Python bindings for libguestfs
8916
8917 import guestfs
8918 g = guestfs.GuestFS ()
8919 g.add_drive (\"guest.img\")
8920 g.launch ()
8921 parts = g.list_partitions ()
8922
8923 The guestfs module provides a Python binding to the libguestfs API
8924 for examining and modifying virtual machine disk images.
8925
8926 Amongst the things this is good for: making batch configuration
8927 changes to guests, getting disk used/free statistics (see also:
8928 virt-df), migrating between virtualization systems (see also:
8929 virt-p2v), performing partial backups, performing partial guest
8930 clones, cloning guests and changing registry/UUID/hostname info, and
8931 much else besides.
8932
8933 Libguestfs uses Linux kernel and qemu code, and can access any type of
8934 guest filesystem that Linux and qemu can, including but not limited
8935 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8936 schemes, qcow, qcow2, vmdk.
8937
8938 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8939 LVs, what filesystem is in each LV, etc.).  It can also run commands
8940 in the context of the guest.  Also you can access filesystems over
8941 FUSE.
8942
8943 Errors which happen while using the API are turned into Python
8944 RuntimeError exceptions.
8945
8946 To create a guestfs handle you usually have to perform the following
8947 sequence of calls:
8948
8949 # Create the handle, call add_drive at least once, and possibly
8950 # several times if the guest has multiple block devices:
8951 g = guestfs.GuestFS ()
8952 g.add_drive (\"guest.img\")
8953
8954 # Launch the qemu subprocess and wait for it to become ready:
8955 g.launch ()
8956
8957 # Now you can issue commands, for example:
8958 logvols = g.lvs ()
8959
8960 \"\"\"
8961
8962 import libguestfsmod
8963
8964 class GuestFS:
8965     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8966
8967     def __init__ (self):
8968         \"\"\"Create a new libguestfs handle.\"\"\"
8969         self._o = libguestfsmod.create ()
8970
8971     def __del__ (self):
8972         libguestfsmod.close (self._o)
8973
8974 ";
8975
8976   List.iter (
8977     fun (name, style, _, flags, _, _, longdesc) ->
8978       pr "    def %s " name;
8979       generate_py_call_args ~handle:"self" (snd style);
8980       pr ":\n";
8981
8982       if not (List.mem NotInDocs flags) then (
8983         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8984         let doc =
8985           match fst style with
8986           | RErr | RInt _ | RInt64 _ | RBool _
8987           | RConstOptString _ | RConstString _
8988           | RString _ | RBufferOut _ -> doc
8989           | RStringList _ ->
8990               doc ^ "\n\nThis function returns a list of strings."
8991           | RStruct (_, typ) ->
8992               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8993           | RStructList (_, typ) ->
8994               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8995           | RHashtable _ ->
8996               doc ^ "\n\nThis function returns a dictionary." in
8997         let doc =
8998           if List.mem ProtocolLimitWarning flags then
8999             doc ^ "\n\n" ^ protocol_limit_warning
9000           else doc in
9001         let doc =
9002           if List.mem DangerWillRobinson flags then
9003             doc ^ "\n\n" ^ danger_will_robinson
9004           else doc in
9005         let doc =
9006           match deprecation_notice flags with
9007           | None -> doc
9008           | Some txt -> doc ^ "\n\n" ^ txt in
9009         let doc = pod2text ~width:60 name doc in
9010         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9011         let doc = String.concat "\n        " doc in
9012         pr "        u\"\"\"%s\"\"\"\n" doc;
9013       );
9014       pr "        return libguestfsmod.%s " name;
9015       generate_py_call_args ~handle:"self._o" (snd style);
9016       pr "\n";
9017       pr "\n";
9018   ) all_functions
9019
9020 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9021 and generate_py_call_args ~handle args =
9022   pr "(%s" handle;
9023   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9024   pr ")"
9025
9026 (* Useful if you need the longdesc POD text as plain text.  Returns a
9027  * list of lines.
9028  *
9029  * Because this is very slow (the slowest part of autogeneration),
9030  * we memoize the results.
9031  *)
9032 and pod2text ~width name longdesc =
9033   let key = width, name, longdesc in
9034   try Hashtbl.find pod2text_memo key
9035   with Not_found ->
9036     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9037     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9038     close_out chan;
9039     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9040     let chan = open_process_in cmd in
9041     let lines = ref [] in
9042     let rec loop i =
9043       let line = input_line chan in
9044       if i = 1 then             (* discard the first line of output *)
9045         loop (i+1)
9046       else (
9047         let line = triml line in
9048         lines := line :: !lines;
9049         loop (i+1)
9050       ) in
9051     let lines = try loop 1 with End_of_file -> List.rev !lines in
9052     unlink filename;
9053     (match close_process_in chan with
9054      | WEXITED 0 -> ()
9055      | WEXITED i ->
9056          failwithf "pod2text: process exited with non-zero status (%d)" i
9057      | WSIGNALED i | WSTOPPED i ->
9058          failwithf "pod2text: process signalled or stopped by signal %d" i
9059     );
9060     Hashtbl.add pod2text_memo key lines;
9061     pod2text_memo_updated ();
9062     lines
9063
9064 (* Generate ruby bindings. *)
9065 and generate_ruby_c () =
9066   generate_header CStyle LGPLv2plus;
9067
9068   pr "\
9069 #include <stdio.h>
9070 #include <stdlib.h>
9071
9072 #include <ruby.h>
9073
9074 #include \"guestfs.h\"
9075
9076 #include \"extconf.h\"
9077
9078 /* For Ruby < 1.9 */
9079 #ifndef RARRAY_LEN
9080 #define RARRAY_LEN(r) (RARRAY((r))->len)
9081 #endif
9082
9083 static VALUE m_guestfs;                 /* guestfs module */
9084 static VALUE c_guestfs;                 /* guestfs_h handle */
9085 static VALUE e_Error;                   /* used for all errors */
9086
9087 static void ruby_guestfs_free (void *p)
9088 {
9089   if (!p) return;
9090   guestfs_close ((guestfs_h *) p);
9091 }
9092
9093 static VALUE ruby_guestfs_create (VALUE m)
9094 {
9095   guestfs_h *g;
9096
9097   g = guestfs_create ();
9098   if (!g)
9099     rb_raise (e_Error, \"failed to create guestfs handle\");
9100
9101   /* Don't print error messages to stderr by default. */
9102   guestfs_set_error_handler (g, NULL, NULL);
9103
9104   /* Wrap it, and make sure the close function is called when the
9105    * handle goes away.
9106    */
9107   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9108 }
9109
9110 static VALUE ruby_guestfs_close (VALUE gv)
9111 {
9112   guestfs_h *g;
9113   Data_Get_Struct (gv, guestfs_h, g);
9114
9115   ruby_guestfs_free (g);
9116   DATA_PTR (gv) = NULL;
9117
9118   return Qnil;
9119 }
9120
9121 ";
9122
9123   List.iter (
9124     fun (name, style, _, _, _, _, _) ->
9125       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9126       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9127       pr ")\n";
9128       pr "{\n";
9129       pr "  guestfs_h *g;\n";
9130       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9131       pr "  if (!g)\n";
9132       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9133         name;
9134       pr "\n";
9135
9136       List.iter (
9137         function
9138         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9139             pr "  Check_Type (%sv, T_STRING);\n" n;
9140             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9141             pr "  if (!%s)\n" n;
9142             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9143             pr "              \"%s\", \"%s\");\n" n name
9144         | OptString n ->
9145             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9146         | StringList n | DeviceList n ->
9147             pr "  char **%s;\n" n;
9148             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9149             pr "  {\n";
9150             pr "    int i, len;\n";
9151             pr "    len = RARRAY_LEN (%sv);\n" n;
9152             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9153               n;
9154             pr "    for (i = 0; i < len; ++i) {\n";
9155             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9156             pr "      %s[i] = StringValueCStr (v);\n" n;
9157             pr "    }\n";
9158             pr "    %s[len] = NULL;\n" n;
9159             pr "  }\n";
9160         | Bool n ->
9161             pr "  int %s = RTEST (%sv);\n" n n
9162         | Int n ->
9163             pr "  int %s = NUM2INT (%sv);\n" n n
9164         | Int64 n ->
9165             pr "  long long %s = NUM2LL (%sv);\n" n n
9166       ) (snd style);
9167       pr "\n";
9168
9169       let error_code =
9170         match fst style with
9171         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9172         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9173         | RConstString _ | RConstOptString _ ->
9174             pr "  const char *r;\n"; "NULL"
9175         | RString _ -> pr "  char *r;\n"; "NULL"
9176         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9177         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9178         | RStructList (_, typ) ->
9179             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9180         | RBufferOut _ ->
9181             pr "  char *r;\n";
9182             pr "  size_t size;\n";
9183             "NULL" in
9184       pr "\n";
9185
9186       pr "  r = guestfs_%s " name;
9187       generate_c_call_args ~handle:"g" style;
9188       pr ";\n";
9189
9190       List.iter (
9191         function
9192         | Pathname _ | Device _ | Dev_or_Path _ | String _
9193         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9194         | StringList n | DeviceList n ->
9195             pr "  free (%s);\n" n
9196       ) (snd style);
9197
9198       pr "  if (r == %s)\n" error_code;
9199       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9200       pr "\n";
9201
9202       (match fst style with
9203        | RErr ->
9204            pr "  return Qnil;\n"
9205        | RInt _ | RBool _ ->
9206            pr "  return INT2NUM (r);\n"
9207        | RInt64 _ ->
9208            pr "  return ULL2NUM (r);\n"
9209        | RConstString _ ->
9210            pr "  return rb_str_new2 (r);\n";
9211        | RConstOptString _ ->
9212            pr "  if (r)\n";
9213            pr "    return rb_str_new2 (r);\n";
9214            pr "  else\n";
9215            pr "    return Qnil;\n";
9216        | RString _ ->
9217            pr "  VALUE rv = rb_str_new2 (r);\n";
9218            pr "  free (r);\n";
9219            pr "  return rv;\n";
9220        | RStringList _ ->
9221            pr "  int i, len = 0;\n";
9222            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9223            pr "  VALUE rv = rb_ary_new2 (len);\n";
9224            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9225            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9226            pr "    free (r[i]);\n";
9227            pr "  }\n";
9228            pr "  free (r);\n";
9229            pr "  return rv;\n"
9230        | RStruct (_, typ) ->
9231            let cols = cols_of_struct typ in
9232            generate_ruby_struct_code typ cols
9233        | RStructList (_, typ) ->
9234            let cols = cols_of_struct typ in
9235            generate_ruby_struct_list_code typ cols
9236        | RHashtable _ ->
9237            pr "  VALUE rv = rb_hash_new ();\n";
9238            pr "  int i;\n";
9239            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9240            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9241            pr "    free (r[i]);\n";
9242            pr "    free (r[i+1]);\n";
9243            pr "  }\n";
9244            pr "  free (r);\n";
9245            pr "  return rv;\n"
9246        | RBufferOut _ ->
9247            pr "  VALUE rv = rb_str_new (r, size);\n";
9248            pr "  free (r);\n";
9249            pr "  return rv;\n";
9250       );
9251
9252       pr "}\n";
9253       pr "\n"
9254   ) all_functions;
9255
9256   pr "\
9257 /* Initialize the module. */
9258 void Init__guestfs ()
9259 {
9260   m_guestfs = rb_define_module (\"Guestfs\");
9261   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9262   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9263
9264   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9265   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9266
9267 ";
9268   (* Define the rest of the methods. *)
9269   List.iter (
9270     fun (name, style, _, _, _, _, _) ->
9271       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9272       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9273   ) all_functions;
9274
9275   pr "}\n"
9276
9277 (* Ruby code to return a struct. *)
9278 and generate_ruby_struct_code typ cols =
9279   pr "  VALUE rv = rb_hash_new ();\n";
9280   List.iter (
9281     function
9282     | name, FString ->
9283         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9284     | name, FBuffer ->
9285         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9286     | name, FUUID ->
9287         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9288     | name, (FBytes|FUInt64) ->
9289         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9290     | name, FInt64 ->
9291         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9292     | name, FUInt32 ->
9293         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9294     | name, FInt32 ->
9295         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9296     | name, FOptPercent ->
9297         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9298     | name, FChar -> (* XXX wrong? *)
9299         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9300   ) cols;
9301   pr "  guestfs_free_%s (r);\n" typ;
9302   pr "  return rv;\n"
9303
9304 (* Ruby code to return a struct list. *)
9305 and generate_ruby_struct_list_code typ cols =
9306   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9307   pr "  int i;\n";
9308   pr "  for (i = 0; i < r->len; ++i) {\n";
9309   pr "    VALUE hv = rb_hash_new ();\n";
9310   List.iter (
9311     function
9312     | name, FString ->
9313         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9314     | name, FBuffer ->
9315         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
9316     | name, FUUID ->
9317         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9318     | name, (FBytes|FUInt64) ->
9319         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9320     | name, FInt64 ->
9321         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9322     | name, FUInt32 ->
9323         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9324     | name, FInt32 ->
9325         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9326     | name, FOptPercent ->
9327         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9328     | name, FChar -> (* XXX wrong? *)
9329         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9330   ) cols;
9331   pr "    rb_ary_push (rv, hv);\n";
9332   pr "  }\n";
9333   pr "  guestfs_free_%s_list (r);\n" typ;
9334   pr "  return rv;\n"
9335
9336 (* Generate Java bindings GuestFS.java file. *)
9337 and generate_java_java () =
9338   generate_header CStyle LGPLv2plus;
9339
9340   pr "\
9341 package com.redhat.et.libguestfs;
9342
9343 import java.util.HashMap;
9344 import com.redhat.et.libguestfs.LibGuestFSException;
9345 import com.redhat.et.libguestfs.PV;
9346 import com.redhat.et.libguestfs.VG;
9347 import com.redhat.et.libguestfs.LV;
9348 import com.redhat.et.libguestfs.Stat;
9349 import com.redhat.et.libguestfs.StatVFS;
9350 import com.redhat.et.libguestfs.IntBool;
9351 import com.redhat.et.libguestfs.Dirent;
9352
9353 /**
9354  * The GuestFS object is a libguestfs handle.
9355  *
9356  * @author rjones
9357  */
9358 public class GuestFS {
9359   // Load the native code.
9360   static {
9361     System.loadLibrary (\"guestfs_jni\");
9362   }
9363
9364   /**
9365    * The native guestfs_h pointer.
9366    */
9367   long g;
9368
9369   /**
9370    * Create a libguestfs handle.
9371    *
9372    * @throws LibGuestFSException
9373    */
9374   public GuestFS () throws LibGuestFSException
9375   {
9376     g = _create ();
9377   }
9378   private native long _create () throws LibGuestFSException;
9379
9380   /**
9381    * Close a libguestfs handle.
9382    *
9383    * You can also leave handles to be collected by the garbage
9384    * collector, but this method ensures that the resources used
9385    * by the handle are freed up immediately.  If you call any
9386    * other methods after closing the handle, you will get an
9387    * exception.
9388    *
9389    * @throws LibGuestFSException
9390    */
9391   public void close () throws LibGuestFSException
9392   {
9393     if (g != 0)
9394       _close (g);
9395     g = 0;
9396   }
9397   private native void _close (long g) throws LibGuestFSException;
9398
9399   public void finalize () throws LibGuestFSException
9400   {
9401     close ();
9402   }
9403
9404 ";
9405
9406   List.iter (
9407     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9408       if not (List.mem NotInDocs flags); then (
9409         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9410         let doc =
9411           if List.mem ProtocolLimitWarning flags then
9412             doc ^ "\n\n" ^ protocol_limit_warning
9413           else doc in
9414         let doc =
9415           if List.mem DangerWillRobinson flags then
9416             doc ^ "\n\n" ^ danger_will_robinson
9417           else doc in
9418         let doc =
9419           match deprecation_notice flags with
9420           | None -> doc
9421           | Some txt -> doc ^ "\n\n" ^ txt in
9422         let doc = pod2text ~width:60 name doc in
9423         let doc = List.map (            (* RHBZ#501883 *)
9424           function
9425           | "" -> "<p>"
9426           | nonempty -> nonempty
9427         ) doc in
9428         let doc = String.concat "\n   * " doc in
9429
9430         pr "  /**\n";
9431         pr "   * %s\n" shortdesc;
9432         pr "   * <p>\n";
9433         pr "   * %s\n" doc;
9434         pr "   * @throws LibGuestFSException\n";
9435         pr "   */\n";
9436         pr "  ";
9437       );
9438       generate_java_prototype ~public:true ~semicolon:false name style;
9439       pr "\n";
9440       pr "  {\n";
9441       pr "    if (g == 0)\n";
9442       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9443         name;
9444       pr "    ";
9445       if fst style <> RErr then pr "return ";
9446       pr "_%s " name;
9447       generate_java_call_args ~handle:"g" (snd style);
9448       pr ";\n";
9449       pr "  }\n";
9450       pr "  ";
9451       generate_java_prototype ~privat:true ~native:true name style;
9452       pr "\n";
9453       pr "\n";
9454   ) all_functions;
9455
9456   pr "}\n"
9457
9458 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9459 and generate_java_call_args ~handle args =
9460   pr "(%s" handle;
9461   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9462   pr ")"
9463
9464 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9465     ?(semicolon=true) name style =
9466   if privat then pr "private ";
9467   if public then pr "public ";
9468   if native then pr "native ";
9469
9470   (* return type *)
9471   (match fst style with
9472    | RErr -> pr "void ";
9473    | RInt _ -> pr "int ";
9474    | RInt64 _ -> pr "long ";
9475    | RBool _ -> pr "boolean ";
9476    | RConstString _ | RConstOptString _ | RString _
9477    | RBufferOut _ -> pr "String ";
9478    | RStringList _ -> pr "String[] ";
9479    | RStruct (_, typ) ->
9480        let name = java_name_of_struct typ in
9481        pr "%s " name;
9482    | RStructList (_, typ) ->
9483        let name = java_name_of_struct typ in
9484        pr "%s[] " name;
9485    | RHashtable _ -> pr "HashMap<String,String> ";
9486   );
9487
9488   if native then pr "_%s " name else pr "%s " name;
9489   pr "(";
9490   let needs_comma = ref false in
9491   if native then (
9492     pr "long g";
9493     needs_comma := true
9494   );
9495
9496   (* args *)
9497   List.iter (
9498     fun arg ->
9499       if !needs_comma then pr ", ";
9500       needs_comma := true;
9501
9502       match arg with
9503       | Pathname n
9504       | Device n | Dev_or_Path n
9505       | String n
9506       | OptString n
9507       | FileIn n
9508       | FileOut n ->
9509           pr "String %s" n
9510       | StringList n | DeviceList n ->
9511           pr "String[] %s" n
9512       | Bool n ->
9513           pr "boolean %s" n
9514       | Int n ->
9515           pr "int %s" n
9516       | Int64 n ->
9517           pr "long %s" n
9518   ) (snd style);
9519
9520   pr ")\n";
9521   pr "    throws LibGuestFSException";
9522   if semicolon then pr ";"
9523
9524 and generate_java_struct jtyp cols () =
9525   generate_header CStyle LGPLv2plus;
9526
9527   pr "\
9528 package com.redhat.et.libguestfs;
9529
9530 /**
9531  * Libguestfs %s structure.
9532  *
9533  * @author rjones
9534  * @see GuestFS
9535  */
9536 public class %s {
9537 " jtyp jtyp;
9538
9539   List.iter (
9540     function
9541     | name, FString
9542     | name, FUUID
9543     | name, FBuffer -> pr "  public String %s;\n" name
9544     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9545     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9546     | name, FChar -> pr "  public char %s;\n" name
9547     | name, FOptPercent ->
9548         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9549         pr "  public float %s;\n" name
9550   ) cols;
9551
9552   pr "}\n"
9553
9554 and generate_java_c () =
9555   generate_header CStyle LGPLv2plus;
9556
9557   pr "\
9558 #include <stdio.h>
9559 #include <stdlib.h>
9560 #include <string.h>
9561
9562 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9563 #include \"guestfs.h\"
9564
9565 /* Note that this function returns.  The exception is not thrown
9566  * until after the wrapper function returns.
9567  */
9568 static void
9569 throw_exception (JNIEnv *env, const char *msg)
9570 {
9571   jclass cl;
9572   cl = (*env)->FindClass (env,
9573                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9574   (*env)->ThrowNew (env, cl, msg);
9575 }
9576
9577 JNIEXPORT jlong JNICALL
9578 Java_com_redhat_et_libguestfs_GuestFS__1create
9579   (JNIEnv *env, jobject obj)
9580 {
9581   guestfs_h *g;
9582
9583   g = guestfs_create ();
9584   if (g == NULL) {
9585     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9586     return 0;
9587   }
9588   guestfs_set_error_handler (g, NULL, NULL);
9589   return (jlong) (long) g;
9590 }
9591
9592 JNIEXPORT void JNICALL
9593 Java_com_redhat_et_libguestfs_GuestFS__1close
9594   (JNIEnv *env, jobject obj, jlong jg)
9595 {
9596   guestfs_h *g = (guestfs_h *) (long) jg;
9597   guestfs_close (g);
9598 }
9599
9600 ";
9601
9602   List.iter (
9603     fun (name, style, _, _, _, _, _) ->
9604       pr "JNIEXPORT ";
9605       (match fst style with
9606        | RErr -> pr "void ";
9607        | RInt _ -> pr "jint ";
9608        | RInt64 _ -> pr "jlong ";
9609        | RBool _ -> pr "jboolean ";
9610        | RConstString _ | RConstOptString _ | RString _
9611        | RBufferOut _ -> pr "jstring ";
9612        | RStruct _ | RHashtable _ ->
9613            pr "jobject ";
9614        | RStringList _ | RStructList _ ->
9615            pr "jobjectArray ";
9616       );
9617       pr "JNICALL\n";
9618       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9619       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9620       pr "\n";
9621       pr "  (JNIEnv *env, jobject obj, jlong jg";
9622       List.iter (
9623         function
9624         | Pathname n
9625         | Device n | Dev_or_Path n
9626         | String n
9627         | OptString n
9628         | FileIn n
9629         | FileOut n ->
9630             pr ", jstring j%s" n
9631         | StringList n | DeviceList n ->
9632             pr ", jobjectArray j%s" n
9633         | Bool n ->
9634             pr ", jboolean j%s" n
9635         | Int n ->
9636             pr ", jint j%s" n
9637         | Int64 n ->
9638             pr ", jlong j%s" n
9639       ) (snd style);
9640       pr ")\n";
9641       pr "{\n";
9642       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9643       let error_code, no_ret =
9644         match fst style with
9645         | RErr -> pr "  int r;\n"; "-1", ""
9646         | RBool _
9647         | RInt _ -> pr "  int r;\n"; "-1", "0"
9648         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9649         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9650         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9651         | RString _ ->
9652             pr "  jstring jr;\n";
9653             pr "  char *r;\n"; "NULL", "NULL"
9654         | RStringList _ ->
9655             pr "  jobjectArray jr;\n";
9656             pr "  int r_len;\n";
9657             pr "  jclass cl;\n";
9658             pr "  jstring jstr;\n";
9659             pr "  char **r;\n"; "NULL", "NULL"
9660         | RStruct (_, typ) ->
9661             pr "  jobject jr;\n";
9662             pr "  jclass cl;\n";
9663             pr "  jfieldID fl;\n";
9664             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9665         | RStructList (_, typ) ->
9666             pr "  jobjectArray jr;\n";
9667             pr "  jclass cl;\n";
9668             pr "  jfieldID fl;\n";
9669             pr "  jobject jfl;\n";
9670             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9671         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9672         | RBufferOut _ ->
9673             pr "  jstring jr;\n";
9674             pr "  char *r;\n";
9675             pr "  size_t size;\n";
9676             "NULL", "NULL" in
9677       List.iter (
9678         function
9679         | Pathname n
9680         | Device n | Dev_or_Path n
9681         | String n
9682         | OptString n
9683         | FileIn n
9684         | FileOut n ->
9685             pr "  const char *%s;\n" n
9686         | StringList n | DeviceList n ->
9687             pr "  int %s_len;\n" n;
9688             pr "  const char **%s;\n" n
9689         | Bool n
9690         | Int n ->
9691             pr "  int %s;\n" n
9692         | Int64 n ->
9693             pr "  int64_t %s;\n" n
9694       ) (snd style);
9695
9696       let needs_i =
9697         (match fst style with
9698          | RStringList _ | RStructList _ -> true
9699          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9700          | RConstOptString _
9701          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9702           List.exists (function
9703                        | StringList _ -> true
9704                        | DeviceList _ -> true
9705                        | _ -> false) (snd style) in
9706       if needs_i then
9707         pr "  int i;\n";
9708
9709       pr "\n";
9710
9711       (* Get 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 "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9720         | OptString n ->
9721             (* This is completely undocumented, but Java null becomes
9722              * a NULL parameter.
9723              *)
9724             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9725         | StringList n | DeviceList n ->
9726             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9727             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9728             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9729             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9730               n;
9731             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9732             pr "  }\n";
9733             pr "  %s[%s_len] = NULL;\n" n n;
9734         | Bool n
9735         | Int n
9736         | Int64 n ->
9737             pr "  %s = j%s;\n" n n
9738       ) (snd style);
9739
9740       (* Make the call. *)
9741       pr "  r = guestfs_%s " name;
9742       generate_c_call_args ~handle:"g" style;
9743       pr ";\n";
9744
9745       (* Release the parameters. *)
9746       List.iter (
9747         function
9748         | Pathname n
9749         | Device n | Dev_or_Path n
9750         | String n
9751         | FileIn n
9752         | FileOut n ->
9753             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9754         | OptString n ->
9755             pr "  if (j%s)\n" n;
9756             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9757         | StringList n | DeviceList n ->
9758             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9759             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9760               n;
9761             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9762             pr "  }\n";
9763             pr "  free (%s);\n" n
9764         | Bool n
9765         | Int n
9766         | Int64 n -> ()
9767       ) (snd style);
9768
9769       (* Check for errors. *)
9770       pr "  if (r == %s) {\n" error_code;
9771       pr "    throw_exception (env, guestfs_last_error (g));\n";
9772       pr "    return %s;\n" no_ret;
9773       pr "  }\n";
9774
9775       (* Return value. *)
9776       (match fst style with
9777        | RErr -> ()
9778        | RInt _ -> pr "  return (jint) r;\n"
9779        | RBool _ -> pr "  return (jboolean) r;\n"
9780        | RInt64 _ -> pr "  return (jlong) r;\n"
9781        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9782        | RConstOptString _ ->
9783            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9784        | RString _ ->
9785            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9786            pr "  free (r);\n";
9787            pr "  return jr;\n"
9788        | RStringList _ ->
9789            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9790            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9791            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9792            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9793            pr "  for (i = 0; i < r_len; ++i) {\n";
9794            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9795            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9796            pr "    free (r[i]);\n";
9797            pr "  }\n";
9798            pr "  free (r);\n";
9799            pr "  return jr;\n"
9800        | RStruct (_, typ) ->
9801            let jtyp = java_name_of_struct typ in
9802            let cols = cols_of_struct typ in
9803            generate_java_struct_return typ jtyp cols
9804        | RStructList (_, typ) ->
9805            let jtyp = java_name_of_struct typ in
9806            let cols = cols_of_struct typ in
9807            generate_java_struct_list_return typ jtyp cols
9808        | RHashtable _ ->
9809            (* XXX *)
9810            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9811            pr "  return NULL;\n"
9812        | RBufferOut _ ->
9813            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9814            pr "  free (r);\n";
9815            pr "  return jr;\n"
9816       );
9817
9818       pr "}\n";
9819       pr "\n"
9820   ) all_functions
9821
9822 and generate_java_struct_return typ jtyp cols =
9823   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9824   pr "  jr = (*env)->AllocObject (env, cl);\n";
9825   List.iter (
9826     function
9827     | name, FString ->
9828         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9829         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9830     | name, FUUID ->
9831         pr "  {\n";
9832         pr "    char s[33];\n";
9833         pr "    memcpy (s, r->%s, 32);\n" name;
9834         pr "    s[32] = 0;\n";
9835         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9836         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9837         pr "  }\n";
9838     | name, FBuffer ->
9839         pr "  {\n";
9840         pr "    int len = r->%s_len;\n" name;
9841         pr "    char s[len+1];\n";
9842         pr "    memcpy (s, r->%s, len);\n" name;
9843         pr "    s[len] = 0;\n";
9844         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9845         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9846         pr "  }\n";
9847     | name, (FBytes|FUInt64|FInt64) ->
9848         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9849         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9850     | name, (FUInt32|FInt32) ->
9851         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9852         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9853     | name, FOptPercent ->
9854         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9855         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9856     | name, FChar ->
9857         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9858         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9859   ) cols;
9860   pr "  free (r);\n";
9861   pr "  return jr;\n"
9862
9863 and generate_java_struct_list_return typ jtyp cols =
9864   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9865   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9866   pr "  for (i = 0; i < r->len; ++i) {\n";
9867   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9868   List.iter (
9869     function
9870     | name, FString ->
9871         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9872         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9873     | name, FUUID ->
9874         pr "    {\n";
9875         pr "      char s[33];\n";
9876         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9877         pr "      s[32] = 0;\n";
9878         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9879         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9880         pr "    }\n";
9881     | name, FBuffer ->
9882         pr "    {\n";
9883         pr "      int len = r->val[i].%s_len;\n" name;
9884         pr "      char s[len+1];\n";
9885         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9886         pr "      s[len] = 0;\n";
9887         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9888         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9889         pr "    }\n";
9890     | name, (FBytes|FUInt64|FInt64) ->
9891         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9892         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9893     | name, (FUInt32|FInt32) ->
9894         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9895         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9896     | name, FOptPercent ->
9897         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9898         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9899     | name, FChar ->
9900         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9901         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9902   ) cols;
9903   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9904   pr "  }\n";
9905   pr "  guestfs_free_%s_list (r);\n" typ;
9906   pr "  return jr;\n"
9907
9908 and generate_java_makefile_inc () =
9909   generate_header HashStyle GPLv2plus;
9910
9911   pr "java_built_sources = \\\n";
9912   List.iter (
9913     fun (typ, jtyp) ->
9914         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9915   ) java_structs;
9916   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9917
9918 and generate_haskell_hs () =
9919   generate_header HaskellStyle LGPLv2plus;
9920
9921   (* XXX We only know how to generate partial FFI for Haskell
9922    * at the moment.  Please help out!
9923    *)
9924   let can_generate style =
9925     match style with
9926     | RErr, _
9927     | RInt _, _
9928     | RInt64 _, _ -> true
9929     | RBool _, _
9930     | RConstString _, _
9931     | RConstOptString _, _
9932     | RString _, _
9933     | RStringList _, _
9934     | RStruct _, _
9935     | RStructList _, _
9936     | RHashtable _, _
9937     | RBufferOut _, _ -> false in
9938
9939   pr "\
9940 {-# INCLUDE <guestfs.h> #-}
9941 {-# LANGUAGE ForeignFunctionInterface #-}
9942
9943 module Guestfs (
9944   create";
9945
9946   (* List out the names of the actions we want to export. *)
9947   List.iter (
9948     fun (name, style, _, _, _, _, _) ->
9949       if can_generate style then pr ",\n  %s" name
9950   ) all_functions;
9951
9952   pr "
9953   ) where
9954
9955 -- Unfortunately some symbols duplicate ones already present
9956 -- in Prelude.  We don't know which, so we hard-code a list
9957 -- here.
9958 import Prelude hiding (truncate)
9959
9960 import Foreign
9961 import Foreign.C
9962 import Foreign.C.Types
9963 import IO
9964 import Control.Exception
9965 import Data.Typeable
9966
9967 data GuestfsS = GuestfsS            -- represents the opaque C struct
9968 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9969 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9970
9971 -- XXX define properly later XXX
9972 data PV = PV
9973 data VG = VG
9974 data LV = LV
9975 data IntBool = IntBool
9976 data Stat = Stat
9977 data StatVFS = StatVFS
9978 data Hashtable = Hashtable
9979
9980 foreign import ccall unsafe \"guestfs_create\" c_create
9981   :: IO GuestfsP
9982 foreign import ccall unsafe \"&guestfs_close\" c_close
9983   :: FunPtr (GuestfsP -> IO ())
9984 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9985   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9986
9987 create :: IO GuestfsH
9988 create = do
9989   p <- c_create
9990   c_set_error_handler p nullPtr nullPtr
9991   h <- newForeignPtr c_close p
9992   return h
9993
9994 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9995   :: GuestfsP -> IO CString
9996
9997 -- last_error :: GuestfsH -> IO (Maybe String)
9998 -- last_error h = do
9999 --   str <- withForeignPtr h (\\p -> c_last_error p)
10000 --   maybePeek peekCString str
10001
10002 last_error :: GuestfsH -> IO (String)
10003 last_error h = do
10004   str <- withForeignPtr h (\\p -> c_last_error p)
10005   if (str == nullPtr)
10006     then return \"no error\"
10007     else peekCString str
10008
10009 ";
10010
10011   (* Generate wrappers for each foreign function. *)
10012   List.iter (
10013     fun (name, style, _, _, _, _, _) ->
10014       if can_generate style then (
10015         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10016         pr "  :: ";
10017         generate_haskell_prototype ~handle:"GuestfsP" style;
10018         pr "\n";
10019         pr "\n";
10020         pr "%s :: " name;
10021         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10022         pr "\n";
10023         pr "%s %s = do\n" name
10024           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10025         pr "  r <- ";
10026         (* Convert pointer arguments using with* functions. *)
10027         List.iter (
10028           function
10029           | FileIn n
10030           | FileOut n
10031           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10032           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10033           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10034           | Bool _ | Int _ | Int64 _ -> ()
10035         ) (snd style);
10036         (* Convert integer arguments. *)
10037         let args =
10038           List.map (
10039             function
10040             | Bool n -> sprintf "(fromBool %s)" n
10041             | Int n -> sprintf "(fromIntegral %s)" n
10042             | Int64 n -> sprintf "(fromIntegral %s)" n
10043             | FileIn n | FileOut n
10044             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10045           ) (snd style) in
10046         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10047           (String.concat " " ("p" :: args));
10048         (match fst style with
10049          | RErr | RInt _ | RInt64 _ | RBool _ ->
10050              pr "  if (r == -1)\n";
10051              pr "    then do\n";
10052              pr "      err <- last_error h\n";
10053              pr "      fail err\n";
10054          | RConstString _ | RConstOptString _ | RString _
10055          | RStringList _ | RStruct _
10056          | RStructList _ | RHashtable _ | RBufferOut _ ->
10057              pr "  if (r == nullPtr)\n";
10058              pr "    then do\n";
10059              pr "      err <- last_error h\n";
10060              pr "      fail err\n";
10061         );
10062         (match fst style with
10063          | RErr ->
10064              pr "    else return ()\n"
10065          | RInt _ ->
10066              pr "    else return (fromIntegral r)\n"
10067          | RInt64 _ ->
10068              pr "    else return (fromIntegral r)\n"
10069          | RBool _ ->
10070              pr "    else return (toBool r)\n"
10071          | RConstString _
10072          | RConstOptString _
10073          | RString _
10074          | RStringList _
10075          | RStruct _
10076          | RStructList _
10077          | RHashtable _
10078          | RBufferOut _ ->
10079              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10080         );
10081         pr "\n";
10082       )
10083   ) all_functions
10084
10085 and generate_haskell_prototype ~handle ?(hs = false) style =
10086   pr "%s -> " handle;
10087   let string = if hs then "String" else "CString" in
10088   let int = if hs then "Int" else "CInt" in
10089   let bool = if hs then "Bool" else "CInt" in
10090   let int64 = if hs then "Integer" else "Int64" in
10091   List.iter (
10092     fun arg ->
10093       (match arg with
10094        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10095        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10096        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10097        | Bool _ -> pr "%s" bool
10098        | Int _ -> pr "%s" int
10099        | Int64 _ -> pr "%s" int
10100        | FileIn _ -> pr "%s" string
10101        | FileOut _ -> pr "%s" string
10102       );
10103       pr " -> ";
10104   ) (snd style);
10105   pr "IO (";
10106   (match fst style with
10107    | RErr -> if not hs then pr "CInt"
10108    | RInt _ -> pr "%s" int
10109    | RInt64 _ -> pr "%s" int64
10110    | RBool _ -> pr "%s" bool
10111    | RConstString _ -> pr "%s" string
10112    | RConstOptString _ -> pr "Maybe %s" string
10113    | RString _ -> pr "%s" string
10114    | RStringList _ -> pr "[%s]" string
10115    | RStruct (_, typ) ->
10116        let name = java_name_of_struct typ in
10117        pr "%s" name
10118    | RStructList (_, typ) ->
10119        let name = java_name_of_struct typ in
10120        pr "[%s]" name
10121    | RHashtable _ -> pr "Hashtable"
10122    | RBufferOut _ -> pr "%s" string
10123   );
10124   pr ")"
10125
10126 and generate_csharp () =
10127   generate_header CPlusPlusStyle LGPLv2plus;
10128
10129   (* XXX Make this configurable by the C# assembly users. *)
10130   let library = "libguestfs.so.0" in
10131
10132   pr "\
10133 // These C# bindings are highly experimental at present.
10134 //
10135 // Firstly they only work on Linux (ie. Mono).  In order to get them
10136 // to work on Windows (ie. .Net) you would need to port the library
10137 // itself to Windows first.
10138 //
10139 // The second issue is that some calls are known to be incorrect and
10140 // can cause Mono to segfault.  Particularly: calls which pass or
10141 // return string[], or return any structure value.  This is because
10142 // we haven't worked out the correct way to do this from C#.
10143 //
10144 // The third issue is that when compiling you get a lot of warnings.
10145 // We are not sure whether the warnings are important or not.
10146 //
10147 // Fourthly we do not routinely build or test these bindings as part
10148 // of the make && make check cycle, which means that regressions might
10149 // go unnoticed.
10150 //
10151 // Suggestions and patches are welcome.
10152
10153 // To compile:
10154 //
10155 // gmcs Libguestfs.cs
10156 // mono Libguestfs.exe
10157 //
10158 // (You'll probably want to add a Test class / static main function
10159 // otherwise this won't do anything useful).
10160
10161 using System;
10162 using System.IO;
10163 using System.Runtime.InteropServices;
10164 using System.Runtime.Serialization;
10165 using System.Collections;
10166
10167 namespace Guestfs
10168 {
10169   class Error : System.ApplicationException
10170   {
10171     public Error (string message) : base (message) {}
10172     protected Error (SerializationInfo info, StreamingContext context) {}
10173   }
10174
10175   class Guestfs
10176   {
10177     IntPtr _handle;
10178
10179     [DllImport (\"%s\")]
10180     static extern IntPtr guestfs_create ();
10181
10182     public Guestfs ()
10183     {
10184       _handle = guestfs_create ();
10185       if (_handle == IntPtr.Zero)
10186         throw new Error (\"could not create guestfs handle\");
10187     }
10188
10189     [DllImport (\"%s\")]
10190     static extern void guestfs_close (IntPtr h);
10191
10192     ~Guestfs ()
10193     {
10194       guestfs_close (_handle);
10195     }
10196
10197     [DllImport (\"%s\")]
10198     static extern string guestfs_last_error (IntPtr h);
10199
10200 " library library library;
10201
10202   (* Generate C# structure bindings.  We prefix struct names with
10203    * underscore because C# cannot have conflicting struct names and
10204    * method names (eg. "class stat" and "stat").
10205    *)
10206   List.iter (
10207     fun (typ, cols) ->
10208       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10209       pr "    public class _%s {\n" typ;
10210       List.iter (
10211         function
10212         | name, FChar -> pr "      char %s;\n" name
10213         | name, FString -> pr "      string %s;\n" name
10214         | name, FBuffer ->
10215             pr "      uint %s_len;\n" name;
10216             pr "      string %s;\n" name
10217         | name, FUUID ->
10218             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10219             pr "      string %s;\n" name
10220         | name, FUInt32 -> pr "      uint %s;\n" name
10221         | name, FInt32 -> pr "      int %s;\n" name
10222         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10223         | name, FInt64 -> pr "      long %s;\n" name
10224         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10225       ) cols;
10226       pr "    }\n";
10227       pr "\n"
10228   ) structs;
10229
10230   (* Generate C# function bindings. *)
10231   List.iter (
10232     fun (name, style, _, _, _, shortdesc, _) ->
10233       let rec csharp_return_type () =
10234         match fst style with
10235         | RErr -> "void"
10236         | RBool n -> "bool"
10237         | RInt n -> "int"
10238         | RInt64 n -> "long"
10239         | RConstString n
10240         | RConstOptString n
10241         | RString n
10242         | RBufferOut n -> "string"
10243         | RStruct (_,n) -> "_" ^ n
10244         | RHashtable n -> "Hashtable"
10245         | RStringList n -> "string[]"
10246         | RStructList (_,n) -> sprintf "_%s[]" n
10247
10248       and c_return_type () =
10249         match fst style with
10250         | RErr
10251         | RBool _
10252         | RInt _ -> "int"
10253         | RInt64 _ -> "long"
10254         | RConstString _
10255         | RConstOptString _
10256         | RString _
10257         | RBufferOut _ -> "string"
10258         | RStruct (_,n) -> "_" ^ n
10259         | RHashtable _
10260         | RStringList _ -> "string[]"
10261         | RStructList (_,n) -> sprintf "_%s[]" n
10262
10263       and c_error_comparison () =
10264         match fst style with
10265         | RErr
10266         | RBool _
10267         | RInt _
10268         | RInt64 _ -> "== -1"
10269         | RConstString _
10270         | RConstOptString _
10271         | RString _
10272         | RBufferOut _
10273         | RStruct (_,_)
10274         | RHashtable _
10275         | RStringList _
10276         | RStructList (_,_) -> "== null"
10277
10278       and generate_extern_prototype () =
10279         pr "    static extern %s guestfs_%s (IntPtr h"
10280           (c_return_type ()) name;
10281         List.iter (
10282           function
10283           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10284           | FileIn n | FileOut n ->
10285               pr ", [In] string %s" n
10286           | StringList n | DeviceList n ->
10287               pr ", [In] string[] %s" n
10288           | Bool n ->
10289               pr ", bool %s" n
10290           | Int n ->
10291               pr ", int %s" n
10292           | Int64 n ->
10293               pr ", long %s" n
10294         ) (snd style);
10295         pr ");\n"
10296
10297       and generate_public_prototype () =
10298         pr "    public %s %s (" (csharp_return_type ()) name;
10299         let comma = ref false in
10300         let next () =
10301           if !comma then pr ", ";
10302           comma := true
10303         in
10304         List.iter (
10305           function
10306           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10307           | FileIn n | FileOut n ->
10308               next (); pr "string %s" n
10309           | StringList n | DeviceList n ->
10310               next (); pr "string[] %s" n
10311           | Bool n ->
10312               next (); pr "bool %s" n
10313           | Int n ->
10314               next (); pr "int %s" n
10315           | Int64 n ->
10316               next (); pr "long %s" n
10317         ) (snd style);
10318         pr ")\n"
10319
10320       and generate_call () =
10321         pr "guestfs_%s (_handle" name;
10322         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10323         pr ");\n";
10324       in
10325
10326       pr "    [DllImport (\"%s\")]\n" library;
10327       generate_extern_prototype ();
10328       pr "\n";
10329       pr "    /// <summary>\n";
10330       pr "    /// %s\n" shortdesc;
10331       pr "    /// </summary>\n";
10332       generate_public_prototype ();
10333       pr "    {\n";
10334       pr "      %s r;\n" (c_return_type ());
10335       pr "      r = ";
10336       generate_call ();
10337       pr "      if (r %s)\n" (c_error_comparison ());
10338       pr "        throw new Error (guestfs_last_error (_handle));\n";
10339       (match fst style with
10340        | RErr -> ()
10341        | RBool _ ->
10342            pr "      return r != 0 ? true : false;\n"
10343        | RHashtable _ ->
10344            pr "      Hashtable rr = new Hashtable ();\n";
10345            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10346            pr "        rr.Add (r[i], r[i+1]);\n";
10347            pr "      return rr;\n"
10348        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10349        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10350        | RStructList _ ->
10351            pr "      return r;\n"
10352       );
10353       pr "    }\n";
10354       pr "\n";
10355   ) all_functions_sorted;
10356
10357   pr "  }
10358 }
10359 "
10360
10361 and generate_bindtests () =
10362   generate_header CStyle LGPLv2plus;
10363
10364   pr "\
10365 #include <stdio.h>
10366 #include <stdlib.h>
10367 #include <inttypes.h>
10368 #include <string.h>
10369
10370 #include \"guestfs.h\"
10371 #include \"guestfs-internal.h\"
10372 #include \"guestfs-internal-actions.h\"
10373 #include \"guestfs_protocol.h\"
10374
10375 #define error guestfs_error
10376 #define safe_calloc guestfs_safe_calloc
10377 #define safe_malloc guestfs_safe_malloc
10378
10379 static void
10380 print_strings (char *const *argv)
10381 {
10382   int argc;
10383
10384   printf (\"[\");
10385   for (argc = 0; argv[argc] != NULL; ++argc) {
10386     if (argc > 0) printf (\", \");
10387     printf (\"\\\"%%s\\\"\", argv[argc]);
10388   }
10389   printf (\"]\\n\");
10390 }
10391
10392 /* The test0 function prints its parameters to stdout. */
10393 ";
10394
10395   let test0, tests =
10396     match test_functions with
10397     | [] -> assert false
10398     | test0 :: tests -> test0, tests in
10399
10400   let () =
10401     let (name, style, _, _, _, _, _) = test0 in
10402     generate_prototype ~extern:false ~semicolon:false ~newline:true
10403       ~handle:"g" ~prefix:"guestfs__" name style;
10404     pr "{\n";
10405     List.iter (
10406       function
10407       | Pathname n
10408       | Device n | Dev_or_Path n
10409       | String n
10410       | FileIn n
10411       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10412       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10413       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10414       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10415       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10416       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10417     ) (snd style);
10418     pr "  /* Java changes stdout line buffering so we need this: */\n";
10419     pr "  fflush (stdout);\n";
10420     pr "  return 0;\n";
10421     pr "}\n";
10422     pr "\n" in
10423
10424   List.iter (
10425     fun (name, style, _, _, _, _, _) ->
10426       if String.sub name (String.length name - 3) 3 <> "err" then (
10427         pr "/* Test normal return. */\n";
10428         generate_prototype ~extern:false ~semicolon:false ~newline:true
10429           ~handle:"g" ~prefix:"guestfs__" name style;
10430         pr "{\n";
10431         (match fst style with
10432          | RErr ->
10433              pr "  return 0;\n"
10434          | RInt _ ->
10435              pr "  int r;\n";
10436              pr "  sscanf (val, \"%%d\", &r);\n";
10437              pr "  return r;\n"
10438          | RInt64 _ ->
10439              pr "  int64_t r;\n";
10440              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10441              pr "  return r;\n"
10442          | RBool _ ->
10443              pr "  return STREQ (val, \"true\");\n"
10444          | RConstString _
10445          | RConstOptString _ ->
10446              (* Can't return the input string here.  Return a static
10447               * string so we ensure we get a segfault if the caller
10448               * tries to free it.
10449               *)
10450              pr "  return \"static string\";\n"
10451          | RString _ ->
10452              pr "  return strdup (val);\n"
10453          | RStringList _ ->
10454              pr "  char **strs;\n";
10455              pr "  int n, i;\n";
10456              pr "  sscanf (val, \"%%d\", &n);\n";
10457              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10458              pr "  for (i = 0; i < n; ++i) {\n";
10459              pr "    strs[i] = safe_malloc (g, 16);\n";
10460              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10461              pr "  }\n";
10462              pr "  strs[n] = NULL;\n";
10463              pr "  return strs;\n"
10464          | RStruct (_, typ) ->
10465              pr "  struct guestfs_%s *r;\n" typ;
10466              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10467              pr "  return r;\n"
10468          | RStructList (_, typ) ->
10469              pr "  struct guestfs_%s_list *r;\n" typ;
10470              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10471              pr "  sscanf (val, \"%%d\", &r->len);\n";
10472              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10473              pr "  return r;\n"
10474          | RHashtable _ ->
10475              pr "  char **strs;\n";
10476              pr "  int n, i;\n";
10477              pr "  sscanf (val, \"%%d\", &n);\n";
10478              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10479              pr "  for (i = 0; i < n; ++i) {\n";
10480              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10481              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10482              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10483              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10484              pr "  }\n";
10485              pr "  strs[n*2] = NULL;\n";
10486              pr "  return strs;\n"
10487          | RBufferOut _ ->
10488              pr "  return strdup (val);\n"
10489         );
10490         pr "}\n";
10491         pr "\n"
10492       ) else (
10493         pr "/* Test error return. */\n";
10494         generate_prototype ~extern:false ~semicolon:false ~newline:true
10495           ~handle:"g" ~prefix:"guestfs__" name style;
10496         pr "{\n";
10497         pr "  error (g, \"error\");\n";
10498         (match fst style with
10499          | RErr | RInt _ | RInt64 _ | RBool _ ->
10500              pr "  return -1;\n"
10501          | RConstString _ | RConstOptString _
10502          | RString _ | RStringList _ | RStruct _
10503          | RStructList _
10504          | RHashtable _
10505          | RBufferOut _ ->
10506              pr "  return NULL;\n"
10507         );
10508         pr "}\n";
10509         pr "\n"
10510       )
10511   ) tests
10512
10513 and generate_ocaml_bindtests () =
10514   generate_header OCamlStyle GPLv2plus;
10515
10516   pr "\
10517 let () =
10518   let g = Guestfs.create () in
10519 ";
10520
10521   let mkargs args =
10522     String.concat " " (
10523       List.map (
10524         function
10525         | CallString s -> "\"" ^ s ^ "\""
10526         | CallOptString None -> "None"
10527         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10528         | CallStringList xs ->
10529             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10530         | CallInt i when i >= 0 -> string_of_int i
10531         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10532         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10533         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10534         | CallBool b -> string_of_bool b
10535       ) args
10536     )
10537   in
10538
10539   generate_lang_bindtests (
10540     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10541   );
10542
10543   pr "print_endline \"EOF\"\n"
10544
10545 and generate_perl_bindtests () =
10546   pr "#!/usr/bin/perl -w\n";
10547   generate_header HashStyle GPLv2plus;
10548
10549   pr "\
10550 use strict;
10551
10552 use Sys::Guestfs;
10553
10554 my $g = Sys::Guestfs->new ();
10555 ";
10556
10557   let mkargs args =
10558     String.concat ", " (
10559       List.map (
10560         function
10561         | CallString s -> "\"" ^ s ^ "\""
10562         | CallOptString None -> "undef"
10563         | CallOptString (Some s) -> sprintf "\"%s\"" s
10564         | CallStringList xs ->
10565             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10566         | CallInt i -> string_of_int i
10567         | CallInt64 i -> Int64.to_string i
10568         | CallBool b -> if b then "1" else "0"
10569       ) args
10570     )
10571   in
10572
10573   generate_lang_bindtests (
10574     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10575   );
10576
10577   pr "print \"EOF\\n\"\n"
10578
10579 and generate_python_bindtests () =
10580   generate_header HashStyle GPLv2plus;
10581
10582   pr "\
10583 import guestfs
10584
10585 g = guestfs.GuestFS ()
10586 ";
10587
10588   let mkargs args =
10589     String.concat ", " (
10590       List.map (
10591         function
10592         | CallString s -> "\"" ^ s ^ "\""
10593         | CallOptString None -> "None"
10594         | CallOptString (Some s) -> sprintf "\"%s\"" s
10595         | CallStringList xs ->
10596             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10597         | CallInt i -> string_of_int i
10598         | CallInt64 i -> Int64.to_string i
10599         | CallBool b -> if b then "1" else "0"
10600       ) args
10601     )
10602   in
10603
10604   generate_lang_bindtests (
10605     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10606   );
10607
10608   pr "print \"EOF\"\n"
10609
10610 and generate_ruby_bindtests () =
10611   generate_header HashStyle GPLv2plus;
10612
10613   pr "\
10614 require 'guestfs'
10615
10616 g = Guestfs::create()
10617 ";
10618
10619   let mkargs args =
10620     String.concat ", " (
10621       List.map (
10622         function
10623         | CallString s -> "\"" ^ s ^ "\""
10624         | CallOptString None -> "nil"
10625         | CallOptString (Some s) -> sprintf "\"%s\"" s
10626         | CallStringList xs ->
10627             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10628         | CallInt i -> string_of_int i
10629         | CallInt64 i -> Int64.to_string i
10630         | CallBool b -> string_of_bool b
10631       ) args
10632     )
10633   in
10634
10635   generate_lang_bindtests (
10636     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10637   );
10638
10639   pr "print \"EOF\\n\"\n"
10640
10641 and generate_java_bindtests () =
10642   generate_header CStyle GPLv2plus;
10643
10644   pr "\
10645 import com.redhat.et.libguestfs.*;
10646
10647 public class Bindtests {
10648     public static void main (String[] argv)
10649     {
10650         try {
10651             GuestFS g = new GuestFS ();
10652 ";
10653
10654   let mkargs args =
10655     String.concat ", " (
10656       List.map (
10657         function
10658         | CallString s -> "\"" ^ s ^ "\""
10659         | CallOptString None -> "null"
10660         | CallOptString (Some s) -> sprintf "\"%s\"" s
10661         | CallStringList xs ->
10662             "new String[]{" ^
10663               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10664         | CallInt i -> string_of_int i
10665         | CallInt64 i -> Int64.to_string i
10666         | CallBool b -> string_of_bool b
10667       ) args
10668     )
10669   in
10670
10671   generate_lang_bindtests (
10672     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10673   );
10674
10675   pr "
10676             System.out.println (\"EOF\");
10677         }
10678         catch (Exception exn) {
10679             System.err.println (exn);
10680             System.exit (1);
10681         }
10682     }
10683 }
10684 "
10685
10686 and generate_haskell_bindtests () =
10687   generate_header HaskellStyle GPLv2plus;
10688
10689   pr "\
10690 module Bindtests where
10691 import qualified Guestfs
10692
10693 main = do
10694   g <- Guestfs.create
10695 ";
10696
10697   let mkargs args =
10698     String.concat " " (
10699       List.map (
10700         function
10701         | CallString s -> "\"" ^ s ^ "\""
10702         | CallOptString None -> "Nothing"
10703         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10704         | CallStringList xs ->
10705             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10706         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10707         | CallInt i -> string_of_int i
10708         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10709         | CallInt64 i -> Int64.to_string i
10710         | CallBool true -> "True"
10711         | CallBool false -> "False"
10712       ) args
10713     )
10714   in
10715
10716   generate_lang_bindtests (
10717     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10718   );
10719
10720   pr "  putStrLn \"EOF\"\n"
10721
10722 (* Language-independent bindings tests - we do it this way to
10723  * ensure there is parity in testing bindings across all languages.
10724  *)
10725 and generate_lang_bindtests call =
10726   call "test0" [CallString "abc"; CallOptString (Some "def");
10727                 CallStringList []; CallBool false;
10728                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10729   call "test0" [CallString "abc"; CallOptString None;
10730                 CallStringList []; CallBool false;
10731                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10732   call "test0" [CallString ""; CallOptString (Some "def");
10733                 CallStringList []; CallBool false;
10734                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10735   call "test0" [CallString ""; CallOptString (Some "");
10736                 CallStringList []; CallBool false;
10737                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10738   call "test0" [CallString "abc"; CallOptString (Some "def");
10739                 CallStringList ["1"]; CallBool false;
10740                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10741   call "test0" [CallString "abc"; CallOptString (Some "def");
10742                 CallStringList ["1"; "2"]; CallBool false;
10743                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10744   call "test0" [CallString "abc"; CallOptString (Some "def");
10745                 CallStringList ["1"]; CallBool true;
10746                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10747   call "test0" [CallString "abc"; CallOptString (Some "def");
10748                 CallStringList ["1"]; CallBool false;
10749                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10750   call "test0" [CallString "abc"; CallOptString (Some "def");
10751                 CallStringList ["1"]; CallBool false;
10752                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10753   call "test0" [CallString "abc"; CallOptString (Some "def");
10754                 CallStringList ["1"]; CallBool false;
10755                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10756   call "test0" [CallString "abc"; CallOptString (Some "def");
10757                 CallStringList ["1"]; CallBool false;
10758                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10759   call "test0" [CallString "abc"; CallOptString (Some "def");
10760                 CallStringList ["1"]; CallBool false;
10761                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10762   call "test0" [CallString "abc"; CallOptString (Some "def");
10763                 CallStringList ["1"]; CallBool false;
10764                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10765
10766 (* XXX Add here tests of the return and error functions. *)
10767
10768 (* Code to generator bindings for virt-inspector.  Currently only
10769  * implemented for OCaml code (for virt-p2v 2.0).
10770  *)
10771 let rng_input = "inspector/virt-inspector.rng"
10772
10773 (* Read the input file and parse it into internal structures.  This is
10774  * by no means a complete RELAX NG parser, but is just enough to be
10775  * able to parse the specific input file.
10776  *)
10777 type rng =
10778   | Element of string * rng list        (* <element name=name/> *)
10779   | Attribute of string * rng list        (* <attribute name=name/> *)
10780   | Interleave of rng list                (* <interleave/> *)
10781   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10782   | OneOrMore of rng                        (* <oneOrMore/> *)
10783   | Optional of rng                        (* <optional/> *)
10784   | Choice of string list                (* <choice><value/>*</choice> *)
10785   | Value of string                        (* <value>str</value> *)
10786   | Text                                (* <text/> *)
10787
10788 let rec string_of_rng = function
10789   | Element (name, xs) ->
10790       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10791   | Attribute (name, xs) ->
10792       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10793   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10794   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10795   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10796   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10797   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10798   | Value value -> "Value \"" ^ value ^ "\""
10799   | Text -> "Text"
10800
10801 and string_of_rng_list xs =
10802   String.concat ", " (List.map string_of_rng xs)
10803
10804 let rec parse_rng ?defines context = function
10805   | [] -> []
10806   | Xml.Element ("element", ["name", name], children) :: rest ->
10807       Element (name, parse_rng ?defines context children)
10808       :: parse_rng ?defines context rest
10809   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10810       Attribute (name, parse_rng ?defines context children)
10811       :: parse_rng ?defines context rest
10812   | Xml.Element ("interleave", [], children) :: rest ->
10813       Interleave (parse_rng ?defines context children)
10814       :: parse_rng ?defines context rest
10815   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10816       let rng = parse_rng ?defines context [child] in
10817       (match rng with
10818        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10819        | _ ->
10820            failwithf "%s: <zeroOrMore> contains more than one child element"
10821              context
10822       )
10823   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10824       let rng = parse_rng ?defines context [child] in
10825       (match rng with
10826        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10827        | _ ->
10828            failwithf "%s: <oneOrMore> contains more than one child element"
10829              context
10830       )
10831   | Xml.Element ("optional", [], [child]) :: rest ->
10832       let rng = parse_rng ?defines context [child] in
10833       (match rng with
10834        | [child] -> Optional child :: parse_rng ?defines context rest
10835        | _ ->
10836            failwithf "%s: <optional> contains more than one child element"
10837              context
10838       )
10839   | Xml.Element ("choice", [], children) :: rest ->
10840       let values = List.map (
10841         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10842         | _ ->
10843             failwithf "%s: can't handle anything except <value> in <choice>"
10844               context
10845       ) children in
10846       Choice values
10847       :: parse_rng ?defines context rest
10848   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10849       Value value :: parse_rng ?defines context rest
10850   | Xml.Element ("text", [], []) :: rest ->
10851       Text :: parse_rng ?defines context rest
10852   | Xml.Element ("ref", ["name", name], []) :: rest ->
10853       (* Look up the reference.  Because of limitations in this parser,
10854        * we can't handle arbitrarily nested <ref> yet.  You can only
10855        * use <ref> from inside <start>.
10856        *)
10857       (match defines with
10858        | None ->
10859            failwithf "%s: contains <ref>, but no refs are defined yet" context
10860        | Some map ->
10861            let rng = StringMap.find name map in
10862            rng @ parse_rng ?defines context rest
10863       )
10864   | x :: _ ->
10865       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10866
10867 let grammar =
10868   let xml = Xml.parse_file rng_input in
10869   match xml with
10870   | Xml.Element ("grammar", _,
10871                  Xml.Element ("start", _, gram) :: defines) ->
10872       (* The <define/> elements are referenced in the <start> section,
10873        * so build a map of those first.
10874        *)
10875       let defines = List.fold_left (
10876         fun map ->
10877           function Xml.Element ("define", ["name", name], defn) ->
10878             StringMap.add name defn map
10879           | _ ->
10880               failwithf "%s: expected <define name=name/>" rng_input
10881       ) StringMap.empty defines in
10882       let defines = StringMap.mapi parse_rng defines in
10883
10884       (* Parse the <start> clause, passing the defines. *)
10885       parse_rng ~defines "<start>" gram
10886   | _ ->
10887       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10888         rng_input
10889
10890 let name_of_field = function
10891   | Element (name, _) | Attribute (name, _)
10892   | ZeroOrMore (Element (name, _))
10893   | OneOrMore (Element (name, _))
10894   | Optional (Element (name, _)) -> name
10895   | Optional (Attribute (name, _)) -> name
10896   | Text -> (* an unnamed field in an element *)
10897       "data"
10898   | rng ->
10899       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10900
10901 (* At the moment this function only generates OCaml types.  However we
10902  * should parameterize it later so it can generate types/structs in a
10903  * variety of languages.
10904  *)
10905 let generate_types xs =
10906   (* A simple type is one that can be printed out directly, eg.
10907    * "string option".  A complex type is one which has a name and has
10908    * to be defined via another toplevel definition, eg. a struct.
10909    *
10910    * generate_type generates code for either simple or complex types.
10911    * In the simple case, it returns the string ("string option").  In
10912    * the complex case, it returns the name ("mountpoint").  In the
10913    * complex case it has to print out the definition before returning,
10914    * so it should only be called when we are at the beginning of a
10915    * new line (BOL context).
10916    *)
10917   let rec generate_type = function
10918     | Text ->                                (* string *)
10919         "string", true
10920     | Choice values ->                        (* [`val1|`val2|...] *)
10921         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10922     | ZeroOrMore rng ->                        (* <rng> list *)
10923         let t, is_simple = generate_type rng in
10924         t ^ " list (* 0 or more *)", is_simple
10925     | OneOrMore rng ->                        (* <rng> list *)
10926         let t, is_simple = generate_type rng in
10927         t ^ " list (* 1 or more *)", is_simple
10928                                         (* virt-inspector hack: bool *)
10929     | Optional (Attribute (name, [Value "1"])) ->
10930         "bool", true
10931     | Optional rng ->                        (* <rng> list *)
10932         let t, is_simple = generate_type rng in
10933         t ^ " option", is_simple
10934                                         (* type name = { fields ... } *)
10935     | Element (name, fields) when is_attrs_interleave fields ->
10936         generate_type_struct name (get_attrs_interleave fields)
10937     | Element (name, [field])                (* type name = field *)
10938     | Attribute (name, [field]) ->
10939         let t, is_simple = generate_type field in
10940         if is_simple then (t, true)
10941         else (
10942           pr "type %s = %s\n" name t;
10943           name, false
10944         )
10945     | Element (name, fields) ->              (* type name = { fields ... } *)
10946         generate_type_struct name fields
10947     | rng ->
10948         failwithf "generate_type failed at: %s" (string_of_rng rng)
10949
10950   and is_attrs_interleave = function
10951     | [Interleave _] -> true
10952     | Attribute _ :: fields -> is_attrs_interleave fields
10953     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
10954     | _ -> false
10955
10956   and get_attrs_interleave = function
10957     | [Interleave fields] -> fields
10958     | ((Attribute _) as field) :: fields
10959     | ((Optional (Attribute _)) as field) :: fields ->
10960         field :: get_attrs_interleave fields
10961     | _ -> assert false
10962
10963   and generate_types xs =
10964     List.iter (fun x -> ignore (generate_type x)) xs
10965
10966   and generate_type_struct name fields =
10967     (* Calculate the types of the fields first.  We have to do this
10968      * before printing anything so we are still in BOL context.
10969      *)
10970     let types = List.map fst (List.map generate_type fields) in
10971
10972     (* Special case of a struct containing just a string and another
10973      * field.  Turn it into an assoc list.
10974      *)
10975     match types with
10976     | ["string"; other] ->
10977         let fname1, fname2 =
10978           match fields with
10979           | [f1; f2] -> name_of_field f1, name_of_field f2
10980           | _ -> assert false in
10981         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
10982         name, false
10983
10984     | types ->
10985         pr "type %s = {\n" name;
10986         List.iter (
10987           fun (field, ftype) ->
10988             let fname = name_of_field field in
10989             pr "  %s_%s : %s;\n" name fname ftype
10990         ) (List.combine fields types);
10991         pr "}\n";
10992         (* Return the name of this type, and
10993          * false because it's not a simple type.
10994          *)
10995         name, false
10996   in
10997
10998   generate_types xs
10999
11000 let generate_parsers xs =
11001   (* As for generate_type above, generate_parser makes a parser for
11002    * some type, and returns the name of the parser it has generated.
11003    * Because it (may) need to print something, it should always be
11004    * called in BOL context.
11005    *)
11006   let rec generate_parser = function
11007     | Text ->                                (* string *)
11008         "string_child_or_empty"
11009     | Choice values ->                        (* [`val1|`val2|...] *)
11010         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11011           (String.concat "|"
11012              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11013     | ZeroOrMore rng ->                        (* <rng> list *)
11014         let pa = generate_parser rng in
11015         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11016     | OneOrMore rng ->                        (* <rng> list *)
11017         let pa = generate_parser rng in
11018         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11019                                         (* virt-inspector hack: bool *)
11020     | Optional (Attribute (name, [Value "1"])) ->
11021         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11022     | Optional rng ->                        (* <rng> list *)
11023         let pa = generate_parser rng in
11024         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11025                                         (* type name = { fields ... } *)
11026     | Element (name, fields) when is_attrs_interleave fields ->
11027         generate_parser_struct name (get_attrs_interleave fields)
11028     | Element (name, [field]) ->        (* type name = field *)
11029         let pa = generate_parser field in
11030         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11031         pr "let %s =\n" parser_name;
11032         pr "  %s\n" pa;
11033         pr "let parse_%s = %s\n" name parser_name;
11034         parser_name
11035     | Attribute (name, [field]) ->
11036         let pa = generate_parser field in
11037         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11038         pr "let %s =\n" parser_name;
11039         pr "  %s\n" pa;
11040         pr "let parse_%s = %s\n" name parser_name;
11041         parser_name
11042     | Element (name, fields) ->              (* type name = { fields ... } *)
11043         generate_parser_struct name ([], fields)
11044     | rng ->
11045         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11046
11047   and is_attrs_interleave = function
11048     | [Interleave _] -> true
11049     | Attribute _ :: fields -> is_attrs_interleave fields
11050     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11051     | _ -> false
11052
11053   and get_attrs_interleave = function
11054     | [Interleave fields] -> [], fields
11055     | ((Attribute _) as field) :: fields
11056     | ((Optional (Attribute _)) as field) :: fields ->
11057         let attrs, interleaves = get_attrs_interleave fields in
11058         (field :: attrs), interleaves
11059     | _ -> assert false
11060
11061   and generate_parsers xs =
11062     List.iter (fun x -> ignore (generate_parser x)) xs
11063
11064   and generate_parser_struct name (attrs, interleaves) =
11065     (* Generate parsers for the fields first.  We have to do this
11066      * before printing anything so we are still in BOL context.
11067      *)
11068     let fields = attrs @ interleaves in
11069     let pas = List.map generate_parser fields in
11070
11071     (* Generate an intermediate tuple from all the fields first.
11072      * If the type is just a string + another field, then we will
11073      * return this directly, otherwise it is turned into a record.
11074      *
11075      * RELAX NG note: This code treats <interleave> and plain lists of
11076      * fields the same.  In other words, it doesn't bother enforcing
11077      * any ordering of fields in the XML.
11078      *)
11079     pr "let parse_%s x =\n" name;
11080     pr "  let t = (\n    ";
11081     let comma = ref false in
11082     List.iter (
11083       fun x ->
11084         if !comma then pr ",\n    ";
11085         comma := true;
11086         match x with
11087         | Optional (Attribute (fname, [field])), pa ->
11088             pr "%s x" pa
11089         | Optional (Element (fname, [field])), pa ->
11090             pr "%s (optional_child %S x)" pa fname
11091         | Attribute (fname, [Text]), _ ->
11092             pr "attribute %S x" fname
11093         | (ZeroOrMore _ | OneOrMore _), pa ->
11094             pr "%s x" pa
11095         | Text, pa ->
11096             pr "%s x" pa
11097         | (field, pa) ->
11098             let fname = name_of_field field in
11099             pr "%s (child %S x)" pa fname
11100     ) (List.combine fields pas);
11101     pr "\n  ) in\n";
11102
11103     (match fields with
11104      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11105          pr "  t\n"
11106
11107      | _ ->
11108          pr "  (Obj.magic t : %s)\n" name
11109 (*
11110          List.iter (
11111            function
11112            | (Optional (Attribute (fname, [field])), pa) ->
11113                pr "  %s_%s =\n" name fname;
11114                pr "    %s x;\n" pa
11115            | (Optional (Element (fname, [field])), pa) ->
11116                pr "  %s_%s =\n" name fname;
11117                pr "    (let x = optional_child %S x in\n" fname;
11118                pr "     %s x);\n" pa
11119            | (field, pa) ->
11120                let fname = name_of_field field in
11121                pr "  %s_%s =\n" name fname;
11122                pr "    (let x = child %S x in\n" fname;
11123                pr "     %s x);\n" pa
11124          ) (List.combine fields pas);
11125          pr "}\n"
11126 *)
11127     );
11128     sprintf "parse_%s" name
11129   in
11130
11131   generate_parsers xs
11132
11133 (* Generate ocaml/guestfs_inspector.mli. *)
11134 let generate_ocaml_inspector_mli () =
11135   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11136
11137   pr "\
11138 (** This is an OCaml language binding to the external [virt-inspector]
11139     program.
11140
11141     For more information, please read the man page [virt-inspector(1)].
11142 *)
11143
11144 ";
11145
11146   generate_types grammar;
11147   pr "(** The nested information returned from the {!inspect} function. *)\n";
11148   pr "\n";
11149
11150   pr "\
11151 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11152 (** To inspect a libvirt domain called [name], pass a singleton
11153     list: [inspect [name]].  When using libvirt only, you may
11154     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11155
11156     To inspect a disk image or images, pass a list of the filenames
11157     of the disk images: [inspect filenames]
11158
11159     This function inspects the given guest or disk images and
11160     returns a list of operating system(s) found and a large amount
11161     of information about them.  In the vast majority of cases,
11162     a virtual machine only contains a single operating system.
11163
11164     If the optional [~xml] parameter is given, then this function
11165     skips running the external virt-inspector program and just
11166     parses the given XML directly (which is expected to be XML
11167     produced from a previous run of virt-inspector).  The list of
11168     names and connect URI are ignored in this case.
11169
11170     This function can throw a wide variety of exceptions, for example
11171     if the external virt-inspector program cannot be found, or if
11172     it doesn't generate valid XML.
11173 *)
11174 "
11175
11176 (* Generate ocaml/guestfs_inspector.ml. *)
11177 let generate_ocaml_inspector_ml () =
11178   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11179
11180   pr "open Unix\n";
11181   pr "\n";
11182
11183   generate_types grammar;
11184   pr "\n";
11185
11186   pr "\
11187 (* Misc functions which are used by the parser code below. *)
11188 let first_child = function
11189   | Xml.Element (_, _, c::_) -> c
11190   | Xml.Element (name, _, []) ->
11191       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11192   | Xml.PCData str ->
11193       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11194
11195 let string_child_or_empty = function
11196   | Xml.Element (_, _, [Xml.PCData s]) -> s
11197   | Xml.Element (_, _, []) -> \"\"
11198   | Xml.Element (x, _, _) ->
11199       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11200                 x ^ \" instead\")
11201   | Xml.PCData str ->
11202       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11203
11204 let optional_child name xml =
11205   let children = Xml.children xml in
11206   try
11207     Some (List.find (function
11208                      | Xml.Element (n, _, _) when n = name -> true
11209                      | _ -> false) children)
11210   with
11211     Not_found -> None
11212
11213 let child name xml =
11214   match optional_child name xml with
11215   | Some c -> c
11216   | None ->
11217       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11218
11219 let attribute name xml =
11220   try Xml.attrib xml name
11221   with Xml.No_attribute _ ->
11222     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11223
11224 ";
11225
11226   generate_parsers grammar;
11227   pr "\n";
11228
11229   pr "\
11230 (* Run external virt-inspector, then use parser to parse the XML. *)
11231 let inspect ?connect ?xml names =
11232   let xml =
11233     match xml with
11234     | None ->
11235         if names = [] then invalid_arg \"inspect: no names given\";
11236         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11237           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11238           names in
11239         let cmd = List.map Filename.quote cmd in
11240         let cmd = String.concat \" \" cmd in
11241         let chan = open_process_in cmd in
11242         let xml = Xml.parse_in chan in
11243         (match close_process_in chan with
11244          | WEXITED 0 -> ()
11245          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11246          | WSIGNALED i | WSTOPPED i ->
11247              failwith (\"external virt-inspector command died or stopped on sig \" ^
11248                        string_of_int i)
11249         );
11250         xml
11251     | Some doc ->
11252         Xml.parse_string doc in
11253   parse_operatingsystems xml
11254 "
11255
11256 (* This is used to generate the src/MAX_PROC_NR file which
11257  * contains the maximum procedure number, a surrogate for the
11258  * ABI version number.  See src/Makefile.am for the details.
11259  *)
11260 and generate_max_proc_nr () =
11261   let proc_nrs = List.map (
11262     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11263   ) daemon_functions in
11264
11265   let max_proc_nr = List.fold_left max 0 proc_nrs in
11266
11267   pr "%d\n" max_proc_nr
11268
11269 let output_to filename k =
11270   let filename_new = filename ^ ".new" in
11271   chan := open_out filename_new;
11272   k ();
11273   close_out !chan;
11274   chan := Pervasives.stdout;
11275
11276   (* Is the new file different from the current file? *)
11277   if Sys.file_exists filename && files_equal filename filename_new then
11278     unlink filename_new                 (* same, so skip it *)
11279   else (
11280     (* different, overwrite old one *)
11281     (try chmod filename 0o644 with Unix_error _ -> ());
11282     rename filename_new filename;
11283     chmod filename 0o444;
11284     printf "written %s\n%!" filename;
11285   )
11286
11287 let perror msg = function
11288   | Unix_error (err, _, _) ->
11289       eprintf "%s: %s\n" msg (error_message err)
11290   | exn ->
11291       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11292
11293 (* Main program. *)
11294 let () =
11295   let lock_fd =
11296     try openfile "HACKING" [O_RDWR] 0
11297     with
11298     | Unix_error (ENOENT, _, _) ->
11299         eprintf "\
11300 You are probably running this from the wrong directory.
11301 Run it from the top source directory using the command
11302   src/generator.ml
11303 ";
11304         exit 1
11305     | exn ->
11306         perror "open: HACKING" exn;
11307         exit 1 in
11308
11309   (* Acquire a lock so parallel builds won't try to run the generator
11310    * twice at the same time.  Subsequent builds will wait for the first
11311    * one to finish.  Note the lock is released implicitly when the
11312    * program exits.
11313    *)
11314   (try lockf lock_fd F_LOCK 1
11315    with exn ->
11316      perror "lock: HACKING" exn;
11317      exit 1);
11318
11319   check_functions ();
11320
11321   output_to "src/guestfs_protocol.x" generate_xdr;
11322   output_to "src/guestfs-structs.h" generate_structs_h;
11323   output_to "src/guestfs-actions.h" generate_actions_h;
11324   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11325   output_to "src/guestfs-actions.c" generate_client_actions;
11326   output_to "src/guestfs-bindtests.c" generate_bindtests;
11327   output_to "src/guestfs-structs.pod" generate_structs_pod;
11328   output_to "src/guestfs-actions.pod" generate_actions_pod;
11329   output_to "src/guestfs-availability.pod" generate_availability_pod;
11330   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11331   output_to "src/libguestfs.syms" generate_linker_script;
11332   output_to "daemon/actions.h" generate_daemon_actions_h;
11333   output_to "daemon/stubs.c" generate_daemon_actions;
11334   output_to "daemon/names.c" generate_daemon_names;
11335   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11336   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11337   output_to "capitests/tests.c" generate_tests;
11338   output_to "fish/cmds.c" generate_fish_cmds;
11339   output_to "fish/completion.c" generate_fish_completion;
11340   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11341   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11342   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11343   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11344   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11345   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11346   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11347   output_to "perl/Guestfs.xs" generate_perl_xs;
11348   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11349   output_to "perl/bindtests.pl" generate_perl_bindtests;
11350   output_to "python/guestfs-py.c" generate_python_c;
11351   output_to "python/guestfs.py" generate_python_py;
11352   output_to "python/bindtests.py" generate_python_bindtests;
11353   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11354   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11355   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11356
11357   List.iter (
11358     fun (typ, jtyp) ->
11359       let cols = cols_of_struct typ in
11360       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11361       output_to filename (generate_java_struct jtyp cols);
11362   ) java_structs;
11363
11364   output_to "java/Makefile.inc" generate_java_makefile_inc;
11365   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11366   output_to "java/Bindtests.java" generate_java_bindtests;
11367   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11368   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11369   output_to "csharp/Libguestfs.cs" generate_csharp;
11370
11371   (* Always generate this file last, and unconditionally.  It's used
11372    * by the Makefile to know when we must re-run the generator.
11373    *)
11374   let chan = open_out "src/stamp-generator" in
11375   fprintf chan "1\n";
11376   close_out chan;
11377
11378   printf "generated %d lines of code\n" !lines