532aba98a7257736943b84d7495e2964df2836fd
[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 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1384
1385   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM volume group",
1477    "\
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>
2029 or C<guestfs_txz_in>.");
2030
2031   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2032    [],
2033    "pack directory into tarfile",
2034    "\
2035 This command packs the contents of C<directory> and downloads
2036 it to local file C<tarfile>.
2037
2038 To download a compressed tarball, use C<guestfs_tgz_out>
2039 or C<guestfs_txz_out>.");
2040
2041   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042    [InitBasicFS, Always, TestOutput (
2043       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044        ["cat"; "/hello"]], "hello\n")],
2045    "unpack compressed tarball to directory",
2046    "\
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2049
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2051
2052   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2053    [],
2054    "pack directory into compressed tarball",
2055    "\
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2058
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2060
2061   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062    [InitBasicFS, Always, TestLastFail (
2063       [["umount"; "/"];
2064        ["mount_ro"; "/dev/sda1"; "/"];
2065        ["touch"; "/new"]]);
2066     InitBasicFS, Always, TestOutput (
2067       [["write_file"; "/new"; "data"; "0"];
2068        ["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["cat"; "/new"]], "data")],
2071    "mount a guest disk, read-only",
2072    "\
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2075
2076   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2077    [],
2078    "mount a guest disk with mount options",
2079    "\
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2083
2084   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2085    [],
2086    "mount a guest disk with mount options and vfstype",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2091
2092   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2093    [],
2094    "debugging and internals",
2095    "\
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2098 qemu subprocess.
2099
2100 There is no comprehensive help for this command.  You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2103
2104   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105    [InitEmpty, Always, TestOutputList (
2106       [["part_disk"; "/dev/sda"; "mbr"];
2107        ["pvcreate"; "/dev/sda1"];
2108        ["vgcreate"; "VG"; "/dev/sda1"];
2109        ["lvcreate"; "LV1"; "VG"; "50"];
2110        ["lvcreate"; "LV2"; "VG"; "50"];
2111        ["lvremove"; "/dev/VG/LV1"];
2112        ["lvs"]], ["/dev/VG/LV2"]);
2113     InitEmpty, Always, TestOutputList (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["lvremove"; "/dev/VG"];
2120        ["lvs"]], []);
2121     InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG"];
2128        ["vgs"]], ["VG"])],
2129    "remove an LVM logical volume",
2130    "\
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2133
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2136
2137   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["vgremove"; "VG"];
2145        ["lvs"]], []);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["vgremove"; "VG"];
2153        ["vgs"]], [])],
2154    "remove an LVM volume group",
2155    "\
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2157
2158 This also forcibly removes all logical volumes in the volume
2159 group (if any).");
2160
2161   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162    [InitEmpty, Always, TestOutputListOfDevices (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["pvremove"; "/dev/sda1"];
2170        ["lvs"]], []);
2171     InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["vgs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["pvs"]], [])],
2189    "remove an LVM physical volume",
2190    "\
2191 This wipes a physical volume C<device> so that LVM will no longer
2192 recognise it.
2193
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2197
2198   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199    [InitBasicFS, Always, TestOutput (
2200       [["set_e2label"; "/dev/sda1"; "testlabel"];
2201        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202    "set the ext2/3/4 filesystem label",
2203    "\
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>.  Filesystem labels are limited to
2206 16 characters.
2207
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2210
2211   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2212    [],
2213    "get the ext2/3/4 filesystem label",
2214    "\
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2216 C<device>.");
2217
2218   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219    (let uuid = uuidgen () in
2220     [InitBasicFS, Always, TestOutput (
2221        [["set_e2uuid"; "/dev/sda1"; uuid];
2222         ["get_e2uuid"; "/dev/sda1"]], uuid);
2223      InitBasicFS, Always, TestOutput (
2224        [["set_e2uuid"; "/dev/sda1"; "clear"];
2225         ["get_e2uuid"; "/dev/sda1"]], "");
2226      (* We can't predict what UUIDs will be, so just check the commands run. *)
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229      InitBasicFS, Always, TestRun (
2230        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231    "set the ext2/3/4 filesystem UUID",
2232    "\
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>.  The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2240
2241   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2242    [],
2243    "get the ext2/3/4 filesystem UUID",
2244    "\
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device>.");
2247
2248   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249    [InitBasicFS, Always, TestOutputInt (
2250       [["umount"; "/dev/sda1"];
2251        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252     InitBasicFS, Always, TestOutputInt (
2253       [["umount"; "/dev/sda1"];
2254        ["zero"; "/dev/sda1"];
2255        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256    "run the filesystem checker",
2257    "\
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2260
2261 The returned integer is the status.  See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2263
2264 Notes:
2265
2266 =over 4
2267
2268 =item *
2269
2270 Multiple status codes can be summed together.
2271
2272 =item *
2273
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2276
2277 =item *
2278
2279 Checking or repairing NTFS volumes is not supported
2280 (by linux-ntfs).
2281
2282 =back
2283
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2285
2286   ("zero", (RErr, [Device "device"]), 85, [],
2287    [InitBasicFS, Always, TestOutput (
2288       [["umount"; "/dev/sda1"];
2289        ["zero"; "/dev/sda1"];
2290        ["file"; "/dev/sda1"]], "data")],
2291    "write zeroes to the device",
2292    "\
2293 This command writes zeroes over the first few blocks of C<device>.
2294
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device).  It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2298
2299 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2300
2301   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302    (* Test disabled because grub-install incompatible with virtio-blk driver.
2303     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2304     *)
2305    [InitBasicFS, Disabled, TestOutputTrue (
2306       [["grub_install"; "/"; "/dev/sda1"];
2307        ["is_dir"; "/boot"]])],
2308    "install GRUB",
2309    "\
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2312
2313   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["write_file"; "/old"; "file content"; "0"];
2316        ["cp"; "/old"; "/new"];
2317        ["cat"; "/new"]], "file content");
2318     InitBasicFS, Always, TestOutputTrue (
2319       [["write_file"; "/old"; "file content"; "0"];
2320        ["cp"; "/old"; "/new"];
2321        ["is_file"; "/old"]]);
2322     InitBasicFS, Always, TestOutput (
2323       [["write_file"; "/old"; "file content"; "0"];
2324        ["mkdir"; "/dir"];
2325        ["cp"; "/old"; "/dir/new"];
2326        ["cat"; "/dir/new"]], "file content")],
2327    "copy a file",
2328    "\
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2331
2332   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333    [InitBasicFS, Always, TestOutput (
2334       [["mkdir"; "/olddir"];
2335        ["mkdir"; "/newdir"];
2336        ["write_file"; "/olddir/file"; "file content"; "0"];
2337        ["cp_a"; "/olddir"; "/newdir"];
2338        ["cat"; "/newdir/olddir/file"]], "file content")],
2339    "copy a file or directory recursively",
2340    "\
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2343
2344   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["mv"; "/old"; "/new"];
2348        ["cat"; "/new"]], "file content");
2349     InitBasicFS, Always, TestOutputFalse (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mv"; "/old"; "/new"];
2352        ["is_file"; "/old"]])],
2353    "move a file",
2354    "\
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2357
2358   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359    [InitEmpty, Always, TestRun (
2360       [["drop_caches"; "3"]])],
2361    "drop kernel page cache, dentries and inodes",
2362    "\
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches.  The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2367
2368 Setting C<whattodrop> to 3 should drop everything.
2369
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2372
2373   ("dmesg", (RString "kmsgs", []), 91, [],
2374    [InitEmpty, Always, TestRun (
2375       [["dmesg"]])],
2376    "return kernel messages",
2377    "\
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel.  This is sometimes useful for extended
2380 debugging of problems.
2381
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2386
2387   ("ping_daemon", (RErr, []), 92, [],
2388    [InitEmpty, Always, TestRun (
2389       [["ping_daemon"]])],
2390    "ping the guest daemon",
2391    "\
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess.  Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2396
2397   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398    [InitBasicFS, Always, TestOutputTrue (
2399       [["write_file"; "/file1"; "contents of a file"; "0"];
2400        ["cp"; "/file1"; "/file2"];
2401        ["equal"; "/file1"; "/file2"]]);
2402     InitBasicFS, Always, TestOutputFalse (
2403       [["write_file"; "/file1"; "contents of a file"; "0"];
2404        ["write_file"; "/file2"; "contents of another file"; "0"];
2405        ["equal"; "/file1"; "/file2"]]);
2406     InitBasicFS, Always, TestLastFail (
2407       [["equal"; "/file1"; "/file2"]])],
2408    "test if two files have equal contents",
2409    "\
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2412
2413 The external L<cmp(1)> program is used for the comparison.");
2414
2415   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416    [InitISOFS, Always, TestOutputList (
2417       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418     InitISOFS, Always, TestOutputList (
2419       [["strings"; "/empty"]], [])],
2420    "print the printable strings in a file",
2421    "\
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2424
2425   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings_e"; "b"; "/known-5"]], []);
2428     InitBasicFS, Disabled, TestOutputList (
2429       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431    "print the printable strings in a file",
2432    "\
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2435
2436 See the L<strings(1)> manpage for the full list of encodings.
2437
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2440
2441 The returned strings are transcoded to UTF-8.");
2442
2443   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444    [InitISOFS, Always, TestOutput (
2445       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2446     (* Test for RHBZ#501888c2 regression which caused large hexdump
2447      * commands to segfault.
2448      *)
2449     InitISOFS, Always, TestRun (
2450       [["hexdump"; "/100krandom"]])],
2451    "dump a file in hexadecimal",
2452    "\
2453 This runs C<hexdump -C> on the given C<path>.  The result is
2454 the human-readable, canonical hex dump of the file.");
2455
2456   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457    [InitNone, Always, TestOutput (
2458       [["part_disk"; "/dev/sda"; "mbr"];
2459        ["mkfs"; "ext3"; "/dev/sda1"];
2460        ["mount_options"; ""; "/dev/sda1"; "/"];
2461        ["write_file"; "/new"; "test file"; "0"];
2462        ["umount"; "/dev/sda1"];
2463        ["zerofree"; "/dev/sda1"];
2464        ["mount_options"; ""; "/dev/sda1"; "/"];
2465        ["cat"; "/new"]], "test file")],
2466    "zero unused inodes and disk blocks on ext2/3 filesystem",
2467    "\
2468 This runs the I<zerofree> program on C<device>.  This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2471 more effectively.
2472
2473 You should B<not> run this program if the filesystem is
2474 mounted.
2475
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2478
2479   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2480    [],
2481    "resize an LVM physical volume",
2482    "\
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2485
2486   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487                        Int "cyls"; Int "heads"; Int "sectors";
2488                        String "line"]), 99, [DangerWillRobinson],
2489    [],
2490    "modify a single partition on a block device",
2491    "\
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2494
2495 For other parameters, see C<guestfs_sfdisk>.  You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2497
2498 See also: C<guestfs_part_add>");
2499
2500   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2501    [],
2502    "display the partition table",
2503    "\
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command.  It is
2506 not intended to be parsed.
2507
2508 See also: C<guestfs_part_list>");
2509
2510   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2511    [],
2512    "display the kernel geometry",
2513    "\
2514 This displays the kernel's idea of the geometry of C<device>.
2515
2516 The result is in human-readable format, and not designed to
2517 be parsed.");
2518
2519   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2520    [],
2521    "display the disk geometry from the partition table",
2522    "\
2523 This displays the disk geometry of C<device> read from the
2524 partition table.  Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2532    [],
2533    "activate or deactivate all volume groups",
2534    "\
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2539 then those devices disappear.
2540
2541 This command is the same as running C<vgchange -a y|n>");
2542
2543   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate some volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2554
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2557
2558   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559    [InitNone, Always, TestOutput (
2560       [["part_disk"; "/dev/sda"; "mbr"];
2561        ["pvcreate"; "/dev/sda1"];
2562        ["vgcreate"; "VG"; "/dev/sda1"];
2563        ["lvcreate"; "LV"; "VG"; "10"];
2564        ["mkfs"; "ext2"; "/dev/VG/LV"];
2565        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566        ["write_file"; "/new"; "test content"; "0"];
2567        ["umount"; "/"];
2568        ["lvresize"; "/dev/VG/LV"; "20"];
2569        ["e2fsck_f"; "/dev/VG/LV"];
2570        ["resize2fs"; "/dev/VG/LV"];
2571        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572        ["cat"; "/new"]], "test content")],
2573    "resize an LVM logical volume",
2574    "\
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>.  When reducing, data in the reduced part
2577 is lost.");
2578
2579   ("resize2fs", (RErr, [Device "device"]), 106, [],
2580    [], (* lvresize tests this *)
2581    "resize an ext2/ext3 filesystem",
2582    "\
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2585
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command.  For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2591
2592   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593    [InitBasicFS, Always, TestOutputList (
2594       [["find"; "/"]], ["lost+found"]);
2595     InitBasicFS, Always, TestOutputList (
2596       [["touch"; "/a"];
2597        ["mkdir"; "/b"];
2598        ["touch"; "/b/c"];
2599        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600     InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["find"; "/a/b/"]], ["c"; "c/d"])],
2604    "find all files and directories",
2605    "\
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>.  It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2610
2611 This returns a list of strings I<without any prefix>.  Thus
2612 if the directory structure was:
2613
2614  /tmp/a
2615  /tmp/b
2616  /tmp/c/d
2617
2618 then the returned list from C<guestfs_find> C</tmp> would be
2619 4 elements:
2620
2621  a
2622  b
2623  c
2624  c/d
2625
2626 If C<directory> is not a directory, then this command returns
2627 an error.
2628
2629 The returned list is sorted.
2630
2631 See also C<guestfs_find0>.");
2632
2633   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634    [], (* lvresize tests this *)
2635    "check an ext2/ext3 filesystem",
2636    "\
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2640
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.).  Normally you should use C<guestfs_fsck>.");
2643
2644   ("sleep", (RErr, [Int "secs"]), 109, [],
2645    [InitNone, Always, TestRun (
2646       [["sleep"; "1"]])],
2647    "sleep for some seconds",
2648    "\
2649 Sleep for C<secs> seconds.");
2650
2651   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652    [InitNone, Always, TestOutputInt (
2653       [["part_disk"; "/dev/sda"; "mbr"];
2654        ["mkfs"; "ntfs"; "/dev/sda1"];
2655        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656     InitNone, Always, TestOutputInt (
2657       [["part_disk"; "/dev/sda"; "mbr"];
2658        ["mkfs"; "ext2"; "/dev/sda1"];
2659        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660    "probe NTFS volume",
2661    "\
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2665
2666 C<rw> is a boolean flag.  Set it to true if you want to test
2667 if the volume can be mounted read-write.  Set it to false if
2668 you want to test if the volume can be mounted read-only.
2669
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2673
2674   ("sh", (RString "output", [String "command"]), 111, [],
2675    [], (* XXX needs tests *)
2676    "run a command via the shell",
2677    "\
2678 This call runs a command from the guest filesystem via the
2679 guest's C</bin/sh>.
2680
2681 This is like C<guestfs_command>, but passes the command to:
2682
2683  /bin/sh -c \"command\"
2684
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2687 and so on.
2688
2689 All the provisos about C<guestfs_command> apply to this call.");
2690
2691   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692    [], (* XXX needs tests *)
2693    "run a command via the shell returning lines",
2694    "\
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2697
2698 See also: C<guestfs_command_lines>");
2699
2700   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702     * code in stubs.c, since all valid glob patterns must start with "/".
2703     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2704     *)
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/b/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/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715     InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/*/x/*"]], [])],
2720    "expand a wildcard path",
2721    "\
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2724 used by the shell.
2725
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2728
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2732
2733   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735       [["scrub_device"; "/dev/sdc"]])],
2736    "scrub (securely wipe) a device",
2737    "\
2738 This command writes patterns over C<device> to make data retrieval
2739 more difficult.
2740
2741 It is an interface to the L<scrub(1)> program.  See that
2742 manual page for more details.");
2743
2744   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745    [InitBasicFS, Always, TestRun (
2746       [["write_file"; "/file"; "content"; "0"];
2747        ["scrub_file"; "/file"]])],
2748    "scrub (securely wipe) a file",
2749    "\
2750 This command writes patterns over a file to make data retrieval
2751 more difficult.
2752
2753 The file is I<removed> after scrubbing.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759    [], (* XXX needs testing *)
2760    "scrub (securely wipe) free space",
2761    "\
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2766 containing C<dir>.
2767
2768 It is an interface to the L<scrub(1)> program.  See that
2769 manual page for more details.");
2770
2771   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772    [InitBasicFS, Always, TestRun (
2773       [["mkdir"; "/tmp"];
2774        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775    "create a temporary directory",
2776    "\
2777 This command creates a temporary directory.  The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2780 \"XXXXXX\".
2781
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2784
2785 The name of the temporary directory that was created
2786 is returned.
2787
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2790
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2793
2794 See also: L<mkdtemp(3)>");
2795
2796   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["wc_l"; "/10klines"]], 10000)],
2799    "count lines in a file",
2800    "\
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2803
2804   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805    [InitISOFS, Always, TestOutputInt (
2806       [["wc_w"; "/10klines"]], 10000)],
2807    "count words in a file",
2808    "\
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2811
2812   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813    [InitISOFS, Always, TestOutputInt (
2814       [["wc_c"; "/100kallspaces"]], 102400)],
2815    "count characters in a file",
2816    "\
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2819
2820   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821    [InitISOFS, Always, TestOutputList (
2822       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823    "return first 10 lines of a file",
2824    "\
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2827
2828   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829    [InitISOFS, Always, TestOutputList (
2830       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833     InitISOFS, Always, TestOutputList (
2834       [["head_n"; "0"; "/10klines"]], [])],
2835    "return first N lines of a file",
2836    "\
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2839
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2842
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2844
2845   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846    [InitISOFS, Always, TestOutputList (
2847       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848    "return last 10 lines of a file",
2849    "\
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2852
2853   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854    [InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858     InitISOFS, Always, TestOutputList (
2859       [["tail_n"; "0"; "/10klines"]], [])],
2860    "return last N lines of a file",
2861    "\
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2864
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2867
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2869
2870   ("df", (RString "output", []), 125, [],
2871    [], (* XXX Tricky to test because it depends on the exact format
2872         * of the 'df' command and other imponderables.
2873         *)
2874    "report file system disk space usage",
2875    "\
2876 This command runs the C<df> command to report disk space used.
2877
2878 This command is mostly useful for interactive sessions.  It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2881
2882   ("df_h", (RString "output", []), 126, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage (human readable)",
2887    "\
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2890
2891 This command is mostly useful for interactive sessions.  It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2894
2895   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896    [InitISOFS, Always, TestOutputInt (
2897       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898    "estimate file space usage",
2899    "\
2900 This command runs the C<du -s> command to estimate file space
2901 usage for C<path>.
2902
2903 C<path> can be a file or a directory.  If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2906
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2909
2910   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911    [InitISOFS, Always, TestOutputList (
2912       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913    "list files in an initrd",
2914    "\
2915 This command lists out files contained in an initrd.
2916
2917 The files are listed without any initial C</> character.  The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical).  Directory names are listed as separate items.
2920
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd.  We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2924
2925   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2926    [],
2927    "mount a file using the loop device",
2928    "\
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point.  It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2932
2933   ("mkswap", (RErr, [Device "device"]), 130, [],
2934    [InitEmpty, Always, TestRun (
2935       [["part_disk"; "/dev/sda"; "mbr"];
2936        ["mkswap"; "/dev/sda1"]])],
2937    "create a swap partition",
2938    "\
2939 Create a swap partition on C<device>.");
2940
2941   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942    [InitEmpty, Always, TestRun (
2943       [["part_disk"; "/dev/sda"; "mbr"];
2944        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945    "create a swap partition with a label",
2946    "\
2947 Create a swap partition on C<device> with label C<label>.
2948
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition.  This appears to be
2951 a limitation of the kernel or swap tools.");
2952
2953   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954    (let uuid = uuidgen () in
2955     [InitEmpty, Always, TestRun (
2956        [["part_disk"; "/dev/sda"; "mbr"];
2957         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958    "create a swap partition with an explicit UUID",
2959    "\
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2961
2962   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963    [InitBasicFS, Always, TestOutputStruct (
2964       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967     InitBasicFS, Always, TestOutputStruct (
2968       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970    "make block, character or FIFO devices",
2971    "\
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2974
2975 The C<mode> parameter should be the mode, using the standard
2976 constants.  C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.");
2979
2980   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2981    [InitBasicFS, Always, TestOutputStruct (
2982       [["mkfifo"; "0o777"; "/node"];
2983        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2984    "make FIFO (named pipe)",
2985    "\
2986 This call creates a FIFO (named pipe) called C<path> with
2987 mode C<mode>.  It is just a convenient wrapper around
2988 C<guestfs_mknod>.");
2989
2990   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2994    "make block device node",
2995    "\
2996 This call creates a block device node called C<path> with
2997 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2998 It is just a convenient wrapper around C<guestfs_mknod>.");
2999
3000   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3001    [InitBasicFS, Always, TestOutputStruct (
3002       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3004    "make char device node",
3005    "\
3006 This call creates a char device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3009
3010   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3011    [], (* XXX umask is one of those stateful things that we should
3012         * reset between each test.
3013         *)
3014    "set file mode creation mask (umask)",
3015    "\
3016 This function sets the mask used for creating new files and
3017 device nodes to C<mask & 0777>.
3018
3019 Typical umask values would be C<022> which creates new files
3020 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3021 C<002> which creates new files with permissions like
3022 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3023
3024 The default umask is C<022>.  This is important because it
3025 means that directories and device nodes will be created with
3026 C<0644> or C<0755> mode even if you specify C<0777>.
3027
3028 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3029
3030 This call returns the previous umask.");
3031
3032   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3033    [],
3034    "read directories entries",
3035    "\
3036 This returns the list of directory entries in directory C<dir>.
3037
3038 All entries in the directory are returned, including C<.> and
3039 C<..>.  The entries are I<not> sorted, but returned in the same
3040 order as the underlying filesystem.
3041
3042 Also this call returns basic file type information about each
3043 file.  The C<ftyp> field will contain one of the following characters:
3044
3045 =over 4
3046
3047 =item 'b'
3048
3049 Block special
3050
3051 =item 'c'
3052
3053 Char special
3054
3055 =item 'd'
3056
3057 Directory
3058
3059 =item 'f'
3060
3061 FIFO (named pipe)
3062
3063 =item 'l'
3064
3065 Symbolic link
3066
3067 =item 'r'
3068
3069 Regular file
3070
3071 =item 's'
3072
3073 Socket
3074
3075 =item 'u'
3076
3077 Unknown file type
3078
3079 =item '?'
3080
3081 The L<readdir(3)> returned a C<d_type> field with an
3082 unexpected value
3083
3084 =back
3085
3086 This function is primarily intended for use by programs.  To
3087 get a simple list of names, use C<guestfs_ls>.  To get a printable
3088 directory for human consumption, use C<guestfs_ll>.");
3089
3090   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3091    [],
3092    "create partitions on a block device",
3093    "\
3094 This is a simplified interface to the C<guestfs_sfdisk>
3095 command, where partition sizes are specified in megabytes
3096 only (rounded to the nearest cylinder) and you don't need
3097 to specify the cyls, heads and sectors parameters which
3098 were rarely if ever used anyway.
3099
3100 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3101 and C<guestfs_part_disk>");
3102
3103   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3104    [],
3105    "determine file type inside a compressed file",
3106    "\
3107 This command runs C<file> after first decompressing C<path>
3108 using C<method>.
3109
3110 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3111
3112 Since 1.0.63, use C<guestfs_file> instead which can now
3113 process compressed files.");
3114
3115   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3116    [],
3117    "list extended attributes of a file or directory",
3118    "\
3119 This call lists the extended attributes of the file or directory
3120 C<path>.
3121
3122 At the system call level, this is a combination of the
3123 L<listxattr(2)> and L<getxattr(2)> calls.
3124
3125 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3126
3127   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3128    [],
3129    "list extended attributes of a file or directory",
3130    "\
3131 This is the same as C<guestfs_getxattrs>, but if C<path>
3132 is a symbolic link, then it returns the extended attributes
3133 of the link itself.");
3134
3135   ("setxattr", (RErr, [String "xattr";
3136                        String "val"; Int "vallen"; (* will be BufferIn *)
3137                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3138    [],
3139    "set extended attribute of a file or directory",
3140    "\
3141 This call sets the extended attribute named C<xattr>
3142 of the file C<path> to the value C<val> (of length C<vallen>).
3143 The value is arbitrary 8 bit data.
3144
3145 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3146
3147   ("lsetxattr", (RErr, [String "xattr";
3148                         String "val"; Int "vallen"; (* will be BufferIn *)
3149                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3150    [],
3151    "set extended attribute of a file or directory",
3152    "\
3153 This is the same as C<guestfs_setxattr>, but if C<path>
3154 is a symbolic link, then it sets an extended attribute
3155 of the link itself.");
3156
3157   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3158    [],
3159    "remove extended attribute of a file or directory",
3160    "\
3161 This call removes the extended attribute named C<xattr>
3162 of the file C<path>.
3163
3164 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3165
3166   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3167    [],
3168    "remove extended attribute of a file or directory",
3169    "\
3170 This is the same as C<guestfs_removexattr>, but if C<path>
3171 is a symbolic link, then it removes an extended attribute
3172 of the link itself.");
3173
3174   ("mountpoints", (RHashtable "mps", []), 147, [],
3175    [],
3176    "show mountpoints",
3177    "\
3178 This call is similar to C<guestfs_mounts>.  That call returns
3179 a list of devices.  This one returns a hash table (map) of
3180 device name to directory where the device is mounted.");
3181
3182   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3183    (* This is a special case: while you would expect a parameter
3184     * of type "Pathname", that doesn't work, because it implies
3185     * NEED_ROOT in the generated calling code in stubs.c, and
3186     * this function cannot use NEED_ROOT.
3187     *)
3188    [],
3189    "create a mountpoint",
3190    "\
3191 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3192 specialized calls that can be used to create extra mountpoints
3193 before mounting the first filesystem.
3194
3195 These calls are I<only> necessary in some very limited circumstances,
3196 mainly the case where you want to mount a mix of unrelated and/or
3197 read-only filesystems together.
3198
3199 For example, live CDs often contain a \"Russian doll\" nest of
3200 filesystems, an ISO outer layer, with a squashfs image inside, with
3201 an ext2/3 image inside that.  You can unpack this as follows
3202 in guestfish:
3203
3204  add-ro Fedora-11-i686-Live.iso
3205  run
3206  mkmountpoint /cd
3207  mkmountpoint /squash
3208  mkmountpoint /ext3
3209  mount /dev/sda /cd
3210  mount-loop /cd/LiveOS/squashfs.img /squash
3211  mount-loop /squash/LiveOS/ext3fs.img /ext3
3212
3213 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3214
3215   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3216    [],
3217    "remove a mountpoint",
3218    "\
3219 This calls removes a mountpoint that was previously created
3220 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3221 for full details.");
3222
3223   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3224    [InitISOFS, Always, TestOutputBuffer (
3225       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3226    "read a file",
3227    "\
3228 This calls returns the contents of the file C<path> as a
3229 buffer.
3230
3231 Unlike C<guestfs_cat>, this function can correctly
3232 handle files that contain embedded ASCII NUL characters.
3233 However unlike C<guestfs_download>, this function is limited
3234 in the total size of file that can be handled.");
3235
3236   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3237    [InitISOFS, Always, TestOutputList (
3238       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3239     InitISOFS, Always, TestOutputList (
3240       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3241    "return lines matching a pattern",
3242    "\
3243 This calls the external C<grep> program and returns the
3244 matching lines.");
3245
3246   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3247    [InitISOFS, Always, TestOutputList (
3248       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3249    "return lines matching a pattern",
3250    "\
3251 This calls the external C<egrep> program and returns the
3252 matching lines.");
3253
3254   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3255    [InitISOFS, Always, TestOutputList (
3256       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3257    "return lines matching a pattern",
3258    "\
3259 This calls the external C<fgrep> program and returns the
3260 matching lines.");
3261
3262   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3263    [InitISOFS, Always, TestOutputList (
3264       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3265    "return lines matching a pattern",
3266    "\
3267 This calls the external C<grep -i> program and returns the
3268 matching lines.");
3269
3270   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3271    [InitISOFS, Always, TestOutputList (
3272       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3273    "return lines matching a pattern",
3274    "\
3275 This calls the external C<egrep -i> program and returns the
3276 matching lines.");
3277
3278   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3279    [InitISOFS, Always, TestOutputList (
3280       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3281    "return lines matching a pattern",
3282    "\
3283 This calls the external C<fgrep -i> program and returns the
3284 matching lines.");
3285
3286   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputList (
3288       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3289    "return lines matching a pattern",
3290    "\
3291 This calls the external C<zgrep> program and returns the
3292 matching lines.");
3293
3294   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3295    [InitISOFS, Always, TestOutputList (
3296       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3297    "return lines matching a pattern",
3298    "\
3299 This calls the external C<zegrep> program and returns the
3300 matching lines.");
3301
3302   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3303    [InitISOFS, Always, TestOutputList (
3304       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3305    "return lines matching a pattern",
3306    "\
3307 This calls the external C<zfgrep> program and returns the
3308 matching lines.");
3309
3310   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3311    [InitISOFS, Always, TestOutputList (
3312       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3313    "return lines matching a pattern",
3314    "\
3315 This calls the external C<zgrep -i> program and returns the
3316 matching lines.");
3317
3318   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3319    [InitISOFS, Always, TestOutputList (
3320       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<zegrep -i> program and returns the
3324 matching lines.");
3325
3326   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<zfgrep -i> program and returns the
3332 matching lines.");
3333
3334   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3335    [InitISOFS, Always, TestOutput (
3336       [["realpath"; "/../directory"]], "/directory")],
3337    "canonicalized absolute pathname",
3338    "\
3339 Return the canonicalized absolute pathname of C<path>.  The
3340 returned path has no C<.>, C<..> or symbolic link path elements.");
3341
3342   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3343    [InitBasicFS, Always, TestOutputStruct (
3344       [["touch"; "/a"];
3345        ["ln"; "/a"; "/b"];
3346        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3347    "create a hard link",
3348    "\
3349 This command creates a hard link using the C<ln> command.");
3350
3351   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3352    [InitBasicFS, Always, TestOutputStruct (
3353       [["touch"; "/a"];
3354        ["touch"; "/b"];
3355        ["ln_f"; "/a"; "/b"];
3356        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357    "create a hard link",
3358    "\
3359 This command creates a hard link using the C<ln -f> command.
3360 The C<-f> option removes the link (C<linkname>) if it exists already.");
3361
3362   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3363    [InitBasicFS, Always, TestOutputStruct (
3364       [["touch"; "/a"];
3365        ["ln_s"; "a"; "/b"];
3366        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3367    "create a symbolic link",
3368    "\
3369 This command creates a symbolic link using the C<ln -s> command.");
3370
3371   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3372    [InitBasicFS, Always, TestOutput (
3373       [["mkdir_p"; "/a/b"];
3374        ["touch"; "/a/b/c"];
3375        ["ln_sf"; "../d"; "/a/b/c"];
3376        ["readlink"; "/a/b/c"]], "../d")],
3377    "create a symbolic link",
3378    "\
3379 This command creates a symbolic link using the C<ln -sf> command,
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3381
3382   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3383    [] (* XXX tested above *),
3384    "read the target of a symbolic link",
3385    "\
3386 This command reads the target of a symbolic link.");
3387
3388   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3389    [InitBasicFS, Always, TestOutputStruct (
3390       [["fallocate"; "/a"; "1000000"];
3391        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3392    "preallocate a file in the guest filesystem",
3393    "\
3394 This command preallocates a file (containing zero bytes) named
3395 C<path> of size C<len> bytes.  If the file exists already, it
3396 is overwritten.
3397
3398 Do not confuse this with the guestfish-specific
3399 C<alloc> command which allocates a file in the host and
3400 attaches it as a device.");
3401
3402   ("swapon_device", (RErr, [Device "device"]), 170, [],
3403    [InitPartition, Always, TestRun (
3404       [["mkswap"; "/dev/sda1"];
3405        ["swapon_device"; "/dev/sda1"];
3406        ["swapoff_device"; "/dev/sda1"]])],
3407    "enable swap on device",
3408    "\
3409 This command enables the libguestfs appliance to use the
3410 swap device or partition named C<device>.  The increased
3411 memory is made available for all commands, for example
3412 those run using C<guestfs_command> or C<guestfs_sh>.
3413
3414 Note that you should not swap to existing guest swap
3415 partitions unless you know what you are doing.  They may
3416 contain hibernation information, or other information that
3417 the guest doesn't want you to trash.  You also risk leaking
3418 information about the host to the guest this way.  Instead,
3419 attach a new host device to the guest and swap on that.");
3420
3421   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3422    [], (* XXX tested by swapon_device *)
3423    "disable swap on device",
3424    "\
3425 This command disables the libguestfs appliance swap
3426 device or partition named C<device>.
3427 See C<guestfs_swapon_device>.");
3428
3429   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3430    [InitBasicFS, Always, TestRun (
3431       [["fallocate"; "/swap"; "8388608"];
3432        ["mkswap_file"; "/swap"];
3433        ["swapon_file"; "/swap"];
3434        ["swapoff_file"; "/swap"]])],
3435    "enable swap on file",
3436    "\
3437 This command enables swap to a file.
3438 See C<guestfs_swapon_device> for other notes.");
3439
3440   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3441    [], (* XXX tested by swapon_file *)
3442    "disable swap on file",
3443    "\
3444 This command disables the libguestfs appliance swap on file.");
3445
3446   ("swapon_label", (RErr, [String "label"]), 174, [],
3447    [InitEmpty, Always, TestRun (
3448       [["part_disk"; "/dev/sdb"; "mbr"];
3449        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3450        ["swapon_label"; "swapit"];
3451        ["swapoff_label"; "swapit"];
3452        ["zero"; "/dev/sdb"];
3453        ["blockdev_rereadpt"; "/dev/sdb"]])],
3454    "enable swap on labeled swap partition",
3455    "\
3456 This command enables swap to a labeled swap partition.
3457 See C<guestfs_swapon_device> for other notes.");
3458
3459   ("swapoff_label", (RErr, [String "label"]), 175, [],
3460    [], (* XXX tested by swapon_label *)
3461    "disable swap on labeled swap partition",
3462    "\
3463 This command disables the libguestfs appliance swap on
3464 labeled swap partition.");
3465
3466   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3467    (let uuid = uuidgen () in
3468     [InitEmpty, Always, TestRun (
3469        [["mkswap_U"; uuid; "/dev/sdb"];
3470         ["swapon_uuid"; uuid];
3471         ["swapoff_uuid"; uuid]])]),
3472    "enable swap on swap partition by UUID",
3473    "\
3474 This command enables swap to a swap partition with the given UUID.
3475 See C<guestfs_swapon_device> for other notes.");
3476
3477   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3478    [], (* XXX tested by swapon_uuid *)
3479    "disable swap on swap partition by UUID",
3480    "\
3481 This command disables the libguestfs appliance swap partition
3482 with the given UUID.");
3483
3484   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3485    [InitBasicFS, Always, TestRun (
3486       [["fallocate"; "/swap"; "8388608"];
3487        ["mkswap_file"; "/swap"]])],
3488    "create a swap file",
3489    "\
3490 Create a swap file.
3491
3492 This command just writes a swap file signature to an existing
3493 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3494
3495   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3496    [InitISOFS, Always, TestRun (
3497       [["inotify_init"; "0"]])],
3498    "create an inotify handle",
3499    "\
3500 This command creates a new inotify handle.
3501 The inotify subsystem can be used to notify events which happen to
3502 objects in the guest filesystem.
3503
3504 C<maxevents> is the maximum number of events which will be
3505 queued up between calls to C<guestfs_inotify_read> or
3506 C<guestfs_inotify_files>.
3507 If this is passed as C<0>, then the kernel (or previously set)
3508 default is used.  For Linux 2.6.29 the default was 16384 events.
3509 Beyond this limit, the kernel throws away events, but records
3510 the fact that it threw them away by setting a flag
3511 C<IN_Q_OVERFLOW> in the returned structure list (see
3512 C<guestfs_inotify_read>).
3513
3514 Before any events are generated, you have to add some
3515 watches to the internal watch list.  See:
3516 C<guestfs_inotify_add_watch>,
3517 C<guestfs_inotify_rm_watch> and
3518 C<guestfs_inotify_watch_all>.
3519
3520 Queued up events should be read periodically by calling
3521 C<guestfs_inotify_read>
3522 (or C<guestfs_inotify_files> which is just a helpful
3523 wrapper around C<guestfs_inotify_read>).  If you don't
3524 read the events out often enough then you risk the internal
3525 queue overflowing.
3526
3527 The handle should be closed after use by calling
3528 C<guestfs_inotify_close>.  This also removes any
3529 watches automatically.
3530
3531 See also L<inotify(7)> for an overview of the inotify interface
3532 as exposed by the Linux kernel, which is roughly what we expose
3533 via libguestfs.  Note that there is one global inotify handle
3534 per libguestfs instance.");
3535
3536   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3537    [InitBasicFS, Always, TestOutputList (
3538       [["inotify_init"; "0"];
3539        ["inotify_add_watch"; "/"; "1073741823"];
3540        ["touch"; "/a"];
3541        ["touch"; "/b"];
3542        ["inotify_files"]], ["a"; "b"])],
3543    "add an inotify watch",
3544    "\
3545 Watch C<path> for the events listed in C<mask>.
3546
3547 Note that if C<path> is a directory then events within that
3548 directory are watched, but this does I<not> happen recursively
3549 (in subdirectories).
3550
3551 Note for non-C or non-Linux callers: the inotify events are
3552 defined by the Linux kernel ABI and are listed in
3553 C</usr/include/sys/inotify.h>.");
3554
3555   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3556    [],
3557    "remove an inotify watch",
3558    "\
3559 Remove a previously defined inotify watch.
3560 See C<guestfs_inotify_add_watch>.");
3561
3562   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3563    [],
3564    "return list of inotify events",
3565    "\
3566 Return the complete queue of events that have happened
3567 since the previous read call.
3568
3569 If no events have happened, this returns an empty list.
3570
3571 I<Note>: In order to make sure that all events have been
3572 read, you must call this function repeatedly until it
3573 returns an empty list.  The reason is that the call will
3574 read events up to the maximum appliance-to-host message
3575 size and leave remaining events in the queue.");
3576
3577   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3578    [],
3579    "return list of watched files that had events",
3580    "\
3581 This function is a helpful wrapper around C<guestfs_inotify_read>
3582 which just returns a list of pathnames of objects that were
3583 touched.  The returned pathnames are sorted and deduplicated.");
3584
3585   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3586    [],
3587    "close the inotify handle",
3588    "\
3589 This closes the inotify handle which was previously
3590 opened by inotify_init.  It removes all watches, throws
3591 away any pending events, and deallocates all resources.");
3592
3593   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3594    [],
3595    "set SELinux security context",
3596    "\
3597 This sets the SELinux security context of the daemon
3598 to the string C<context>.
3599
3600 See the documentation about SELINUX in L<guestfs(3)>.");
3601
3602   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3603    [],
3604    "get SELinux security context",
3605    "\
3606 This gets the SELinux security context of the daemon.
3607
3608 See the documentation about SELINUX in L<guestfs(3)>,
3609 and C<guestfs_setcon>");
3610
3611   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3612    [InitEmpty, Always, TestOutput (
3613       [["part_disk"; "/dev/sda"; "mbr"];
3614        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3615        ["mount_options"; ""; "/dev/sda1"; "/"];
3616        ["write_file"; "/new"; "new file contents"; "0"];
3617        ["cat"; "/new"]], "new file contents")],
3618    "make a filesystem with block size",
3619    "\
3620 This call is similar to C<guestfs_mkfs>, but it allows you to
3621 control the block size of the resulting filesystem.  Supported
3622 block sizes depend on the filesystem type, but typically they
3623 are C<1024>, C<2048> or C<4096> only.");
3624
3625   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3626    [InitEmpty, Always, TestOutput (
3627       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3628        ["mke2journal"; "4096"; "/dev/sda1"];
3629        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3630        ["mount_options"; ""; "/dev/sda2"; "/"];
3631        ["write_file"; "/new"; "new file contents"; "0"];
3632        ["cat"; "/new"]], "new file contents")],
3633    "make ext2/3/4 external journal",
3634    "\
3635 This creates an ext2 external journal on C<device>.  It is equivalent
3636 to the command:
3637
3638  mke2fs -O journal_dev -b blocksize device");
3639
3640   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3641    [InitEmpty, Always, TestOutput (
3642       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3644        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3645        ["mount_options"; ""; "/dev/sda2"; "/"];
3646        ["write_file"; "/new"; "new file contents"; "0"];
3647        ["cat"; "/new"]], "new file contents")],
3648    "make ext2/3/4 external journal with label",
3649    "\
3650 This creates an ext2 external journal on C<device> with label C<label>.");
3651
3652   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3653    (let uuid = uuidgen () in
3654     [InitEmpty, Always, TestOutput (
3655        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3656         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3657         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3658         ["mount_options"; ""; "/dev/sda2"; "/"];
3659         ["write_file"; "/new"; "new file contents"; "0"];
3660         ["cat"; "/new"]], "new file contents")]),
3661    "make ext2/3/4 external journal with UUID",
3662    "\
3663 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3664
3665   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3666    [],
3667    "make ext2/3/4 filesystem with external journal",
3668    "\
3669 This creates an ext2/3/4 filesystem on C<device> with
3670 an external journal on C<journal>.  It is equivalent
3671 to the command:
3672
3673  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3674
3675 See also C<guestfs_mke2journal>.");
3676
3677   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3678    [],
3679    "make ext2/3/4 filesystem with external journal",
3680    "\
3681 This creates an ext2/3/4 filesystem on C<device> with
3682 an external journal on the journal labeled C<label>.
3683
3684 See also C<guestfs_mke2journal_L>.");
3685
3686   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3687    [],
3688    "make ext2/3/4 filesystem with external journal",
3689    "\
3690 This creates an ext2/3/4 filesystem on C<device> with
3691 an external journal on the journal with UUID C<uuid>.
3692
3693 See also C<guestfs_mke2journal_U>.");
3694
3695   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3696    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3697    "load a kernel module",
3698    "\
3699 This loads a kernel module in the appliance.
3700
3701 The kernel module must have been whitelisted when libguestfs
3702 was built (see C<appliance/kmod.whitelist.in> in the source).");
3703
3704   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3705    [InitNone, Always, TestOutput (
3706       [["echo_daemon"; "This is a test"]], "This is a test"
3707     )],
3708    "echo arguments back to the client",
3709    "\
3710 This command concatenate the list of C<words> passed with single spaces between
3711 them and returns the resulting string.
3712
3713 You can use this command to test the connection through to the daemon.
3714
3715 See also C<guestfs_ping_daemon>.");
3716
3717   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3718    [], (* There is a regression test for this. *)
3719    "find all files and directories, returning NUL-separated list",
3720    "\
3721 This command lists out all files and directories, recursively,
3722 starting at C<directory>, placing the resulting list in the
3723 external file called C<files>.
3724
3725 This command works the same way as C<guestfs_find> with the
3726 following exceptions:
3727
3728 =over 4
3729
3730 =item *
3731
3732 The resulting list is written to an external file.
3733
3734 =item *
3735
3736 Items (filenames) in the result are separated
3737 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3738
3739 =item *
3740
3741 This command is not limited in the number of names that it
3742 can return.
3743
3744 =item *
3745
3746 The result list is not sorted.
3747
3748 =back");
3749
3750   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3751    [InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3755     InitISOFS, Always, TestOutput (
3756       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3757     InitISOFS, Always, TestLastFail (
3758       [["case_sensitive_path"; "/Known-1/"]]);
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, TestOutput (
3765       [["mkdir"; "/a"];
3766        ["mkdir"; "/a/bbb"];
3767        ["touch"; "/a/bbb/c"];
3768        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3769     InitBasicFS, Always, TestLastFail (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3774    "return true path on case-insensitive filesystem",
3775    "\
3776 This can be used to resolve case insensitive paths on
3777 a filesystem which is case sensitive.  The use case is
3778 to resolve paths which you have read from Windows configuration
3779 files or the Windows Registry, to the true path.
3780
3781 The command handles a peculiarity of the Linux ntfs-3g
3782 filesystem driver (and probably others), which is that although
3783 the underlying filesystem is case-insensitive, the driver
3784 exports the filesystem to Linux as case-sensitive.
3785
3786 One consequence of this is that special directories such
3787 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3788 (or other things) depending on the precise details of how
3789 they were created.  In Windows itself this would not be
3790 a problem.
3791
3792 Bug or feature?  You decide:
3793 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3794
3795 This function resolves the true case of each element in the
3796 path and returns the case-sensitive path.
3797
3798 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3799 might return C<\"/WINDOWS/system32\"> (the exact return value
3800 would depend on details of how the directories were originally
3801 created under Windows).
3802
3803 I<Note>:
3804 This function does not handle drive names, backslashes etc.
3805
3806 See also C<guestfs_realpath>.");
3807
3808   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3809    [InitBasicFS, Always, TestOutput (
3810       [["vfs_type"; "/dev/sda1"]], "ext2")],
3811    "get the Linux VFS type corresponding to a mounted device",
3812    "\
3813 This command gets the block device type corresponding to
3814 a mounted device called C<device>.
3815
3816 Usually the result is the name of the Linux VFS module that
3817 is used to mount this device (probably determined automatically
3818 if you used the C<guestfs_mount> call).");
3819
3820   ("truncate", (RErr, [Pathname "path"]), 199, [],
3821    [InitBasicFS, Always, TestOutputStruct (
3822       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3823        ["truncate"; "/test"];
3824        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3825    "truncate a file to zero size",
3826    "\
3827 This command truncates C<path> to a zero-length file.  The
3828 file must exist already.");
3829
3830   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3831    [InitBasicFS, Always, TestOutputStruct (
3832       [["touch"; "/test"];
3833        ["truncate_size"; "/test"; "1000"];
3834        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3835    "truncate a file to a particular size",
3836    "\
3837 This command truncates C<path> to size C<size> bytes.  The file
3838 must exist already.  If the file is smaller than C<size> then
3839 the file is extended to the required size with null bytes.");
3840
3841   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3842    [InitBasicFS, Always, TestOutputStruct (
3843       [["touch"; "/test"];
3844        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3845        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3846    "set timestamp of a file with nanosecond precision",
3847    "\
3848 This command sets the timestamps of a file with nanosecond
3849 precision.
3850
3851 C<atsecs, atnsecs> are the last access time (atime) in secs and
3852 nanoseconds from the epoch.
3853
3854 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3855 secs and nanoseconds from the epoch.
3856
3857 If the C<*nsecs> field contains the special value C<-1> then
3858 the corresponding timestamp is set to the current time.  (The
3859 C<*secs> field is ignored in this case).
3860
3861 If the C<*nsecs> field contains the special value C<-2> then
3862 the corresponding timestamp is left unchanged.  (The
3863 C<*secs> field is ignored in this case).");
3864
3865   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3866    [InitBasicFS, Always, TestOutputStruct (
3867       [["mkdir_mode"; "/test"; "0o111"];
3868        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3869    "create a directory with a particular mode",
3870    "\
3871 This command creates a directory, setting the initial permissions
3872 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3873
3874   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3875    [], (* XXX *)
3876    "change file owner and group",
3877    "\
3878 Change the file owner to C<owner> and group to C<group>.
3879 This is like C<guestfs_chown> but if C<path> is a symlink then
3880 the link itself is changed, not the target.
3881
3882 Only numeric uid and gid are supported.  If you want to use
3883 names, you will need to locate and parse the password file
3884 yourself (Augeas support makes this relatively easy).");
3885
3886   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3887    [], (* XXX *)
3888    "lstat on multiple files",
3889    "\
3890 This call allows you to perform the C<guestfs_lstat> operation
3891 on multiple files, where all files are in the directory C<path>.
3892 C<names> is the list of files from this directory.
3893
3894 On return you get a list of stat structs, with a one-to-one
3895 correspondence to the C<names> list.  If any name did not exist
3896 or could not be lstat'd, then the C<ino> field of that structure
3897 is set to C<-1>.
3898
3899 This call is intended for programs that want to efficiently
3900 list a directory contents without making many round-trips.
3901 See also C<guestfs_lxattrlist> for a similarly efficient call
3902 for getting extended attributes.  Very long directory listings
3903 might cause the protocol message size to be exceeded, causing
3904 this call to fail.  The caller must split up such requests
3905 into smaller groups of names.");
3906
3907   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3908    [], (* XXX *)
3909    "lgetxattr on multiple files",
3910    "\
3911 This call allows you to get the extended attributes
3912 of multiple files, where all files are in the directory C<path>.
3913 C<names> is the list of files from this directory.
3914
3915 On return you get a flat list of xattr structs which must be
3916 interpreted sequentially.  The first xattr struct always has a zero-length
3917 C<attrname>.  C<attrval> in this struct is zero-length
3918 to indicate there was an error doing C<lgetxattr> for this
3919 file, I<or> is a C string which is a decimal number
3920 (the number of following attributes for this file, which could
3921 be C<\"0\">).  Then after the first xattr struct are the
3922 zero or more attributes for the first named file.
3923 This repeats for the second and subsequent files.
3924
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lstatlist> for a similarly efficient call
3928 for getting standard stats.  Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail.  The caller must split up such requests
3931 into smaller groups of names.");
3932
3933   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3934    [], (* XXX *)
3935    "readlink on multiple files",
3936    "\
3937 This call allows you to do a C<readlink> operation
3938 on multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3940
3941 On return you get a list of strings, with a one-to-one
3942 correspondence to the C<names> list.  Each string is the
3943 value of the symbol link.
3944
3945 If the C<readlink(2)> operation fails on any name, then
3946 the corresponding result string is the empty string C<\"\">.
3947 However the whole operation is completed even if there
3948 were C<readlink(2)> errors, and so you can call this
3949 function with names where you don't know if they are
3950 symbolic links already (albeit slightly less efficient).
3951
3952 This call is intended for programs that want to efficiently
3953 list a directory contents without making many round-trips.
3954 Very long directory listings might cause the protocol
3955 message size to be exceeded, causing
3956 this call to fail.  The caller must split up such requests
3957 into smaller groups of names.");
3958
3959   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3960    [InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/known-4"; "1"; "3"]], "\n");
3962     InitISOFS, Always, TestOutputBuffer (
3963       [["pread"; "/empty"; "0"; "100"]], "")],
3964    "read part of a file",
3965    "\
3966 This command lets you read part of a file.  It reads C<count>
3967 bytes of the file, starting at C<offset>, from file C<path>.
3968
3969 This may read fewer bytes than requested.  For further details
3970 see the L<pread(2)> system call.");
3971
3972   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3973    [InitEmpty, Always, TestRun (
3974       [["part_init"; "/dev/sda"; "gpt"]])],
3975    "create an empty partition table",
3976    "\
3977 This creates an empty partition table on C<device> of one of the
3978 partition types listed below.  Usually C<parttype> should be
3979 either C<msdos> or C<gpt> (for large disks).
3980
3981 Initially there are no partitions.  Following this, you should
3982 call C<guestfs_part_add> for each partition required.
3983
3984 Possible values for C<parttype> are:
3985
3986 =over 4
3987
3988 =item B<efi> | B<gpt>
3989
3990 Intel EFI / GPT partition table.
3991
3992 This is recommended for >= 2 TB partitions that will be accessed
3993 from Linux and Intel-based Mac OS X.  It also has limited backwards
3994 compatibility with the C<mbr> format.
3995
3996 =item B<mbr> | B<msdos>
3997
3998 The standard PC \"Master Boot Record\" (MBR) format used
3999 by MS-DOS and Windows.  This partition type will B<only> work
4000 for device sizes up to 2 TB.  For large disks we recommend
4001 using C<gpt>.
4002
4003 =back
4004
4005 Other partition table types that may work but are not
4006 supported include:
4007
4008 =over 4
4009
4010 =item B<aix>
4011
4012 AIX disk labels.
4013
4014 =item B<amiga> | B<rdb>
4015
4016 Amiga \"Rigid Disk Block\" format.
4017
4018 =item B<bsd>
4019
4020 BSD disk labels.
4021
4022 =item B<dasd>
4023
4024 DASD, used on IBM mainframes.
4025
4026 =item B<dvh>
4027
4028 MIPS/SGI volumes.
4029
4030 =item B<mac>
4031
4032 Old Mac partition format.  Modern Macs use C<gpt>.
4033
4034 =item B<pc98>
4035
4036 NEC PC-98 format, common in Japan apparently.
4037
4038 =item B<sun>
4039
4040 Sun disk labels.
4041
4042 =back");
4043
4044   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4045    [InitEmpty, Always, TestRun (
4046       [["part_init"; "/dev/sda"; "mbr"];
4047        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4048     InitEmpty, Always, TestRun (
4049       [["part_init"; "/dev/sda"; "gpt"];
4050        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4051        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4052     InitEmpty, Always, TestRun (
4053       [["part_init"; "/dev/sda"; "mbr"];
4054        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4055        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4056        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4057        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4058    "add a partition to the device",
4059    "\
4060 This command adds a partition to C<device>.  If there is no partition
4061 table on the device, call C<guestfs_part_init> first.
4062
4063 The C<prlogex> parameter is the type of partition.  Normally you
4064 should pass C<p> or C<primary> here, but MBR partition tables also
4065 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4066 types.
4067
4068 C<startsect> and C<endsect> are the start and end of the partition
4069 in I<sectors>.  C<endsect> may be negative, which means it counts
4070 backwards from the end of the disk (C<-1> is the last sector).
4071
4072 Creating a partition which covers the whole disk is not so easy.
4073 Use C<guestfs_part_disk> to do that.");
4074
4075   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4076    [InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "mbr"]]);
4078     InitEmpty, Always, TestRun (
4079       [["part_disk"; "/dev/sda"; "gpt"]])],
4080    "partition whole disk with a single primary partition",
4081    "\
4082 This command is simply a combination of C<guestfs_part_init>
4083 followed by C<guestfs_part_add> to create a single primary partition
4084 covering the whole disk.
4085
4086 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4087 but other possible values are described in C<guestfs_part_init>.");
4088
4089   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4090    [InitEmpty, Always, TestRun (
4091       [["part_disk"; "/dev/sda"; "mbr"];
4092        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4093    "make a partition bootable",
4094    "\
4095 This sets the bootable flag on partition numbered C<partnum> on
4096 device C<device>.  Note that partitions are numbered from 1.
4097
4098 The bootable flag is used by some operating systems (notably
4099 Windows) to determine which partition to boot from.  It is by
4100 no means universally recognized.");
4101
4102   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4103    [InitEmpty, Always, TestRun (
4104       [["part_disk"; "/dev/sda"; "gpt"];
4105        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4106    "set partition name",
4107    "\
4108 This sets the partition name on partition numbered C<partnum> on
4109 device C<device>.  Note that partitions are numbered from 1.
4110
4111 The partition name can only be set on certain types of partition
4112 table.  This works on C<gpt> but not on C<mbr> partitions.");
4113
4114   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4115    [], (* XXX Add a regression test for this. *)
4116    "list partitions on a device",
4117    "\
4118 This command parses the partition table on C<device> and
4119 returns the list of partitions found.
4120
4121 The fields in the returned structure are:
4122
4123 =over 4
4124
4125 =item B<part_num>
4126
4127 Partition number, counting from 1.
4128
4129 =item B<part_start>
4130
4131 Start of the partition I<in bytes>.  To get sectors you have to
4132 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4133
4134 =item B<part_end>
4135
4136 End of the partition in bytes.
4137
4138 =item B<part_size>
4139
4140 Size of the partition in bytes.
4141
4142 =back");
4143
4144   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4145    [InitEmpty, Always, TestOutput (
4146       [["part_disk"; "/dev/sda"; "gpt"];
4147        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4148    "get the partition table type",
4149    "\
4150 This command examines the partition table on C<device> and
4151 returns the partition table type (format) being used.
4152
4153 Common return values include: C<msdos> (a DOS/Windows style MBR
4154 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4155 values are possible, although unusual.  See C<guestfs_part_init>
4156 for a full list.");
4157
4158   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4159    [InitBasicFS, Always, TestOutputBuffer (
4160       [["fill"; "0x63"; "10"; "/test"];
4161        ["read_file"; "/test"]], "cccccccccc")],
4162    "fill a file with octets",
4163    "\
4164 This command creates a new file called C<path>.  The initial
4165 content of the file is C<len> octets of C<c>, where C<c>
4166 must be a number in the range C<[0..255]>.
4167
4168 To fill a file with zero bytes (sparsely), it is
4169 much more efficient to use C<guestfs_truncate_size>.");
4170
4171   ("available", (RErr, [StringList "groups"]), 216, [],
4172    [InitNone, Always, TestRun [["available"; ""]]],
4173    "test availability of some parts of the API",
4174    "\
4175 This command is used to check the availability of some
4176 groups of functionality in the appliance, which not all builds of
4177 the libguestfs appliance will be able to provide.
4178
4179 The libguestfs groups, and the functions that those
4180 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4181
4182 The argument C<groups> is a list of group names, eg:
4183 C<[\"inotify\", \"augeas\"]> would check for the availability of
4184 the Linux inotify functions and Augeas (configuration file
4185 editing) functions.
4186
4187 The command returns no error if I<all> requested groups are available.
4188
4189 It fails with an error if one or more of the requested
4190 groups is unavailable in the appliance.
4191
4192 If an unknown group name is included in the
4193 list of groups then an error is always returned.
4194
4195 I<Notes:>
4196
4197 =over 4
4198
4199 =item *
4200
4201 You must call C<guestfs_launch> before calling this function.
4202
4203 The reason is because we don't know what groups are
4204 supported by the appliance/daemon until it is running and can
4205 be queried.
4206
4207 =item *
4208
4209 If a group of functions is available, this does not necessarily
4210 mean that they will work.  You still have to check for errors
4211 when calling individual API functions even if they are
4212 available.
4213
4214 =item *
4215
4216 It is usually the job of distro packagers to build
4217 complete functionality into the libguestfs appliance.
4218 Upstream libguestfs, if built from source with all
4219 requirements satisfied, will support everything.
4220
4221 =item *
4222
4223 This call was added in version C<1.0.80>.  In previous
4224 versions of libguestfs all you could do would be to speculatively
4225 execute a command to find out if the daemon implemented it.
4226 See also C<guestfs_version>.
4227
4228 =back");
4229
4230   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4231    [InitBasicFS, Always, TestOutputBuffer (
4232       [["write_file"; "/src"; "hello, world"; "0"];
4233        ["dd"; "/src"; "/dest"];
4234        ["read_file"; "/dest"]], "hello, world")],
4235    "copy from source to destination using dd",
4236    "\
4237 This command copies from one source device or file C<src>
4238 to another destination device or file C<dest>.  Normally you
4239 would use this to copy to or from a device or partition, for
4240 example to duplicate a filesystem.
4241
4242 If the destination is a device, it must be as large or larger
4243 than the source file or device, otherwise the copy will fail.
4244 This command cannot do partial copies (see C<guestfs_copy_size>).");
4245
4246   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4247    [InitBasicFS, Always, TestOutputInt (
4248       [["write_file"; "/file"; "hello, world"; "0"];
4249        ["filesize"; "/file"]], 12)],
4250    "return the size of the file in bytes",
4251    "\
4252 This command returns the size of C<file> in bytes.
4253
4254 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4255 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4256 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4257
4258   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4259    [InitBasicFSonLVM, Always, TestOutputList (
4260       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4261        ["lvs"]], ["/dev/VG/LV2"])],
4262    "rename an LVM logical volume",
4263    "\
4264 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4265
4266   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4267    [InitBasicFSonLVM, Always, TestOutputList (
4268       [["umount"; "/"];
4269        ["vg_activate"; "false"; "VG"];
4270        ["vgrename"; "VG"; "VG2"];
4271        ["vg_activate"; "true"; "VG2"];
4272        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4273        ["vgs"]], ["VG2"])],
4274    "rename an LVM volume group",
4275    "\
4276 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4277
4278   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4279    [InitISOFS, Always, TestOutputBuffer (
4280       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4281    "list the contents of a single file in an initrd",
4282    "\
4283 This command unpacks the file C<filename> from the initrd file
4284 called C<initrdpath>.  The filename must be given I<without> the
4285 initial C</> character.
4286
4287 For example, in guestfish you could use the following command
4288 to examine the boot script (usually called C</init>)
4289 contained in a Linux initrd or initramfs image:
4290
4291  initrd-cat /boot/initrd-<version>.img init
4292
4293 See also C<guestfs_initrd_list>.");
4294
4295   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4296    [],
4297    "get the UUID of a physical volume",
4298    "\
4299 This command returns the UUID of the LVM PV C<device>.");
4300
4301   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4302    [],
4303    "get the UUID of a volume group",
4304    "\
4305 This command returns the UUID of the LVM VG named C<vgname>.");
4306
4307   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4308    [],
4309    "get the UUID of a logical volume",
4310    "\
4311 This command returns the UUID of the LVM LV C<device>.");
4312
4313   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4314    [],
4315    "get the PV UUIDs containing the volume group",
4316    "\
4317 Given a VG called C<vgname>, this returns the UUIDs of all
4318 the physical volumes that this volume group resides on.
4319
4320 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4321 calls to associate physical volumes and volume groups.
4322
4323 See also C<guestfs_vglvuuids>.");
4324
4325   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4326    [],
4327    "get the LV UUIDs of all LVs in the volume group",
4328    "\
4329 Given a VG called C<vgname>, this returns the UUIDs of all
4330 the logical volumes created in this volume group.
4331
4332 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4333 calls to associate logical volumes and volume groups.
4334
4335 See also C<guestfs_vgpvuuids>.");
4336
4337   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4338    [InitBasicFS, Always, TestOutputBuffer (
4339       [["write_file"; "/src"; "hello, world"; "0"];
4340        ["copy_size"; "/src"; "/dest"; "5"];
4341        ["read_file"; "/dest"]], "hello")],
4342    "copy size bytes from source to destination using dd",
4343    "\
4344 This command copies exactly C<size> bytes from one source device
4345 or file C<src> to another destination device or file C<dest>.
4346
4347 Note this will fail if the source is too short or if the destination
4348 is not large enough.");
4349
4350   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4351    [InitBasicFSonLVM, Always, TestRun (
4352       [["zero_device"; "/dev/VG/LV"]])],
4353    "write zeroes to an entire device",
4354    "\
4355 This command writes zeroes over the entire C<device>.  Compare
4356 with C<guestfs_zero> which just zeroes the first few blocks of
4357 a device.");
4358
4359   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4360    [InitBasicFS, Always, TestOutput (
4361       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4362        ["cat"; "/hello"]], "hello\n")],
4363    "unpack compressed tarball to directory",
4364    "\
4365 This command uploads and unpacks local file C<tarball> (an
4366 I<xz compressed> tar file) into C<directory>.");
4367
4368   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4369    [],
4370    "pack directory into compressed tarball",
4371    "\
4372 This command packs the contents of C<directory> and downloads
4373 it to local file C<tarball> (as an xz compressed tar archive).");
4374
4375   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4376    [],
4377    "resize an NTFS filesystem",
4378    "\
4379 This command resizes an NTFS filesystem, expanding or
4380 shrinking it to the size of the underlying device.
4381 See also L<ntfsresize(8)>.");
4382
4383   ("vgscan", (RErr, []), 232, [],
4384    [InitEmpty, Always, TestRun (
4385       [["vgscan"]])],
4386    "rescan for LVM physical volumes, volume groups and logical volumes",
4387    "\
4388 This rescans all block devices and rebuilds the list of LVM
4389 physical volumes, volume groups and logical volumes.");
4390
4391   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4392    [InitEmpty, Always, TestRun (
4393       [["part_init"; "/dev/sda"; "mbr"];
4394        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4395        ["part_del"; "/dev/sda"; "1"]])],
4396    "delete a partition",
4397    "\
4398 This command deletes the partition numbered C<partnum> on C<device>.
4399
4400 Note that in the case of MBR partitioning, deleting an
4401 extended partition also deletes any logical partitions
4402 it contains.");
4403
4404   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4405    [InitEmpty, Always, TestOutputTrue (
4406       [["part_init"; "/dev/sda"; "mbr"];
4407        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4408        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4409        ["part_get_bootable"; "/dev/sda"; "1"]])],
4410    "return true if a partition is bootable",
4411    "\
4412 This command returns true if the partition C<partnum> on
4413 C<device> has the bootable flag set.
4414
4415 See also C<guestfs_part_set_bootable>.");
4416
4417   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4418    [InitEmpty, Always, TestOutputInt (
4419       [["part_init"; "/dev/sda"; "mbr"];
4420        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4421        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4422        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4423    "get the MBR type byte (ID byte) from a partition",
4424    "\
4425 Returns the MBR type byte (also known as the ID byte) from
4426 the numbered partition C<partnum>.
4427
4428 Note that only MBR (old DOS-style) partitions have type bytes.
4429 You will get undefined results for other partition table
4430 types (see C<guestfs_part_get_parttype>).");
4431
4432   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4433    [], (* tested by part_get_mbr_id *)
4434    "set the MBR type byte (ID byte) of a partition",
4435    "\
4436 Sets the MBR type byte (also known as the ID byte) of
4437 the numbered partition C<partnum> to C<idbyte>.  Note
4438 that the type bytes quoted in most documentation are
4439 in fact hexadecimal numbers, but usually documented
4440 without any leading \"0x\" which might be confusing.
4441
4442 Note that only MBR (old DOS-style) partitions have type bytes.
4443 You will get undefined results for other partition table
4444 types (see C<guestfs_part_get_parttype>).");
4445
4446   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4447    [InitISOFS, Always, TestOutput (
4448       [["checksum_device"; "md5"; "/dev/sdd"]],
4449       (Digest.to_hex (Digest.file "images/test.iso")))],
4450    "compute MD5, SHAx or CRC checksum of the contents of a device",
4451    "\
4452 This call computes the MD5, SHAx or CRC checksum of the
4453 contents of the device named C<device>.  For the types of
4454 checksums supported see the C<guestfs_checksum> command.");
4455
4456   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4457    [InitNone, Always, TestRun (
4458       [["part_disk"; "/dev/sda"; "mbr"];
4459        ["pvcreate"; "/dev/sda1"];
4460        ["vgcreate"; "VG"; "/dev/sda1"];
4461        ["lvcreate"; "LV"; "VG"; "10"];
4462        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4463    "expand an LV to fill free space",
4464    "\
4465 This expands an existing logical volume C<lv> so that it fills
4466 C<pc>% of the remaining free space in the volume group.  Commonly
4467 you would call this with pc = 100 which expands the logical volume
4468 as much as possible, using all remaining free space in the volume
4469 group.");
4470
4471 ]
4472
4473 let all_functions = non_daemon_functions @ daemon_functions
4474
4475 (* In some places we want the functions to be displayed sorted
4476  * alphabetically, so this is useful:
4477  *)
4478 let all_functions_sorted =
4479   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4480                compare n1 n2) all_functions
4481
4482 (* Field types for structures. *)
4483 type field =
4484   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4485   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4486   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4487   | FUInt32
4488   | FInt32
4489   | FUInt64
4490   | FInt64
4491   | FBytes                      (* Any int measure that counts bytes. *)
4492   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4493   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4494
4495 (* Because we generate extra parsing code for LVM command line tools,
4496  * we have to pull out the LVM columns separately here.
4497  *)
4498 let lvm_pv_cols = [
4499   "pv_name", FString;
4500   "pv_uuid", FUUID;
4501   "pv_fmt", FString;
4502   "pv_size", FBytes;
4503   "dev_size", FBytes;
4504   "pv_free", FBytes;
4505   "pv_used", FBytes;
4506   "pv_attr", FString (* XXX *);
4507   "pv_pe_count", FInt64;
4508   "pv_pe_alloc_count", FInt64;
4509   "pv_tags", FString;
4510   "pe_start", FBytes;
4511   "pv_mda_count", FInt64;
4512   "pv_mda_free", FBytes;
4513   (* Not in Fedora 10:
4514      "pv_mda_size", FBytes;
4515   *)
4516 ]
4517 let lvm_vg_cols = [
4518   "vg_name", FString;
4519   "vg_uuid", FUUID;
4520   "vg_fmt", FString;
4521   "vg_attr", FString (* XXX *);
4522   "vg_size", FBytes;
4523   "vg_free", FBytes;
4524   "vg_sysid", FString;
4525   "vg_extent_size", FBytes;
4526   "vg_extent_count", FInt64;
4527   "vg_free_count", FInt64;
4528   "max_lv", FInt64;
4529   "max_pv", FInt64;
4530   "pv_count", FInt64;
4531   "lv_count", FInt64;
4532   "snap_count", FInt64;
4533   "vg_seqno", FInt64;
4534   "vg_tags", FString;
4535   "vg_mda_count", FInt64;
4536   "vg_mda_free", FBytes;
4537   (* Not in Fedora 10:
4538      "vg_mda_size", FBytes;
4539   *)
4540 ]
4541 let lvm_lv_cols = [
4542   "lv_name", FString;
4543   "lv_uuid", FUUID;
4544   "lv_attr", FString (* XXX *);
4545   "lv_major", FInt64;
4546   "lv_minor", FInt64;
4547   "lv_kernel_major", FInt64;
4548   "lv_kernel_minor", FInt64;
4549   "lv_size", FBytes;
4550   "seg_count", FInt64;
4551   "origin", FString;
4552   "snap_percent", FOptPercent;
4553   "copy_percent", FOptPercent;
4554   "move_pv", FString;
4555   "lv_tags", FString;
4556   "mirror_log", FString;
4557   "modules", FString;
4558 ]
4559
4560 (* Names and fields in all structures (in RStruct and RStructList)
4561  * that we support.
4562  *)
4563 let structs = [
4564   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4565    * not use this struct in any new code.
4566    *)
4567   "int_bool", [
4568     "i", FInt32;                (* for historical compatibility *)
4569     "b", FInt32;                (* for historical compatibility *)
4570   ];
4571
4572   (* LVM PVs, VGs, LVs. *)
4573   "lvm_pv", lvm_pv_cols;
4574   "lvm_vg", lvm_vg_cols;
4575   "lvm_lv", lvm_lv_cols;
4576
4577   (* Column names and types from stat structures.
4578    * NB. Can't use things like 'st_atime' because glibc header files
4579    * define some of these as macros.  Ugh.
4580    *)
4581   "stat", [
4582     "dev", FInt64;
4583     "ino", FInt64;
4584     "mode", FInt64;
4585     "nlink", FInt64;
4586     "uid", FInt64;
4587     "gid", FInt64;
4588     "rdev", FInt64;
4589     "size", FInt64;
4590     "blksize", FInt64;
4591     "blocks", FInt64;
4592     "atime", FInt64;
4593     "mtime", FInt64;
4594     "ctime", FInt64;
4595   ];
4596   "statvfs", [
4597     "bsize", FInt64;
4598     "frsize", FInt64;
4599     "blocks", FInt64;
4600     "bfree", FInt64;
4601     "bavail", FInt64;
4602     "files", FInt64;
4603     "ffree", FInt64;
4604     "favail", FInt64;
4605     "fsid", FInt64;
4606     "flag", FInt64;
4607     "namemax", FInt64;
4608   ];
4609
4610   (* Column names in dirent structure. *)
4611   "dirent", [
4612     "ino", FInt64;
4613     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4614     "ftyp", FChar;
4615     "name", FString;
4616   ];
4617
4618   (* Version numbers. *)
4619   "version", [
4620     "major", FInt64;
4621     "minor", FInt64;
4622     "release", FInt64;
4623     "extra", FString;
4624   ];
4625
4626   (* Extended attribute. *)
4627   "xattr", [
4628     "attrname", FString;
4629     "attrval", FBuffer;
4630   ];
4631
4632   (* Inotify events. *)
4633   "inotify_event", [
4634     "in_wd", FInt64;
4635     "in_mask", FUInt32;
4636     "in_cookie", FUInt32;
4637     "in_name", FString;
4638   ];
4639
4640   (* Partition table entry. *)
4641   "partition", [
4642     "part_num", FInt32;
4643     "part_start", FBytes;
4644     "part_end", FBytes;
4645     "part_size", FBytes;
4646   ];
4647 ] (* end of structs *)
4648
4649 (* Ugh, Java has to be different ..
4650  * These names are also used by the Haskell bindings.
4651  *)
4652 let java_structs = [
4653   "int_bool", "IntBool";
4654   "lvm_pv", "PV";
4655   "lvm_vg", "VG";
4656   "lvm_lv", "LV";
4657   "stat", "Stat";
4658   "statvfs", "StatVFS";
4659   "dirent", "Dirent";
4660   "version", "Version";
4661   "xattr", "XAttr";
4662   "inotify_event", "INotifyEvent";
4663   "partition", "Partition";
4664 ]
4665
4666 (* What structs are actually returned. *)
4667 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4668
4669 (* Returns a list of RStruct/RStructList structs that are returned
4670  * by any function.  Each element of returned list is a pair:
4671  *
4672  * (structname, RStructOnly)
4673  *    == there exists function which returns RStruct (_, structname)
4674  * (structname, RStructListOnly)
4675  *    == there exists function which returns RStructList (_, structname)
4676  * (structname, RStructAndList)
4677  *    == there are functions returning both RStruct (_, structname)
4678  *                                      and RStructList (_, structname)
4679  *)
4680 let rstructs_used_by functions =
4681   (* ||| is a "logical OR" for rstructs_used_t *)
4682   let (|||) a b =
4683     match a, b with
4684     | RStructAndList, _
4685     | _, RStructAndList -> RStructAndList
4686     | RStructOnly, RStructListOnly
4687     | RStructListOnly, RStructOnly -> RStructAndList
4688     | RStructOnly, RStructOnly -> RStructOnly
4689     | RStructListOnly, RStructListOnly -> RStructListOnly
4690   in
4691
4692   let h = Hashtbl.create 13 in
4693
4694   (* if elem->oldv exists, update entry using ||| operator,
4695    * else just add elem->newv to the hash
4696    *)
4697   let update elem newv =
4698     try  let oldv = Hashtbl.find h elem in
4699          Hashtbl.replace h elem (newv ||| oldv)
4700     with Not_found -> Hashtbl.add h elem newv
4701   in
4702
4703   List.iter (
4704     fun (_, style, _, _, _, _, _) ->
4705       match fst style with
4706       | RStruct (_, structname) -> update structname RStructOnly
4707       | RStructList (_, structname) -> update structname RStructListOnly
4708       | _ -> ()
4709   ) functions;
4710
4711   (* return key->values as a list of (key,value) *)
4712   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4713
4714 (* Used for testing language bindings. *)
4715 type callt =
4716   | CallString of string
4717   | CallOptString of string option
4718   | CallStringList of string list
4719   | CallInt of int
4720   | CallInt64 of int64
4721   | CallBool of bool
4722
4723 (* Used to memoize the result of pod2text. *)
4724 let pod2text_memo_filename = "src/.pod2text.data"
4725 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4726   try
4727     let chan = open_in pod2text_memo_filename in
4728     let v = input_value chan in
4729     close_in chan;
4730     v
4731   with
4732     _ -> Hashtbl.create 13
4733 let pod2text_memo_updated () =
4734   let chan = open_out pod2text_memo_filename in
4735   output_value chan pod2text_memo;
4736   close_out chan
4737
4738 (* Useful functions.
4739  * Note we don't want to use any external OCaml libraries which
4740  * makes this a bit harder than it should be.
4741  *)
4742 module StringMap = Map.Make (String)
4743
4744 let failwithf fs = ksprintf failwith fs
4745
4746 let unique = let i = ref 0 in fun () -> incr i; !i
4747
4748 let replace_char s c1 c2 =
4749   let s2 = String.copy s in
4750   let r = ref false in
4751   for i = 0 to String.length s2 - 1 do
4752     if String.unsafe_get s2 i = c1 then (
4753       String.unsafe_set s2 i c2;
4754       r := true
4755     )
4756   done;
4757   if not !r then s else s2
4758
4759 let isspace c =
4760   c = ' '
4761   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4762
4763 let triml ?(test = isspace) str =
4764   let i = ref 0 in
4765   let n = ref (String.length str) in
4766   while !n > 0 && test str.[!i]; do
4767     decr n;
4768     incr i
4769   done;
4770   if !i = 0 then str
4771   else String.sub str !i !n
4772
4773 let trimr ?(test = isspace) str =
4774   let n = ref (String.length str) in
4775   while !n > 0 && test str.[!n-1]; do
4776     decr n
4777   done;
4778   if !n = String.length str then str
4779   else String.sub str 0 !n
4780
4781 let trim ?(test = isspace) str =
4782   trimr ~test (triml ~test str)
4783
4784 let rec find s sub =
4785   let len = String.length s in
4786   let sublen = String.length sub in
4787   let rec loop i =
4788     if i <= len-sublen then (
4789       let rec loop2 j =
4790         if j < sublen then (
4791           if s.[i+j] = sub.[j] then loop2 (j+1)
4792           else -1
4793         ) else
4794           i (* found *)
4795       in
4796       let r = loop2 0 in
4797       if r = -1 then loop (i+1) else r
4798     ) else
4799       -1 (* not found *)
4800   in
4801   loop 0
4802
4803 let rec replace_str s s1 s2 =
4804   let len = String.length s in
4805   let sublen = String.length s1 in
4806   let i = find s s1 in
4807   if i = -1 then s
4808   else (
4809     let s' = String.sub s 0 i in
4810     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4811     s' ^ s2 ^ replace_str s'' s1 s2
4812   )
4813
4814 let rec string_split sep str =
4815   let len = String.length str in
4816   let seplen = String.length sep in
4817   let i = find str sep in
4818   if i = -1 then [str]
4819   else (
4820     let s' = String.sub str 0 i in
4821     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4822     s' :: string_split sep s''
4823   )
4824
4825 let files_equal n1 n2 =
4826   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4827   match Sys.command cmd with
4828   | 0 -> true
4829   | 1 -> false
4830   | i -> failwithf "%s: failed with error code %d" cmd i
4831
4832 let rec filter_map f = function
4833   | [] -> []
4834   | x :: xs ->
4835       match f x with
4836       | Some y -> y :: filter_map f xs
4837       | None -> filter_map f xs
4838
4839 let rec find_map f = function
4840   | [] -> raise Not_found
4841   | x :: xs ->
4842       match f x with
4843       | Some y -> y
4844       | None -> find_map f xs
4845
4846 let iteri f xs =
4847   let rec loop i = function
4848     | [] -> ()
4849     | x :: xs -> f i x; loop (i+1) xs
4850   in
4851   loop 0 xs
4852
4853 let mapi f xs =
4854   let rec loop i = function
4855     | [] -> []
4856     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4857   in
4858   loop 0 xs
4859
4860 let count_chars c str =
4861   let count = ref 0 in
4862   for i = 0 to String.length str - 1 do
4863     if c = String.unsafe_get str i then incr count
4864   done;
4865   !count
4866
4867 let name_of_argt = function
4868   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4869   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4870   | FileIn n | FileOut n -> n
4871
4872 let java_name_of_struct typ =
4873   try List.assoc typ java_structs
4874   with Not_found ->
4875     failwithf
4876       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4877
4878 let cols_of_struct typ =
4879   try List.assoc typ structs
4880   with Not_found ->
4881     failwithf "cols_of_struct: unknown struct %s" typ
4882
4883 let seq_of_test = function
4884   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4885   | TestOutputListOfDevices (s, _)
4886   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4887   | TestOutputTrue s | TestOutputFalse s
4888   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4889   | TestOutputStruct (s, _)
4890   | TestLastFail s -> s
4891
4892 (* Handling for function flags. *)
4893 let protocol_limit_warning =
4894   "Because of the message protocol, there is a transfer limit
4895 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4896
4897 let danger_will_robinson =
4898   "B<This command is dangerous.  Without careful use you
4899 can easily destroy all your data>."
4900
4901 let deprecation_notice flags =
4902   try
4903     let alt =
4904       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4905     let txt =
4906       sprintf "This function is deprecated.
4907 In new code, use the C<%s> call instead.
4908
4909 Deprecated functions will not be removed from the API, but the
4910 fact that they are deprecated indicates that there are problems
4911 with correct use of these functions." alt in
4912     Some txt
4913   with
4914     Not_found -> None
4915
4916 (* Create list of optional groups. *)
4917 let optgroups =
4918   let h = Hashtbl.create 13 in
4919   List.iter (
4920     fun (name, _, _, flags, _, _, _) ->
4921       List.iter (
4922         function
4923         | Optional group ->
4924             let names = try Hashtbl.find h group with Not_found -> [] in
4925             Hashtbl.replace h group (name :: names)
4926         | _ -> ()
4927       ) flags
4928   ) daemon_functions;
4929   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4930   let groups =
4931     List.map (
4932       fun group -> group, List.sort compare (Hashtbl.find h group)
4933     ) groups in
4934   List.sort (fun x y -> compare (fst x) (fst y)) groups
4935
4936 (* Check function names etc. for consistency. *)
4937 let check_functions () =
4938   let contains_uppercase str =
4939     let len = String.length str in
4940     let rec loop i =
4941       if i >= len then false
4942       else (
4943         let c = str.[i] in
4944         if c >= 'A' && c <= 'Z' then true
4945         else loop (i+1)
4946       )
4947     in
4948     loop 0
4949   in
4950
4951   (* Check function names. *)
4952   List.iter (
4953     fun (name, _, _, _, _, _, _) ->
4954       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4955         failwithf "function name %s does not need 'guestfs' prefix" name;
4956       if name = "" then
4957         failwithf "function name is empty";
4958       if name.[0] < 'a' || name.[0] > 'z' then
4959         failwithf "function name %s must start with lowercase a-z" name;
4960       if String.contains name '-' then
4961         failwithf "function name %s should not contain '-', use '_' instead."
4962           name
4963   ) all_functions;
4964
4965   (* Check function parameter/return names. *)
4966   List.iter (
4967     fun (name, style, _, _, _, _, _) ->
4968       let check_arg_ret_name n =
4969         if contains_uppercase n then
4970           failwithf "%s param/ret %s should not contain uppercase chars"
4971             name n;
4972         if String.contains n '-' || String.contains n '_' then
4973           failwithf "%s param/ret %s should not contain '-' or '_'"
4974             name n;
4975         if n = "value" then
4976           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;
4977         if n = "int" || n = "char" || n = "short" || n = "long" then
4978           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4979         if n = "i" || n = "n" then
4980           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4981         if n = "argv" || n = "args" then
4982           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4983
4984         (* List Haskell, OCaml and C keywords here.
4985          * http://www.haskell.org/haskellwiki/Keywords
4986          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4987          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4988          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4989          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4990          * Omitting _-containing words, since they're handled above.
4991          * Omitting the OCaml reserved word, "val", is ok,
4992          * and saves us from renaming several parameters.
4993          *)
4994         let reserved = [
4995           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4996           "char"; "class"; "const"; "constraint"; "continue"; "data";
4997           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4998           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4999           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5000           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5001           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5002           "interface";
5003           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5004           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5005           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5006           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5007           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5008           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5009           "volatile"; "when"; "where"; "while";
5010           ] in
5011         if List.mem n reserved then
5012           failwithf "%s has param/ret using reserved word %s" name n;
5013       in
5014
5015       (match fst style with
5016        | RErr -> ()
5017        | RInt n | RInt64 n | RBool n
5018        | RConstString n | RConstOptString n | RString n
5019        | RStringList n | RStruct (n, _) | RStructList (n, _)
5020        | RHashtable n | RBufferOut n ->
5021            check_arg_ret_name n
5022       );
5023       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5024   ) all_functions;
5025
5026   (* Check short descriptions. *)
5027   List.iter (
5028     fun (name, _, _, _, _, shortdesc, _) ->
5029       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5030         failwithf "short description of %s should begin with lowercase." name;
5031       let c = shortdesc.[String.length shortdesc-1] in
5032       if c = '\n' || c = '.' then
5033         failwithf "short description of %s should not end with . or \\n." name
5034   ) all_functions;
5035
5036   (* Check long dscriptions. *)
5037   List.iter (
5038     fun (name, _, _, _, _, _, longdesc) ->
5039       if longdesc.[String.length longdesc-1] = '\n' then
5040         failwithf "long description of %s should not end with \\n." name
5041   ) all_functions;
5042
5043   (* Check proc_nrs. *)
5044   List.iter (
5045     fun (name, _, proc_nr, _, _, _, _) ->
5046       if proc_nr <= 0 then
5047         failwithf "daemon function %s should have proc_nr > 0" name
5048   ) daemon_functions;
5049
5050   List.iter (
5051     fun (name, _, proc_nr, _, _, _, _) ->
5052       if proc_nr <> -1 then
5053         failwithf "non-daemon function %s should have proc_nr -1" name
5054   ) non_daemon_functions;
5055
5056   let proc_nrs =
5057     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5058       daemon_functions in
5059   let proc_nrs =
5060     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5061   let rec loop = function
5062     | [] -> ()
5063     | [_] -> ()
5064     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5065         loop rest
5066     | (name1,nr1) :: (name2,nr2) :: _ ->
5067         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5068           name1 name2 nr1 nr2
5069   in
5070   loop proc_nrs;
5071
5072   (* Check tests. *)
5073   List.iter (
5074     function
5075       (* Ignore functions that have no tests.  We generate a
5076        * warning when the user does 'make check' instead.
5077        *)
5078     | name, _, _, _, [], _, _ -> ()
5079     | name, _, _, _, tests, _, _ ->
5080         let funcs =
5081           List.map (
5082             fun (_, _, test) ->
5083               match seq_of_test test with
5084               | [] ->
5085                   failwithf "%s has a test containing an empty sequence" name
5086               | cmds -> List.map List.hd cmds
5087           ) tests in
5088         let funcs = List.flatten funcs in
5089
5090         let tested = List.mem name funcs in
5091
5092         if not tested then
5093           failwithf "function %s has tests but does not test itself" name
5094   ) all_functions
5095
5096 (* 'pr' prints to the current output file. *)
5097 let chan = ref Pervasives.stdout
5098 let lines = ref 0
5099 let pr fs =
5100   ksprintf
5101     (fun str ->
5102        let i = count_chars '\n' str in
5103        lines := !lines + i;
5104        output_string !chan str
5105     ) fs
5106
5107 let copyright_years =
5108   let this_year = 1900 + (localtime (time ())).tm_year in
5109   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5110
5111 (* Generate a header block in a number of standard styles. *)
5112 type comment_style =
5113     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5114 type license = GPLv2plus | LGPLv2plus
5115
5116 let generate_header ?(extra_inputs = []) comment license =
5117   let inputs = "src/generator.ml" :: extra_inputs in
5118   let c = match comment with
5119     | CStyle ->         pr "/* "; " *"
5120     | CPlusPlusStyle -> pr "// "; "//"
5121     | HashStyle ->      pr "# ";  "#"
5122     | OCamlStyle ->     pr "(* "; " *"
5123     | HaskellStyle ->   pr "{- "; "  " in
5124   pr "libguestfs generated file\n";
5125   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5126   List.iter (pr "%s   %s\n" c) inputs;
5127   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5128   pr "%s\n" c;
5129   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5130   pr "%s\n" c;
5131   (match license with
5132    | GPLv2plus ->
5133        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5134        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5135        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5136        pr "%s (at your option) any later version.\n" c;
5137        pr "%s\n" c;
5138        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5139        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5140        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5141        pr "%s GNU General Public License for more details.\n" c;
5142        pr "%s\n" c;
5143        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5144        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5145        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5146
5147    | LGPLv2plus ->
5148        pr "%s This library is free software; you can redistribute it and/or\n" c;
5149        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5150        pr "%s License as published by the Free Software Foundation; either\n" c;
5151        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5152        pr "%s\n" c;
5153        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5154        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5155        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5156        pr "%s Lesser General Public License for more details.\n" c;
5157        pr "%s\n" c;
5158        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5159        pr "%s License along with this library; if not, write to the Free Software\n" c;
5160        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5161   );
5162   (match comment with
5163    | CStyle -> pr " */\n"
5164    | CPlusPlusStyle
5165    | HashStyle -> ()
5166    | OCamlStyle -> pr " *)\n"
5167    | HaskellStyle -> pr "-}\n"
5168   );
5169   pr "\n"
5170
5171 (* Start of main code generation functions below this line. *)
5172
5173 (* Generate the pod documentation for the C API. *)
5174 let rec generate_actions_pod () =
5175   List.iter (
5176     fun (shortname, style, _, flags, _, _, longdesc) ->
5177       if not (List.mem NotInDocs flags) then (
5178         let name = "guestfs_" ^ shortname in
5179         pr "=head2 %s\n\n" name;
5180         pr " ";
5181         generate_prototype ~extern:false ~handle:"handle" name style;
5182         pr "\n\n";
5183         pr "%s\n\n" longdesc;
5184         (match fst style with
5185          | RErr ->
5186              pr "This function returns 0 on success or -1 on error.\n\n"
5187          | RInt _ ->
5188              pr "On error this function returns -1.\n\n"
5189          | RInt64 _ ->
5190              pr "On error this function returns -1.\n\n"
5191          | RBool _ ->
5192              pr "This function returns a C truth value on success or -1 on error.\n\n"
5193          | RConstString _ ->
5194              pr "This function returns a string, or NULL on error.
5195 The string is owned by the guest handle and must I<not> be freed.\n\n"
5196          | RConstOptString _ ->
5197              pr "This function returns a string which may be NULL.
5198 There is way to return an error from this function.
5199 The string is owned by the guest handle and must I<not> be freed.\n\n"
5200          | RString _ ->
5201              pr "This function returns a string, or NULL on error.
5202 I<The caller must free the returned string after use>.\n\n"
5203          | RStringList _ ->
5204              pr "This function returns a NULL-terminated array of strings
5205 (like L<environ(3)>), or NULL if there was an error.
5206 I<The caller must free the strings and the array after use>.\n\n"
5207          | RStruct (_, typ) ->
5208              pr "This function returns a C<struct guestfs_%s *>,
5209 or NULL if there was an error.
5210 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5211          | RStructList (_, typ) ->
5212              pr "This function returns a C<struct guestfs_%s_list *>
5213 (see E<lt>guestfs-structs.hE<gt>),
5214 or NULL if there was an error.
5215 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5216          | RHashtable _ ->
5217              pr "This function returns a NULL-terminated array of
5218 strings, or NULL if there was an error.
5219 The array of strings will always have length C<2n+1>, where
5220 C<n> keys and values alternate, followed by the trailing NULL entry.
5221 I<The caller must free the strings and the array after use>.\n\n"
5222          | RBufferOut _ ->
5223              pr "This function returns a buffer, or NULL on error.
5224 The size of the returned buffer is written to C<*size_r>.
5225 I<The caller must free the returned buffer after use>.\n\n"
5226         );
5227         if List.mem ProtocolLimitWarning flags then
5228           pr "%s\n\n" protocol_limit_warning;
5229         if List.mem DangerWillRobinson flags then
5230           pr "%s\n\n" danger_will_robinson;
5231         match deprecation_notice flags with
5232         | None -> ()
5233         | Some txt -> pr "%s\n\n" txt
5234       )
5235   ) all_functions_sorted
5236
5237 and generate_structs_pod () =
5238   (* Structs documentation. *)
5239   List.iter (
5240     fun (typ, cols) ->
5241       pr "=head2 guestfs_%s\n" typ;
5242       pr "\n";
5243       pr " struct guestfs_%s {\n" typ;
5244       List.iter (
5245         function
5246         | name, FChar -> pr "   char %s;\n" name
5247         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5248         | name, FInt32 -> pr "   int32_t %s;\n" name
5249         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5250         | name, FInt64 -> pr "   int64_t %s;\n" name
5251         | name, FString -> pr "   char *%s;\n" name
5252         | name, FBuffer ->
5253             pr "   /* The next two fields describe a byte array. */\n";
5254             pr "   uint32_t %s_len;\n" name;
5255             pr "   char *%s;\n" name
5256         | name, FUUID ->
5257             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5258             pr "   char %s[32];\n" name
5259         | name, FOptPercent ->
5260             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5261             pr "   float %s;\n" name
5262       ) cols;
5263       pr " };\n";
5264       pr " \n";
5265       pr " struct guestfs_%s_list {\n" typ;
5266       pr "   uint32_t len; /* Number of elements in list. */\n";
5267       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5268       pr " };\n";
5269       pr " \n";
5270       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5271       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5272         typ typ;
5273       pr "\n"
5274   ) structs
5275
5276 and generate_availability_pod () =
5277   (* Availability documentation. *)
5278   pr "=over 4\n";
5279   pr "\n";
5280   List.iter (
5281     fun (group, functions) ->
5282       pr "=item B<%s>\n" group;
5283       pr "\n";
5284       pr "The following functions:\n";
5285       List.iter (pr "L</guestfs_%s>\n") functions;
5286       pr "\n"
5287   ) optgroups;
5288   pr "=back\n";
5289   pr "\n"
5290
5291 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5292  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5293  *
5294  * We have to use an underscore instead of a dash because otherwise
5295  * rpcgen generates incorrect code.
5296  *
5297  * This header is NOT exported to clients, but see also generate_structs_h.
5298  *)
5299 and generate_xdr () =
5300   generate_header CStyle LGPLv2plus;
5301
5302   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5303   pr "typedef string str<>;\n";
5304   pr "\n";
5305
5306   (* Internal structures. *)
5307   List.iter (
5308     function
5309     | typ, cols ->
5310         pr "struct guestfs_int_%s {\n" typ;
5311         List.iter (function
5312                    | name, FChar -> pr "  char %s;\n" name
5313                    | name, FString -> pr "  string %s<>;\n" name
5314                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5315                    | name, FUUID -> pr "  opaque %s[32];\n" name
5316                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5317                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5318                    | name, FOptPercent -> pr "  float %s;\n" name
5319                   ) cols;
5320         pr "};\n";
5321         pr "\n";
5322         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5323         pr "\n";
5324   ) structs;
5325
5326   List.iter (
5327     fun (shortname, style, _, _, _, _, _) ->
5328       let name = "guestfs_" ^ shortname in
5329
5330       (match snd style with
5331        | [] -> ()
5332        | args ->
5333            pr "struct %s_args {\n" name;
5334            List.iter (
5335              function
5336              | Pathname n | Device n | Dev_or_Path n | String n ->
5337                  pr "  string %s<>;\n" n
5338              | OptString n -> pr "  str *%s;\n" n
5339              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5340              | Bool n -> pr "  bool %s;\n" n
5341              | Int n -> pr "  int %s;\n" n
5342              | Int64 n -> pr "  hyper %s;\n" n
5343              | FileIn _ | FileOut _ -> ()
5344            ) args;
5345            pr "};\n\n"
5346       );
5347       (match fst style with
5348        | RErr -> ()
5349        | RInt n ->
5350            pr "struct %s_ret {\n" name;
5351            pr "  int %s;\n" n;
5352            pr "};\n\n"
5353        | RInt64 n ->
5354            pr "struct %s_ret {\n" name;
5355            pr "  hyper %s;\n" n;
5356            pr "};\n\n"
5357        | RBool n ->
5358            pr "struct %s_ret {\n" name;
5359            pr "  bool %s;\n" n;
5360            pr "};\n\n"
5361        | RConstString _ | RConstOptString _ ->
5362            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5363        | RString n ->
5364            pr "struct %s_ret {\n" name;
5365            pr "  string %s<>;\n" n;
5366            pr "};\n\n"
5367        | RStringList n ->
5368            pr "struct %s_ret {\n" name;
5369            pr "  str %s<>;\n" n;
5370            pr "};\n\n"
5371        | RStruct (n, typ) ->
5372            pr "struct %s_ret {\n" name;
5373            pr "  guestfs_int_%s %s;\n" typ n;
5374            pr "};\n\n"
5375        | RStructList (n, typ) ->
5376            pr "struct %s_ret {\n" name;
5377            pr "  guestfs_int_%s_list %s;\n" typ n;
5378            pr "};\n\n"
5379        | RHashtable n ->
5380            pr "struct %s_ret {\n" name;
5381            pr "  str %s<>;\n" n;
5382            pr "};\n\n"
5383        | RBufferOut n ->
5384            pr "struct %s_ret {\n" name;
5385            pr "  opaque %s<>;\n" n;
5386            pr "};\n\n"
5387       );
5388   ) daemon_functions;
5389
5390   (* Table of procedure numbers. *)
5391   pr "enum guestfs_procedure {\n";
5392   List.iter (
5393     fun (shortname, _, proc_nr, _, _, _, _) ->
5394       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5395   ) daemon_functions;
5396   pr "  GUESTFS_PROC_NR_PROCS\n";
5397   pr "};\n";
5398   pr "\n";
5399
5400   (* Having to choose a maximum message size is annoying for several
5401    * reasons (it limits what we can do in the API), but it (a) makes
5402    * the protocol a lot simpler, and (b) provides a bound on the size
5403    * of the daemon which operates in limited memory space.
5404    *)
5405   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5406   pr "\n";
5407
5408   (* Message header, etc. *)
5409   pr "\
5410 /* The communication protocol is now documented in the guestfs(3)
5411  * manpage.
5412  */
5413
5414 const GUESTFS_PROGRAM = 0x2000F5F5;
5415 const GUESTFS_PROTOCOL_VERSION = 1;
5416
5417 /* These constants must be larger than any possible message length. */
5418 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5419 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5420
5421 enum guestfs_message_direction {
5422   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5423   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5424 };
5425
5426 enum guestfs_message_status {
5427   GUESTFS_STATUS_OK = 0,
5428   GUESTFS_STATUS_ERROR = 1
5429 };
5430
5431 const GUESTFS_ERROR_LEN = 256;
5432
5433 struct guestfs_message_error {
5434   string error_message<GUESTFS_ERROR_LEN>;
5435 };
5436
5437 struct guestfs_message_header {
5438   unsigned prog;                     /* GUESTFS_PROGRAM */
5439   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5440   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5441   guestfs_message_direction direction;
5442   unsigned serial;                   /* message serial number */
5443   guestfs_message_status status;
5444 };
5445
5446 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5447
5448 struct guestfs_chunk {
5449   int cancel;                        /* if non-zero, transfer is cancelled */
5450   /* data size is 0 bytes if the transfer has finished successfully */
5451   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5452 };
5453 "
5454
5455 (* Generate the guestfs-structs.h file. *)
5456 and generate_structs_h () =
5457   generate_header CStyle LGPLv2plus;
5458
5459   (* This is a public exported header file containing various
5460    * structures.  The structures are carefully written to have
5461    * exactly the same in-memory format as the XDR structures that
5462    * we use on the wire to the daemon.  The reason for creating
5463    * copies of these structures here is just so we don't have to
5464    * export the whole of guestfs_protocol.h (which includes much
5465    * unrelated and XDR-dependent stuff that we don't want to be
5466    * public, or required by clients).
5467    *
5468    * To reiterate, we will pass these structures to and from the
5469    * client with a simple assignment or memcpy, so the format
5470    * must be identical to what rpcgen / the RFC defines.
5471    *)
5472
5473   (* Public structures. *)
5474   List.iter (
5475     fun (typ, cols) ->
5476       pr "struct guestfs_%s {\n" typ;
5477       List.iter (
5478         function
5479         | name, FChar -> pr "  char %s;\n" name
5480         | name, FString -> pr "  char *%s;\n" name
5481         | name, FBuffer ->
5482             pr "  uint32_t %s_len;\n" name;
5483             pr "  char *%s;\n" name
5484         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5485         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5486         | name, FInt32 -> pr "  int32_t %s;\n" name
5487         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5488         | name, FInt64 -> pr "  int64_t %s;\n" name
5489         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5490       ) cols;
5491       pr "};\n";
5492       pr "\n";
5493       pr "struct guestfs_%s_list {\n" typ;
5494       pr "  uint32_t len;\n";
5495       pr "  struct guestfs_%s *val;\n" typ;
5496       pr "};\n";
5497       pr "\n";
5498       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5499       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5500       pr "\n"
5501   ) structs
5502
5503 (* Generate the guestfs-actions.h file. *)
5504 and generate_actions_h () =
5505   generate_header CStyle LGPLv2plus;
5506   List.iter (
5507     fun (shortname, style, _, _, _, _, _) ->
5508       let name = "guestfs_" ^ shortname in
5509       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5510         name style
5511   ) all_functions
5512
5513 (* Generate the guestfs-internal-actions.h file. *)
5514 and generate_internal_actions_h () =
5515   generate_header CStyle LGPLv2plus;
5516   List.iter (
5517     fun (shortname, style, _, _, _, _, _) ->
5518       let name = "guestfs__" ^ shortname in
5519       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5520         name style
5521   ) non_daemon_functions
5522
5523 (* Generate the client-side dispatch stubs. *)
5524 and generate_client_actions () =
5525   generate_header CStyle LGPLv2plus;
5526
5527   pr "\
5528 #include <stdio.h>
5529 #include <stdlib.h>
5530 #include <stdint.h>
5531 #include <string.h>
5532 #include <inttypes.h>
5533
5534 #include \"guestfs.h\"
5535 #include \"guestfs-internal.h\"
5536 #include \"guestfs-internal-actions.h\"
5537 #include \"guestfs_protocol.h\"
5538
5539 #define error guestfs_error
5540 //#define perrorf guestfs_perrorf
5541 #define safe_malloc guestfs_safe_malloc
5542 #define safe_realloc guestfs_safe_realloc
5543 //#define safe_strdup guestfs_safe_strdup
5544 #define safe_memdup guestfs_safe_memdup
5545
5546 /* Check the return message from a call for validity. */
5547 static int
5548 check_reply_header (guestfs_h *g,
5549                     const struct guestfs_message_header *hdr,
5550                     unsigned int proc_nr, unsigned int serial)
5551 {
5552   if (hdr->prog != GUESTFS_PROGRAM) {
5553     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5554     return -1;
5555   }
5556   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5557     error (g, \"wrong protocol version (%%d/%%d)\",
5558            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5559     return -1;
5560   }
5561   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5562     error (g, \"unexpected message direction (%%d/%%d)\",
5563            hdr->direction, GUESTFS_DIRECTION_REPLY);
5564     return -1;
5565   }
5566   if (hdr->proc != proc_nr) {
5567     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5568     return -1;
5569   }
5570   if (hdr->serial != serial) {
5571     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5572     return -1;
5573   }
5574
5575   return 0;
5576 }
5577
5578 /* Check we are in the right state to run a high-level action. */
5579 static int
5580 check_state (guestfs_h *g, const char *caller)
5581 {
5582   if (!guestfs__is_ready (g)) {
5583     if (guestfs__is_config (g) || guestfs__is_launching (g))
5584       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5585         caller);
5586     else
5587       error (g, \"%%s called from the wrong state, %%d != READY\",
5588         caller, guestfs__get_state (g));
5589     return -1;
5590   }
5591   return 0;
5592 }
5593
5594 ";
5595
5596   (* Generate code to generate guestfish call traces. *)
5597   let trace_call shortname style =
5598     pr "  if (guestfs__get_trace (g)) {\n";
5599
5600     let needs_i =
5601       List.exists (function
5602                    | StringList _ | DeviceList _ -> true
5603                    | _ -> false) (snd style) in
5604     if needs_i then (
5605       pr "    int i;\n";
5606       pr "\n"
5607     );
5608
5609     pr "    printf (\"%s\");\n" shortname;
5610     List.iter (
5611       function
5612       | String n                        (* strings *)
5613       | Device n
5614       | Pathname n
5615       | Dev_or_Path n
5616       | FileIn n
5617       | FileOut n ->
5618           (* guestfish doesn't support string escaping, so neither do we *)
5619           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5620       | OptString n ->                  (* string option *)
5621           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5622           pr "    else printf (\" null\");\n"
5623       | StringList n
5624       | DeviceList n ->                 (* string list *)
5625           pr "    putchar (' ');\n";
5626           pr "    putchar ('\"');\n";
5627           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5628           pr "      if (i > 0) putchar (' ');\n";
5629           pr "      fputs (%s[i], stdout);\n" n;
5630           pr "    }\n";
5631           pr "    putchar ('\"');\n";
5632       | Bool n ->                       (* boolean *)
5633           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5634       | Int n ->                        (* int *)
5635           pr "    printf (\" %%d\", %s);\n" n
5636       | Int64 n ->
5637           pr "    printf (\" %%\" PRIi64, %s);\n" n
5638     ) (snd style);
5639     pr "    putchar ('\\n');\n";
5640     pr "  }\n";
5641     pr "\n";
5642   in
5643
5644   (* For non-daemon functions, generate a wrapper around each function. *)
5645   List.iter (
5646     fun (shortname, style, _, _, _, _, _) ->
5647       let name = "guestfs_" ^ shortname in
5648
5649       generate_prototype ~extern:false ~semicolon:false ~newline:true
5650         ~handle:"g" name style;
5651       pr "{\n";
5652       trace_call shortname style;
5653       pr "  return guestfs__%s " shortname;
5654       generate_c_call_args ~handle:"g" style;
5655       pr ";\n";
5656       pr "}\n";
5657       pr "\n"
5658   ) non_daemon_functions;
5659
5660   (* Client-side stubs for each function. *)
5661   List.iter (
5662     fun (shortname, style, _, _, _, _, _) ->
5663       let name = "guestfs_" ^ shortname in
5664
5665       (* Generate the action stub. *)
5666       generate_prototype ~extern:false ~semicolon:false ~newline:true
5667         ~handle:"g" name style;
5668
5669       let error_code =
5670         match fst style with
5671         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5672         | RConstString _ | RConstOptString _ ->
5673             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5674         | RString _ | RStringList _
5675         | RStruct _ | RStructList _
5676         | RHashtable _ | RBufferOut _ ->
5677             "NULL" in
5678
5679       pr "{\n";
5680
5681       (match snd style with
5682        | [] -> ()
5683        | _ -> pr "  struct %s_args args;\n" name
5684       );
5685
5686       pr "  guestfs_message_header hdr;\n";
5687       pr "  guestfs_message_error err;\n";
5688       let has_ret =
5689         match fst style with
5690         | RErr -> false
5691         | RConstString _ | RConstOptString _ ->
5692             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5693         | RInt _ | RInt64 _
5694         | RBool _ | RString _ | RStringList _
5695         | RStruct _ | RStructList _
5696         | RHashtable _ | RBufferOut _ ->
5697             pr "  struct %s_ret ret;\n" name;
5698             true in
5699
5700       pr "  int serial;\n";
5701       pr "  int r;\n";
5702       pr "\n";
5703       trace_call shortname style;
5704       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5705       pr "  guestfs___set_busy (g);\n";
5706       pr "\n";
5707
5708       (* Send the main header and arguments. *)
5709       (match snd style with
5710        | [] ->
5711            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5712              (String.uppercase shortname)
5713        | args ->
5714            List.iter (
5715              function
5716              | Pathname n | Device n | Dev_or_Path n | String n ->
5717                  pr "  args.%s = (char *) %s;\n" n n
5718              | OptString n ->
5719                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5720              | StringList n | DeviceList n ->
5721                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5722                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5723              | Bool n ->
5724                  pr "  args.%s = %s;\n" n n
5725              | Int n ->
5726                  pr "  args.%s = %s;\n" n n
5727              | Int64 n ->
5728                  pr "  args.%s = %s;\n" n n
5729              | FileIn _ | FileOut _ -> ()
5730            ) args;
5731            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5732              (String.uppercase shortname);
5733            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5734              name;
5735       );
5736       pr "  if (serial == -1) {\n";
5737       pr "    guestfs___end_busy (g);\n";
5738       pr "    return %s;\n" error_code;
5739       pr "  }\n";
5740       pr "\n";
5741
5742       (* Send any additional files (FileIn) requested. *)
5743       let need_read_reply_label = ref false in
5744       List.iter (
5745         function
5746         | FileIn n ->
5747             pr "  r = guestfs___send_file (g, %s);\n" n;
5748             pr "  if (r == -1) {\n";
5749             pr "    guestfs___end_busy (g);\n";
5750             pr "    return %s;\n" error_code;
5751             pr "  }\n";
5752             pr "  if (r == -2) /* daemon cancelled */\n";
5753             pr "    goto read_reply;\n";
5754             need_read_reply_label := true;
5755             pr "\n";
5756         | _ -> ()
5757       ) (snd style);
5758
5759       (* Wait for the reply from the remote end. *)
5760       if !need_read_reply_label then pr " read_reply:\n";
5761       pr "  memset (&hdr, 0, sizeof hdr);\n";
5762       pr "  memset (&err, 0, sizeof err);\n";
5763       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5764       pr "\n";
5765       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5766       if not has_ret then
5767         pr "NULL, NULL"
5768       else
5769         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5770       pr ");\n";
5771
5772       pr "  if (r == -1) {\n";
5773       pr "    guestfs___end_busy (g);\n";
5774       pr "    return %s;\n" error_code;
5775       pr "  }\n";
5776       pr "\n";
5777
5778       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5779         (String.uppercase shortname);
5780       pr "    guestfs___end_busy (g);\n";
5781       pr "    return %s;\n" error_code;
5782       pr "  }\n";
5783       pr "\n";
5784
5785       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5786       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5787       pr "    free (err.error_message);\n";
5788       pr "    guestfs___end_busy (g);\n";
5789       pr "    return %s;\n" error_code;
5790       pr "  }\n";
5791       pr "\n";
5792
5793       (* Expecting to receive further files (FileOut)? *)
5794       List.iter (
5795         function
5796         | FileOut n ->
5797             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5798             pr "    guestfs___end_busy (g);\n";
5799             pr "    return %s;\n" error_code;
5800             pr "  }\n";
5801             pr "\n";
5802         | _ -> ()
5803       ) (snd style);
5804
5805       pr "  guestfs___end_busy (g);\n";
5806
5807       (match fst style with
5808        | RErr -> pr "  return 0;\n"
5809        | RInt n | RInt64 n | RBool n ->
5810            pr "  return ret.%s;\n" n
5811        | RConstString _ | RConstOptString _ ->
5812            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5813        | RString n ->
5814            pr "  return ret.%s; /* caller will free */\n" n
5815        | RStringList n | RHashtable n ->
5816            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5817            pr "  ret.%s.%s_val =\n" n n;
5818            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5819            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5820              n n;
5821            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5822            pr "  return ret.%s.%s_val;\n" n n
5823        | RStruct (n, _) ->
5824            pr "  /* caller will free this */\n";
5825            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5826        | RStructList (n, _) ->
5827            pr "  /* caller will free this */\n";
5828            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5829        | RBufferOut n ->
5830            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5831            pr "   * _val might be NULL here.  To make the API saner for\n";
5832            pr "   * callers, we turn this case into a unique pointer (using\n";
5833            pr "   * malloc(1)).\n";
5834            pr "   */\n";
5835            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5836            pr "    *size_r = ret.%s.%s_len;\n" n n;
5837            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5838            pr "  } else {\n";
5839            pr "    free (ret.%s.%s_val);\n" n n;
5840            pr "    char *p = safe_malloc (g, 1);\n";
5841            pr "    *size_r = ret.%s.%s_len;\n" n n;
5842            pr "    return p;\n";
5843            pr "  }\n";
5844       );
5845
5846       pr "}\n\n"
5847   ) daemon_functions;
5848
5849   (* Functions to free structures. *)
5850   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5851   pr " * structure format is identical to the XDR format.  See note in\n";
5852   pr " * generator.ml.\n";
5853   pr " */\n";
5854   pr "\n";
5855
5856   List.iter (
5857     fun (typ, _) ->
5858       pr "void\n";
5859       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5860       pr "{\n";
5861       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5862       pr "  free (x);\n";
5863       pr "}\n";
5864       pr "\n";
5865
5866       pr "void\n";
5867       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5868       pr "{\n";
5869       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5870       pr "  free (x);\n";
5871       pr "}\n";
5872       pr "\n";
5873
5874   ) structs;
5875
5876 (* Generate daemon/actions.h. *)
5877 and generate_daemon_actions_h () =
5878   generate_header CStyle GPLv2plus;
5879
5880   pr "#include \"../src/guestfs_protocol.h\"\n";
5881   pr "\n";
5882
5883   List.iter (
5884     fun (name, style, _, _, _, _, _) ->
5885       generate_prototype
5886         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5887         name style;
5888   ) daemon_functions
5889
5890 (* Generate the linker script which controls the visibility of
5891  * symbols in the public ABI and ensures no other symbols get
5892  * exported accidentally.
5893  *)
5894 and generate_linker_script () =
5895   generate_header HashStyle GPLv2plus;
5896
5897   let globals = [
5898     "guestfs_create";
5899     "guestfs_close";
5900     "guestfs_get_error_handler";
5901     "guestfs_get_out_of_memory_handler";
5902     "guestfs_last_error";
5903     "guestfs_set_error_handler";
5904     "guestfs_set_launch_done_callback";
5905     "guestfs_set_log_message_callback";
5906     "guestfs_set_out_of_memory_handler";
5907     "guestfs_set_subprocess_quit_callback";
5908
5909     (* Unofficial parts of the API: the bindings code use these
5910      * functions, so it is useful to export them.
5911      *)
5912     "guestfs_safe_calloc";
5913     "guestfs_safe_malloc";
5914   ] in
5915   let functions =
5916     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5917       all_functions in
5918   let structs =
5919     List.concat (
5920       List.map (fun (typ, _) ->
5921                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5922         structs
5923     ) in
5924   let globals = List.sort compare (globals @ functions @ structs) in
5925
5926   pr "{\n";
5927   pr "    global:\n";
5928   List.iter (pr "        %s;\n") globals;
5929   pr "\n";
5930
5931   pr "    local:\n";
5932   pr "        *;\n";
5933   pr "};\n"
5934
5935 (* Generate the server-side stubs. *)
5936 and generate_daemon_actions () =
5937   generate_header CStyle GPLv2plus;
5938
5939   pr "#include <config.h>\n";
5940   pr "\n";
5941   pr "#include <stdio.h>\n";
5942   pr "#include <stdlib.h>\n";
5943   pr "#include <string.h>\n";
5944   pr "#include <inttypes.h>\n";
5945   pr "#include <rpc/types.h>\n";
5946   pr "#include <rpc/xdr.h>\n";
5947   pr "\n";
5948   pr "#include \"daemon.h\"\n";
5949   pr "#include \"c-ctype.h\"\n";
5950   pr "#include \"../src/guestfs_protocol.h\"\n";
5951   pr "#include \"actions.h\"\n";
5952   pr "\n";
5953
5954   List.iter (
5955     fun (name, style, _, _, _, _, _) ->
5956       (* Generate server-side stubs. *)
5957       pr "static void %s_stub (XDR *xdr_in)\n" name;
5958       pr "{\n";
5959       let error_code =
5960         match fst style with
5961         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5962         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5963         | RBool _ -> pr "  int r;\n"; "-1"
5964         | RConstString _ | RConstOptString _ ->
5965             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5966         | RString _ -> pr "  char *r;\n"; "NULL"
5967         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5968         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5969         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5970         | RBufferOut _ ->
5971             pr "  size_t size = 1;\n";
5972             pr "  char *r;\n";
5973             "NULL" in
5974
5975       (match snd style with
5976        | [] -> ()
5977        | args ->
5978            pr "  struct guestfs_%s_args args;\n" name;
5979            List.iter (
5980              function
5981              | Device n | Dev_or_Path n
5982              | Pathname n
5983              | String n -> ()
5984              | OptString n -> pr "  char *%s;\n" n
5985              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5986              | Bool n -> pr "  int %s;\n" n
5987              | Int n -> pr "  int %s;\n" n
5988              | Int64 n -> pr "  int64_t %s;\n" n
5989              | FileIn _ | FileOut _ -> ()
5990            ) args
5991       );
5992       pr "\n";
5993
5994       (match snd style with
5995        | [] -> ()
5996        | args ->
5997            pr "  memset (&args, 0, sizeof args);\n";
5998            pr "\n";
5999            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6000            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6001            pr "    return;\n";
6002            pr "  }\n";
6003            let pr_args n =
6004              pr "  char *%s = args.%s;\n" n n
6005            in
6006            let pr_list_handling_code n =
6007              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6008              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6009              pr "  if (%s == NULL) {\n" n;
6010              pr "    reply_with_perror (\"realloc\");\n";
6011              pr "    goto done;\n";
6012              pr "  }\n";
6013              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6014              pr "  args.%s.%s_val = %s;\n" n n n;
6015            in
6016            List.iter (
6017              function
6018              | Pathname n ->
6019                  pr_args n;
6020                  pr "  ABS_PATH (%s, goto done);\n" n;
6021              | Device n ->
6022                  pr_args n;
6023                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6024              | Dev_or_Path n ->
6025                  pr_args n;
6026                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6027              | String n -> pr_args n
6028              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6029              | StringList n ->
6030                  pr_list_handling_code n;
6031              | DeviceList n ->
6032                  pr_list_handling_code n;
6033                  pr "  /* Ensure that each is a device,\n";
6034                  pr "   * and perform device name translation. */\n";
6035                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6036                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6037                  pr "  }\n";
6038              | Bool n -> pr "  %s = args.%s;\n" n n
6039              | Int n -> pr "  %s = args.%s;\n" n n
6040              | Int64 n -> pr "  %s = args.%s;\n" n n
6041              | FileIn _ | FileOut _ -> ()
6042            ) args;
6043            pr "\n"
6044       );
6045
6046
6047       (* this is used at least for do_equal *)
6048       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6049         (* Emit NEED_ROOT just once, even when there are two or
6050            more Pathname args *)
6051         pr "  NEED_ROOT (goto done);\n";
6052       );
6053
6054       (* Don't want to call the impl with any FileIn or FileOut
6055        * parameters, since these go "outside" the RPC protocol.
6056        *)
6057       let args' =
6058         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6059           (snd style) in
6060       pr "  r = do_%s " name;
6061       generate_c_call_args (fst style, args');
6062       pr ";\n";
6063
6064       (match fst style with
6065        | RErr | RInt _ | RInt64 _ | RBool _
6066        | RConstString _ | RConstOptString _
6067        | RString _ | RStringList _ | RHashtable _
6068        | RStruct (_, _) | RStructList (_, _) ->
6069            pr "  if (r == %s)\n" error_code;
6070            pr "    /* do_%s has already called reply_with_error */\n" name;
6071            pr "    goto done;\n";
6072            pr "\n"
6073        | RBufferOut _ ->
6074            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6075            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6076            pr "   */\n";
6077            pr "  if (size == 1 && r == %s)\n" error_code;
6078            pr "    /* do_%s has already called reply_with_error */\n" name;
6079            pr "    goto done;\n";
6080            pr "\n"
6081       );
6082
6083       (* If there are any FileOut parameters, then the impl must
6084        * send its own reply.
6085        *)
6086       let no_reply =
6087         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6088       if no_reply then
6089         pr "  /* do_%s has already sent a reply */\n" name
6090       else (
6091         match fst style with
6092         | RErr -> pr "  reply (NULL, NULL);\n"
6093         | RInt n | RInt64 n | RBool n ->
6094             pr "  struct guestfs_%s_ret ret;\n" name;
6095             pr "  ret.%s = r;\n" n;
6096             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6097               name
6098         | RConstString _ | RConstOptString _ ->
6099             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6100         | RString n ->
6101             pr "  struct guestfs_%s_ret ret;\n" name;
6102             pr "  ret.%s = r;\n" n;
6103             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6104               name;
6105             pr "  free (r);\n"
6106         | RStringList n | RHashtable n ->
6107             pr "  struct guestfs_%s_ret ret;\n" name;
6108             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6109             pr "  ret.%s.%s_val = r;\n" n n;
6110             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6111               name;
6112             pr "  free_strings (r);\n"
6113         | RStruct (n, _) ->
6114             pr "  struct guestfs_%s_ret ret;\n" name;
6115             pr "  ret.%s = *r;\n" n;
6116             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6117               name;
6118             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6119               name
6120         | RStructList (n, _) ->
6121             pr "  struct guestfs_%s_ret ret;\n" name;
6122             pr "  ret.%s = *r;\n" n;
6123             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6124               name;
6125             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6126               name
6127         | RBufferOut n ->
6128             pr "  struct guestfs_%s_ret ret;\n" name;
6129             pr "  ret.%s.%s_val = r;\n" n n;
6130             pr "  ret.%s.%s_len = size;\n" n n;
6131             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6132               name;
6133             pr "  free (r);\n"
6134       );
6135
6136       (* Free the args. *)
6137       (match snd style with
6138        | [] ->
6139            pr "done: ;\n";
6140        | _ ->
6141            pr "done:\n";
6142            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6143              name
6144       );
6145
6146       pr "}\n\n";
6147   ) daemon_functions;
6148
6149   (* Dispatch function. *)
6150   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6151   pr "{\n";
6152   pr "  switch (proc_nr) {\n";
6153
6154   List.iter (
6155     fun (name, style, _, _, _, _, _) ->
6156       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6157       pr "      %s_stub (xdr_in);\n" name;
6158       pr "      break;\n"
6159   ) daemon_functions;
6160
6161   pr "    default:\n";
6162   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";
6163   pr "  }\n";
6164   pr "}\n";
6165   pr "\n";
6166
6167   (* LVM columns and tokenization functions. *)
6168   (* XXX This generates crap code.  We should rethink how we
6169    * do this parsing.
6170    *)
6171   List.iter (
6172     function
6173     | typ, cols ->
6174         pr "static const char *lvm_%s_cols = \"%s\";\n"
6175           typ (String.concat "," (List.map fst cols));
6176         pr "\n";
6177
6178         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6179         pr "{\n";
6180         pr "  char *tok, *p, *next;\n";
6181         pr "  int i, j;\n";
6182         pr "\n";
6183         (*
6184           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6185           pr "\n";
6186         *)
6187         pr "  if (!str) {\n";
6188         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6189         pr "    return -1;\n";
6190         pr "  }\n";
6191         pr "  if (!*str || c_isspace (*str)) {\n";
6192         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6193         pr "    return -1;\n";
6194         pr "  }\n";
6195         pr "  tok = str;\n";
6196         List.iter (
6197           fun (name, coltype) ->
6198             pr "  if (!tok) {\n";
6199             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6200             pr "    return -1;\n";
6201             pr "  }\n";
6202             pr "  p = strchrnul (tok, ',');\n";
6203             pr "  if (*p) next = p+1; else next = NULL;\n";
6204             pr "  *p = '\\0';\n";
6205             (match coltype with
6206              | FString ->
6207                  pr "  r->%s = strdup (tok);\n" name;
6208                  pr "  if (r->%s == NULL) {\n" name;
6209                  pr "    perror (\"strdup\");\n";
6210                  pr "    return -1;\n";
6211                  pr "  }\n"
6212              | FUUID ->
6213                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6214                  pr "    if (tok[j] == '\\0') {\n";
6215                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6216                  pr "      return -1;\n";
6217                  pr "    } else if (tok[j] != '-')\n";
6218                  pr "      r->%s[i++] = tok[j];\n" name;
6219                  pr "  }\n";
6220              | FBytes ->
6221                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6222                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6223                  pr "    return -1;\n";
6224                  pr "  }\n";
6225              | FInt64 ->
6226                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6227                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6228                  pr "    return -1;\n";
6229                  pr "  }\n";
6230              | FOptPercent ->
6231                  pr "  if (tok[0] == '\\0')\n";
6232                  pr "    r->%s = -1;\n" name;
6233                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6234                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6235                  pr "    return -1;\n";
6236                  pr "  }\n";
6237              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6238                  assert false (* can never be an LVM column *)
6239             );
6240             pr "  tok = next;\n";
6241         ) cols;
6242
6243         pr "  if (tok != NULL) {\n";
6244         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6245         pr "    return -1;\n";
6246         pr "  }\n";
6247         pr "  return 0;\n";
6248         pr "}\n";
6249         pr "\n";
6250
6251         pr "guestfs_int_lvm_%s_list *\n" typ;
6252         pr "parse_command_line_%ss (void)\n" typ;
6253         pr "{\n";
6254         pr "  char *out, *err;\n";
6255         pr "  char *p, *pend;\n";
6256         pr "  int r, i;\n";
6257         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6258         pr "  void *newp;\n";
6259         pr "\n";
6260         pr "  ret = malloc (sizeof *ret);\n";
6261         pr "  if (!ret) {\n";
6262         pr "    reply_with_perror (\"malloc\");\n";
6263         pr "    return NULL;\n";
6264         pr "  }\n";
6265         pr "\n";
6266         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6267         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6268         pr "\n";
6269         pr "  r = command (&out, &err,\n";
6270         pr "           \"lvm\", \"%ss\",\n" typ;
6271         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6272         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6273         pr "  if (r == -1) {\n";
6274         pr "    reply_with_error (\"%%s\", err);\n";
6275         pr "    free (out);\n";
6276         pr "    free (err);\n";
6277         pr "    free (ret);\n";
6278         pr "    return NULL;\n";
6279         pr "  }\n";
6280         pr "\n";
6281         pr "  free (err);\n";
6282         pr "\n";
6283         pr "  /* Tokenize each line of the output. */\n";
6284         pr "  p = out;\n";
6285         pr "  i = 0;\n";
6286         pr "  while (p) {\n";
6287         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6288         pr "    if (pend) {\n";
6289         pr "      *pend = '\\0';\n";
6290         pr "      pend++;\n";
6291         pr "    }\n";
6292         pr "\n";
6293         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6294         pr "      p++;\n";
6295         pr "\n";
6296         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6297         pr "      p = pend;\n";
6298         pr "      continue;\n";
6299         pr "    }\n";
6300         pr "\n";
6301         pr "    /* Allocate some space to store this next entry. */\n";
6302         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6303         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6304         pr "    if (newp == NULL) {\n";
6305         pr "      reply_with_perror (\"realloc\");\n";
6306         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6307         pr "      free (ret);\n";
6308         pr "      free (out);\n";
6309         pr "      return NULL;\n";
6310         pr "    }\n";
6311         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6312         pr "\n";
6313         pr "    /* Tokenize the next entry. */\n";
6314         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6315         pr "    if (r == -1) {\n";
6316         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6317         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6318         pr "      free (ret);\n";
6319         pr "      free (out);\n";
6320         pr "      return NULL;\n";
6321         pr "    }\n";
6322         pr "\n";
6323         pr "    ++i;\n";
6324         pr "    p = pend;\n";
6325         pr "  }\n";
6326         pr "\n";
6327         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6328         pr "\n";
6329         pr "  free (out);\n";
6330         pr "  return ret;\n";
6331         pr "}\n"
6332
6333   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6334
6335 (* Generate a list of function names, for debugging in the daemon.. *)
6336 and generate_daemon_names () =
6337   generate_header CStyle GPLv2plus;
6338
6339   pr "#include <config.h>\n";
6340   pr "\n";
6341   pr "#include \"daemon.h\"\n";
6342   pr "\n";
6343
6344   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6345   pr "const char *function_names[] = {\n";
6346   List.iter (
6347     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6348   ) daemon_functions;
6349   pr "};\n";
6350
6351 (* Generate the optional groups for the daemon to implement
6352  * guestfs_available.
6353  *)
6354 and generate_daemon_optgroups_c () =
6355   generate_header CStyle GPLv2plus;
6356
6357   pr "#include <config.h>\n";
6358   pr "\n";
6359   pr "#include \"daemon.h\"\n";
6360   pr "#include \"optgroups.h\"\n";
6361   pr "\n";
6362
6363   pr "struct optgroup optgroups[] = {\n";
6364   List.iter (
6365     fun (group, _) ->
6366       pr "  { \"%s\", optgroup_%s_available },\n" group group
6367   ) optgroups;
6368   pr "  { NULL, NULL }\n";
6369   pr "};\n"
6370
6371 and generate_daemon_optgroups_h () =
6372   generate_header CStyle GPLv2plus;
6373
6374   List.iter (
6375     fun (group, _) ->
6376       pr "extern int optgroup_%s_available (void);\n" group
6377   ) optgroups
6378
6379 (* Generate the tests. *)
6380 and generate_tests () =
6381   generate_header CStyle GPLv2plus;
6382
6383   pr "\
6384 #include <stdio.h>
6385 #include <stdlib.h>
6386 #include <string.h>
6387 #include <unistd.h>
6388 #include <sys/types.h>
6389 #include <fcntl.h>
6390
6391 #include \"guestfs.h\"
6392 #include \"guestfs-internal.h\"
6393
6394 static guestfs_h *g;
6395 static int suppress_error = 0;
6396
6397 static void print_error (guestfs_h *g, void *data, const char *msg)
6398 {
6399   if (!suppress_error)
6400     fprintf (stderr, \"%%s\\n\", msg);
6401 }
6402
6403 /* FIXME: nearly identical code appears in fish.c */
6404 static void print_strings (char *const *argv)
6405 {
6406   int argc;
6407
6408   for (argc = 0; argv[argc] != NULL; ++argc)
6409     printf (\"\\t%%s\\n\", argv[argc]);
6410 }
6411
6412 /*
6413 static void print_table (char const *const *argv)
6414 {
6415   int i;
6416
6417   for (i = 0; argv[i] != NULL; i += 2)
6418     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6419 }
6420 */
6421
6422 ";
6423
6424   (* Generate a list of commands which are not tested anywhere. *)
6425   pr "static void no_test_warnings (void)\n";
6426   pr "{\n";
6427
6428   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6429   List.iter (
6430     fun (_, _, _, _, tests, _, _) ->
6431       let tests = filter_map (
6432         function
6433         | (_, (Always|If _|Unless _), test) -> Some test
6434         | (_, Disabled, _) -> None
6435       ) tests in
6436       let seq = List.concat (List.map seq_of_test tests) in
6437       let cmds_tested = List.map List.hd seq in
6438       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6439   ) all_functions;
6440
6441   List.iter (
6442     fun (name, _, _, _, _, _, _) ->
6443       if not (Hashtbl.mem hash name) then
6444         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6445   ) all_functions;
6446
6447   pr "}\n";
6448   pr "\n";
6449
6450   (* Generate the actual tests.  Note that we generate the tests
6451    * in reverse order, deliberately, so that (in general) the
6452    * newest tests run first.  This makes it quicker and easier to
6453    * debug them.
6454    *)
6455   let test_names =
6456     List.map (
6457       fun (name, _, _, flags, tests, _, _) ->
6458         mapi (generate_one_test name flags) tests
6459     ) (List.rev all_functions) in
6460   let test_names = List.concat test_names in
6461   let nr_tests = List.length test_names in
6462
6463   pr "\
6464 int main (int argc, char *argv[])
6465 {
6466   char c = 0;
6467   unsigned long int n_failed = 0;
6468   const char *filename;
6469   int fd;
6470   int nr_tests, test_num = 0;
6471
6472   setbuf (stdout, NULL);
6473
6474   no_test_warnings ();
6475
6476   g = guestfs_create ();
6477   if (g == NULL) {
6478     printf (\"guestfs_create FAILED\\n\");
6479     exit (EXIT_FAILURE);
6480   }
6481
6482   guestfs_set_error_handler (g, print_error, NULL);
6483
6484   guestfs_set_path (g, \"../appliance\");
6485
6486   filename = \"test1.img\";
6487   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6488   if (fd == -1) {
6489     perror (filename);
6490     exit (EXIT_FAILURE);
6491   }
6492   if (lseek (fd, %d, SEEK_SET) == -1) {
6493     perror (\"lseek\");
6494     close (fd);
6495     unlink (filename);
6496     exit (EXIT_FAILURE);
6497   }
6498   if (write (fd, &c, 1) == -1) {
6499     perror (\"write\");
6500     close (fd);
6501     unlink (filename);
6502     exit (EXIT_FAILURE);
6503   }
6504   if (close (fd) == -1) {
6505     perror (filename);
6506     unlink (filename);
6507     exit (EXIT_FAILURE);
6508   }
6509   if (guestfs_add_drive (g, filename) == -1) {
6510     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6511     exit (EXIT_FAILURE);
6512   }
6513
6514   filename = \"test2.img\";
6515   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6516   if (fd == -1) {
6517     perror (filename);
6518     exit (EXIT_FAILURE);
6519   }
6520   if (lseek (fd, %d, SEEK_SET) == -1) {
6521     perror (\"lseek\");
6522     close (fd);
6523     unlink (filename);
6524     exit (EXIT_FAILURE);
6525   }
6526   if (write (fd, &c, 1) == -1) {
6527     perror (\"write\");
6528     close (fd);
6529     unlink (filename);
6530     exit (EXIT_FAILURE);
6531   }
6532   if (close (fd) == -1) {
6533     perror (filename);
6534     unlink (filename);
6535     exit (EXIT_FAILURE);
6536   }
6537   if (guestfs_add_drive (g, filename) == -1) {
6538     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6539     exit (EXIT_FAILURE);
6540   }
6541
6542   filename = \"test3.img\";
6543   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6544   if (fd == -1) {
6545     perror (filename);
6546     exit (EXIT_FAILURE);
6547   }
6548   if (lseek (fd, %d, SEEK_SET) == -1) {
6549     perror (\"lseek\");
6550     close (fd);
6551     unlink (filename);
6552     exit (EXIT_FAILURE);
6553   }
6554   if (write (fd, &c, 1) == -1) {
6555     perror (\"write\");
6556     close (fd);
6557     unlink (filename);
6558     exit (EXIT_FAILURE);
6559   }
6560   if (close (fd) == -1) {
6561     perror (filename);
6562     unlink (filename);
6563     exit (EXIT_FAILURE);
6564   }
6565   if (guestfs_add_drive (g, filename) == -1) {
6566     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6567     exit (EXIT_FAILURE);
6568   }
6569
6570   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6571     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6572     exit (EXIT_FAILURE);
6573   }
6574
6575   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6576   alarm (600);
6577
6578   if (guestfs_launch (g) == -1) {
6579     printf (\"guestfs_launch FAILED\\n\");
6580     exit (EXIT_FAILURE);
6581   }
6582
6583   /* Cancel previous alarm. */
6584   alarm (0);
6585
6586   nr_tests = %d;
6587
6588 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6589
6590   iteri (
6591     fun i test_name ->
6592       pr "  test_num++;\n";
6593       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6594       pr "  if (%s () == -1) {\n" test_name;
6595       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6596       pr "    n_failed++;\n";
6597       pr "  }\n";
6598   ) test_names;
6599   pr "\n";
6600
6601   pr "  guestfs_close (g);\n";
6602   pr "  unlink (\"test1.img\");\n";
6603   pr "  unlink (\"test2.img\");\n";
6604   pr "  unlink (\"test3.img\");\n";
6605   pr "\n";
6606
6607   pr "  if (n_failed > 0) {\n";
6608   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6609   pr "    exit (EXIT_FAILURE);\n";
6610   pr "  }\n";
6611   pr "\n";
6612
6613   pr "  exit (EXIT_SUCCESS);\n";
6614   pr "}\n"
6615
6616 and generate_one_test name flags i (init, prereq, test) =
6617   let test_name = sprintf "test_%s_%d" name i in
6618
6619   pr "\
6620 static int %s_skip (void)
6621 {
6622   const char *str;
6623
6624   str = getenv (\"TEST_ONLY\");
6625   if (str)
6626     return strstr (str, \"%s\") == NULL;
6627   str = getenv (\"SKIP_%s\");
6628   if (str && STREQ (str, \"1\")) return 1;
6629   str = getenv (\"SKIP_TEST_%s\");
6630   if (str && STREQ (str, \"1\")) return 1;
6631   return 0;
6632 }
6633
6634 " test_name name (String.uppercase test_name) (String.uppercase name);
6635
6636   (match prereq with
6637    | Disabled | Always -> ()
6638    | If code | Unless code ->
6639        pr "static int %s_prereq (void)\n" test_name;
6640        pr "{\n";
6641        pr "  %s\n" code;
6642        pr "}\n";
6643        pr "\n";
6644   );
6645
6646   pr "\
6647 static int %s (void)
6648 {
6649   if (%s_skip ()) {
6650     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6651     return 0;
6652   }
6653
6654 " test_name test_name test_name;
6655
6656   (* Optional functions should only be tested if the relevant
6657    * support is available in the daemon.
6658    *)
6659   List.iter (
6660     function
6661     | Optional group ->
6662         pr "  {\n";
6663         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6664         pr "    int r;\n";
6665         pr "    suppress_error = 1;\n";
6666         pr "    r = guestfs_available (g, (char **) groups);\n";
6667         pr "    suppress_error = 0;\n";
6668         pr "    if (r == -1) {\n";
6669         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6670         pr "      return 0;\n";
6671         pr "    }\n";
6672         pr "  }\n";
6673     | _ -> ()
6674   ) flags;
6675
6676   (match prereq with
6677    | Disabled ->
6678        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6679    | If _ ->
6680        pr "  if (! %s_prereq ()) {\n" test_name;
6681        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6682        pr "    return 0;\n";
6683        pr "  }\n";
6684        pr "\n";
6685        generate_one_test_body name i test_name init test;
6686    | Unless _ ->
6687        pr "  if (%s_prereq ()) {\n" test_name;
6688        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6689        pr "    return 0;\n";
6690        pr "  }\n";
6691        pr "\n";
6692        generate_one_test_body name i test_name init test;
6693    | Always ->
6694        generate_one_test_body name i test_name init test
6695   );
6696
6697   pr "  return 0;\n";
6698   pr "}\n";
6699   pr "\n";
6700   test_name
6701
6702 and generate_one_test_body name i test_name init test =
6703   (match init with
6704    | InitNone (* XXX at some point, InitNone and InitEmpty became
6705                * folded together as the same thing.  Really we should
6706                * make InitNone do nothing at all, but the tests may
6707                * need to be checked to make sure this is OK.
6708                *)
6709    | InitEmpty ->
6710        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6711        List.iter (generate_test_command_call test_name)
6712          [["blockdev_setrw"; "/dev/sda"];
6713           ["umount_all"];
6714           ["lvm_remove_all"]]
6715    | InitPartition ->
6716        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6717        List.iter (generate_test_command_call test_name)
6718          [["blockdev_setrw"; "/dev/sda"];
6719           ["umount_all"];
6720           ["lvm_remove_all"];
6721           ["part_disk"; "/dev/sda"; "mbr"]]
6722    | InitBasicFS ->
6723        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6724        List.iter (generate_test_command_call test_name)
6725          [["blockdev_setrw"; "/dev/sda"];
6726           ["umount_all"];
6727           ["lvm_remove_all"];
6728           ["part_disk"; "/dev/sda"; "mbr"];
6729           ["mkfs"; "ext2"; "/dev/sda1"];
6730           ["mount_options"; ""; "/dev/sda1"; "/"]]
6731    | InitBasicFSonLVM ->
6732        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6733          test_name;
6734        List.iter (generate_test_command_call test_name)
6735          [["blockdev_setrw"; "/dev/sda"];
6736           ["umount_all"];
6737           ["lvm_remove_all"];
6738           ["part_disk"; "/dev/sda"; "mbr"];
6739           ["pvcreate"; "/dev/sda1"];
6740           ["vgcreate"; "VG"; "/dev/sda1"];
6741           ["lvcreate"; "LV"; "VG"; "8"];
6742           ["mkfs"; "ext2"; "/dev/VG/LV"];
6743           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6744    | InitISOFS ->
6745        pr "  /* InitISOFS for %s */\n" test_name;
6746        List.iter (generate_test_command_call test_name)
6747          [["blockdev_setrw"; "/dev/sda"];
6748           ["umount_all"];
6749           ["lvm_remove_all"];
6750           ["mount_ro"; "/dev/sdd"; "/"]]
6751   );
6752
6753   let get_seq_last = function
6754     | [] ->
6755         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6756           test_name
6757     | seq ->
6758         let seq = List.rev seq in
6759         List.rev (List.tl seq), List.hd seq
6760   in
6761
6762   match test with
6763   | TestRun seq ->
6764       pr "  /* TestRun for %s (%d) */\n" name i;
6765       List.iter (generate_test_command_call test_name) seq
6766   | TestOutput (seq, expected) ->
6767       pr "  /* TestOutput for %s (%d) */\n" name i;
6768       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6769       let seq, last = get_seq_last seq in
6770       let test () =
6771         pr "    if (STRNEQ (r, expected)) {\n";
6772         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6773         pr "      return -1;\n";
6774         pr "    }\n"
6775       in
6776       List.iter (generate_test_command_call test_name) seq;
6777       generate_test_command_call ~test test_name last
6778   | TestOutputList (seq, expected) ->
6779       pr "  /* TestOutputList for %s (%d) */\n" name i;
6780       let seq, last = get_seq_last seq in
6781       let test () =
6782         iteri (
6783           fun i str ->
6784             pr "    if (!r[%d]) {\n" i;
6785             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6786             pr "      print_strings (r);\n";
6787             pr "      return -1;\n";
6788             pr "    }\n";
6789             pr "    {\n";
6790             pr "      const char *expected = \"%s\";\n" (c_quote str);
6791             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6792             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6793             pr "        return -1;\n";
6794             pr "      }\n";
6795             pr "    }\n"
6796         ) expected;
6797         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6798         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6799           test_name;
6800         pr "      print_strings (r);\n";
6801         pr "      return -1;\n";
6802         pr "    }\n"
6803       in
6804       List.iter (generate_test_command_call test_name) seq;
6805       generate_test_command_call ~test test_name last
6806   | TestOutputListOfDevices (seq, expected) ->
6807       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6808       let seq, last = get_seq_last seq in
6809       let test () =
6810         iteri (
6811           fun i str ->
6812             pr "    if (!r[%d]) {\n" i;
6813             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6814             pr "      print_strings (r);\n";
6815             pr "      return -1;\n";
6816             pr "    }\n";
6817             pr "    {\n";
6818             pr "      const char *expected = \"%s\";\n" (c_quote str);
6819             pr "      r[%d][5] = 's';\n" i;
6820             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6821             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6822             pr "        return -1;\n";
6823             pr "      }\n";
6824             pr "    }\n"
6825         ) expected;
6826         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6827         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6828           test_name;
6829         pr "      print_strings (r);\n";
6830         pr "      return -1;\n";
6831         pr "    }\n"
6832       in
6833       List.iter (generate_test_command_call test_name) seq;
6834       generate_test_command_call ~test test_name last
6835   | TestOutputInt (seq, expected) ->
6836       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6837       let seq, last = get_seq_last seq in
6838       let test () =
6839         pr "    if (r != %d) {\n" expected;
6840         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6841           test_name expected;
6842         pr "               (int) r);\n";
6843         pr "      return -1;\n";
6844         pr "    }\n"
6845       in
6846       List.iter (generate_test_command_call test_name) seq;
6847       generate_test_command_call ~test test_name last
6848   | TestOutputIntOp (seq, op, expected) ->
6849       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6850       let seq, last = get_seq_last seq in
6851       let test () =
6852         pr "    if (! (r %s %d)) {\n" op expected;
6853         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6854           test_name op expected;
6855         pr "               (int) r);\n";
6856         pr "      return -1;\n";
6857         pr "    }\n"
6858       in
6859       List.iter (generate_test_command_call test_name) seq;
6860       generate_test_command_call ~test test_name last
6861   | TestOutputTrue seq ->
6862       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6863       let seq, last = get_seq_last seq in
6864       let test () =
6865         pr "    if (!r) {\n";
6866         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6867           test_name;
6868         pr "      return -1;\n";
6869         pr "    }\n"
6870       in
6871       List.iter (generate_test_command_call test_name) seq;
6872       generate_test_command_call ~test test_name last
6873   | TestOutputFalse seq ->
6874       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6875       let seq, last = get_seq_last seq in
6876       let test () =
6877         pr "    if (r) {\n";
6878         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6879           test_name;
6880         pr "      return -1;\n";
6881         pr "    }\n"
6882       in
6883       List.iter (generate_test_command_call test_name) seq;
6884       generate_test_command_call ~test test_name last
6885   | TestOutputLength (seq, expected) ->
6886       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6887       let seq, last = get_seq_last seq in
6888       let test () =
6889         pr "    int j;\n";
6890         pr "    for (j = 0; j < %d; ++j)\n" expected;
6891         pr "      if (r[j] == NULL) {\n";
6892         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6893           test_name;
6894         pr "        print_strings (r);\n";
6895         pr "        return -1;\n";
6896         pr "      }\n";
6897         pr "    if (r[j] != NULL) {\n";
6898         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6899           test_name;
6900         pr "      print_strings (r);\n";
6901         pr "      return -1;\n";
6902         pr "    }\n"
6903       in
6904       List.iter (generate_test_command_call test_name) seq;
6905       generate_test_command_call ~test test_name last
6906   | TestOutputBuffer (seq, expected) ->
6907       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6908       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6909       let seq, last = get_seq_last seq in
6910       let len = String.length expected in
6911       let test () =
6912         pr "    if (size != %d) {\n" len;
6913         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6914         pr "      return -1;\n";
6915         pr "    }\n";
6916         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6917         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6918         pr "      return -1;\n";
6919         pr "    }\n"
6920       in
6921       List.iter (generate_test_command_call test_name) seq;
6922       generate_test_command_call ~test test_name last
6923   | TestOutputStruct (seq, checks) ->
6924       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6925       let seq, last = get_seq_last seq in
6926       let test () =
6927         List.iter (
6928           function
6929           | CompareWithInt (field, expected) ->
6930               pr "    if (r->%s != %d) {\n" field expected;
6931               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6932                 test_name field expected;
6933               pr "               (int) r->%s);\n" field;
6934               pr "      return -1;\n";
6935               pr "    }\n"
6936           | CompareWithIntOp (field, op, expected) ->
6937               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6938               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6939                 test_name field op expected;
6940               pr "               (int) r->%s);\n" field;
6941               pr "      return -1;\n";
6942               pr "    }\n"
6943           | CompareWithString (field, expected) ->
6944               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6945               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6946                 test_name field expected;
6947               pr "               r->%s);\n" field;
6948               pr "      return -1;\n";
6949               pr "    }\n"
6950           | CompareFieldsIntEq (field1, field2) ->
6951               pr "    if (r->%s != r->%s) {\n" field1 field2;
6952               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6953                 test_name field1 field2;
6954               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6955               pr "      return -1;\n";
6956               pr "    }\n"
6957           | CompareFieldsStrEq (field1, field2) ->
6958               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6959               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6960                 test_name field1 field2;
6961               pr "               r->%s, r->%s);\n" field1 field2;
6962               pr "      return -1;\n";
6963               pr "    }\n"
6964         ) checks
6965       in
6966       List.iter (generate_test_command_call test_name) seq;
6967       generate_test_command_call ~test test_name last
6968   | TestLastFail seq ->
6969       pr "  /* TestLastFail for %s (%d) */\n" name i;
6970       let seq, last = get_seq_last seq in
6971       List.iter (generate_test_command_call test_name) seq;
6972       generate_test_command_call test_name ~expect_error:true last
6973
6974 (* Generate the code to run a command, leaving the result in 'r'.
6975  * If you expect to get an error then you should set expect_error:true.
6976  *)
6977 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6978   match cmd with
6979   | [] -> assert false
6980   | name :: args ->
6981       (* Look up the command to find out what args/ret it has. *)
6982       let style =
6983         try
6984           let _, style, _, _, _, _, _ =
6985             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6986           style
6987         with Not_found ->
6988           failwithf "%s: in test, command %s was not found" test_name name in
6989
6990       if List.length (snd style) <> List.length args then
6991         failwithf "%s: in test, wrong number of args given to %s"
6992           test_name name;
6993
6994       pr "  {\n";
6995
6996       List.iter (
6997         function
6998         | OptString n, "NULL" -> ()
6999         | Pathname n, arg
7000         | Device n, arg
7001         | Dev_or_Path n, arg
7002         | String n, arg
7003         | OptString n, arg ->
7004             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7005         | Int _, _
7006         | Int64 _, _
7007         | Bool _, _
7008         | FileIn _, _ | FileOut _, _ -> ()
7009         | StringList n, "" | DeviceList n, "" ->
7010             pr "    const char *const %s[1] = { NULL };\n" n
7011         | StringList n, arg | DeviceList n, arg ->
7012             let strs = string_split " " arg in
7013             iteri (
7014               fun i str ->
7015                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7016             ) strs;
7017             pr "    const char *const %s[] = {\n" n;
7018             iteri (
7019               fun i _ -> pr "      %s_%d,\n" n i
7020             ) strs;
7021             pr "      NULL\n";
7022             pr "    };\n";
7023       ) (List.combine (snd style) args);
7024
7025       let error_code =
7026         match fst style with
7027         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7028         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7029         | RConstString _ | RConstOptString _ ->
7030             pr "    const char *r;\n"; "NULL"
7031         | RString _ -> pr "    char *r;\n"; "NULL"
7032         | RStringList _ | RHashtable _ ->
7033             pr "    char **r;\n";
7034             pr "    int i;\n";
7035             "NULL"
7036         | RStruct (_, typ) ->
7037             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7038         | RStructList (_, typ) ->
7039             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7040         | RBufferOut _ ->
7041             pr "    char *r;\n";
7042             pr "    size_t size;\n";
7043             "NULL" in
7044
7045       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7046       pr "    r = guestfs_%s (g" name;
7047
7048       (* Generate the parameters. *)
7049       List.iter (
7050         function
7051         | OptString _, "NULL" -> pr ", NULL"
7052         | Pathname n, _
7053         | Device n, _ | Dev_or_Path n, _
7054         | String n, _
7055         | OptString n, _ ->
7056             pr ", %s" n
7057         | FileIn _, arg | FileOut _, arg ->
7058             pr ", \"%s\"" (c_quote arg)
7059         | StringList n, _ | DeviceList n, _ ->
7060             pr ", (char **) %s" n
7061         | Int _, arg ->
7062             let i =
7063               try int_of_string arg
7064               with Failure "int_of_string" ->
7065                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7066             pr ", %d" i
7067         | Int64 _, arg ->
7068             let i =
7069               try Int64.of_string arg
7070               with Failure "int_of_string" ->
7071                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7072             pr ", %Ld" i
7073         | Bool _, arg ->
7074             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7075       ) (List.combine (snd style) args);
7076
7077       (match fst style with
7078        | RBufferOut _ -> pr ", &size"
7079        | _ -> ()
7080       );
7081
7082       pr ");\n";
7083
7084       if not expect_error then
7085         pr "    if (r == %s)\n" error_code
7086       else
7087         pr "    if (r != %s)\n" error_code;
7088       pr "      return -1;\n";
7089
7090       (* Insert the test code. *)
7091       (match test with
7092        | None -> ()
7093        | Some f -> f ()
7094       );
7095
7096       (match fst style with
7097        | RErr | RInt _ | RInt64 _ | RBool _
7098        | RConstString _ | RConstOptString _ -> ()
7099        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7100        | RStringList _ | RHashtable _ ->
7101            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7102            pr "      free (r[i]);\n";
7103            pr "    free (r);\n"
7104        | RStruct (_, typ) ->
7105            pr "    guestfs_free_%s (r);\n" typ
7106        | RStructList (_, typ) ->
7107            pr "    guestfs_free_%s_list (r);\n" typ
7108       );
7109
7110       pr "  }\n"
7111
7112 and c_quote str =
7113   let str = replace_str str "\r" "\\r" in
7114   let str = replace_str str "\n" "\\n" in
7115   let str = replace_str str "\t" "\\t" in
7116   let str = replace_str str "\000" "\\0" in
7117   str
7118
7119 (* Generate a lot of different functions for guestfish. *)
7120 and generate_fish_cmds () =
7121   generate_header CStyle GPLv2plus;
7122
7123   let all_functions =
7124     List.filter (
7125       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7126     ) all_functions in
7127   let all_functions_sorted =
7128     List.filter (
7129       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7130     ) all_functions_sorted in
7131
7132   pr "#include <config.h>\n";
7133   pr "\n";
7134   pr "#include <stdio.h>\n";
7135   pr "#include <stdlib.h>\n";
7136   pr "#include <string.h>\n";
7137   pr "#include <inttypes.h>\n";
7138   pr "\n";
7139   pr "#include <guestfs.h>\n";
7140   pr "#include \"c-ctype.h\"\n";
7141   pr "#include \"full-write.h\"\n";
7142   pr "#include \"xstrtol.h\"\n";
7143   pr "#include \"fish.h\"\n";
7144   pr "\n";
7145
7146   (* list_commands function, which implements guestfish -h *)
7147   pr "void list_commands (void)\n";
7148   pr "{\n";
7149   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7150   pr "  list_builtin_commands ();\n";
7151   List.iter (
7152     fun (name, _, _, flags, _, shortdesc, _) ->
7153       let name = replace_char name '_' '-' in
7154       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7155         name shortdesc
7156   ) all_functions_sorted;
7157   pr "  printf (\"    %%s\\n\",";
7158   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7159   pr "}\n";
7160   pr "\n";
7161
7162   (* display_command function, which implements guestfish -h cmd *)
7163   pr "void display_command (const char *cmd)\n";
7164   pr "{\n";
7165   List.iter (
7166     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7167       let name2 = replace_char name '_' '-' in
7168       let alias =
7169         try find_map (function FishAlias n -> Some n | _ -> None) flags
7170         with Not_found -> name in
7171       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7172       let synopsis =
7173         match snd style with
7174         | [] -> name2
7175         | args ->
7176             sprintf "%s %s"
7177               name2 (String.concat " " (List.map name_of_argt args)) in
7178
7179       let warnings =
7180         if List.mem ProtocolLimitWarning flags then
7181           ("\n\n" ^ protocol_limit_warning)
7182         else "" in
7183
7184       (* For DangerWillRobinson commands, we should probably have
7185        * guestfish prompt before allowing you to use them (especially
7186        * in interactive mode). XXX
7187        *)
7188       let warnings =
7189         warnings ^
7190           if List.mem DangerWillRobinson flags then
7191             ("\n\n" ^ danger_will_robinson)
7192           else "" in
7193
7194       let warnings =
7195         warnings ^
7196           match deprecation_notice flags with
7197           | None -> ""
7198           | Some txt -> "\n\n" ^ txt in
7199
7200       let describe_alias =
7201         if name <> alias then
7202           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7203         else "" in
7204
7205       pr "  if (";
7206       pr "STRCASEEQ (cmd, \"%s\")" name;
7207       if name <> name2 then
7208         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7209       if name <> alias then
7210         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7211       pr ")\n";
7212       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7213         name2 shortdesc
7214         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7215          "=head1 DESCRIPTION\n\n" ^
7216          longdesc ^ warnings ^ describe_alias);
7217       pr "  else\n"
7218   ) all_functions;
7219   pr "    display_builtin_command (cmd);\n";
7220   pr "}\n";
7221   pr "\n";
7222
7223   let emit_print_list_function typ =
7224     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7225       typ typ typ;
7226     pr "{\n";
7227     pr "  unsigned int i;\n";
7228     pr "\n";
7229     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7230     pr "    printf (\"[%%d] = {\\n\", i);\n";
7231     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7232     pr "    printf (\"}\\n\");\n";
7233     pr "  }\n";
7234     pr "}\n";
7235     pr "\n";
7236   in
7237
7238   (* print_* functions *)
7239   List.iter (
7240     fun (typ, cols) ->
7241       let needs_i =
7242         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7243
7244       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7245       pr "{\n";
7246       if needs_i then (
7247         pr "  unsigned int i;\n";
7248         pr "\n"
7249       );
7250       List.iter (
7251         function
7252         | name, FString ->
7253             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7254         | name, FUUID ->
7255             pr "  printf (\"%%s%s: \", indent);\n" name;
7256             pr "  for (i = 0; i < 32; ++i)\n";
7257             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7258             pr "  printf (\"\\n\");\n"
7259         | name, FBuffer ->
7260             pr "  printf (\"%%s%s: \", indent);\n" name;
7261             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7262             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7263             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7264             pr "    else\n";
7265             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7266             pr "  printf (\"\\n\");\n"
7267         | name, (FUInt64|FBytes) ->
7268             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7269               name typ name
7270         | name, FInt64 ->
7271             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7272               name typ name
7273         | name, FUInt32 ->
7274             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7275               name typ name
7276         | name, FInt32 ->
7277             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7278               name typ name
7279         | name, FChar ->
7280             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7281               name typ name
7282         | name, FOptPercent ->
7283             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7284               typ name name typ name;
7285             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7286       ) cols;
7287       pr "}\n";
7288       pr "\n";
7289   ) structs;
7290
7291   (* Emit a print_TYPE_list function definition only if that function is used. *)
7292   List.iter (
7293     function
7294     | typ, (RStructListOnly | RStructAndList) ->
7295         (* generate the function for typ *)
7296         emit_print_list_function typ
7297     | typ, _ -> () (* empty *)
7298   ) (rstructs_used_by all_functions);
7299
7300   (* Emit a print_TYPE function definition only if that function is used. *)
7301   List.iter (
7302     function
7303     | typ, (RStructOnly | RStructAndList) ->
7304         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7305         pr "{\n";
7306         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7307         pr "}\n";
7308         pr "\n";
7309     | typ, _ -> () (* empty *)
7310   ) (rstructs_used_by all_functions);
7311
7312   (* run_<action> actions *)
7313   List.iter (
7314     fun (name, style, _, flags, _, _, _) ->
7315       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7316       pr "{\n";
7317       (match fst style with
7318        | RErr
7319        | RInt _
7320        | RBool _ -> pr "  int r;\n"
7321        | RInt64 _ -> pr "  int64_t r;\n"
7322        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7323        | RString _ -> pr "  char *r;\n"
7324        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7325        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7326        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7327        | RBufferOut _ ->
7328            pr "  char *r;\n";
7329            pr "  size_t size;\n";
7330       );
7331       List.iter (
7332         function
7333         | Device n
7334         | String n
7335         | OptString n
7336         | FileIn n
7337         | FileOut n -> pr "  const char *%s;\n" n
7338         | Pathname n
7339         | Dev_or_Path n -> pr "  char *%s;\n" n
7340         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7341         | Bool n -> pr "  int %s;\n" n
7342         | Int n -> pr "  int %s;\n" n
7343         | Int64 n -> pr "  int64_t %s;\n" n
7344       ) (snd style);
7345
7346       (* Check and convert parameters. *)
7347       let argc_expected = List.length (snd style) in
7348       pr "  if (argc != %d) {\n" argc_expected;
7349       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7350         argc_expected;
7351       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7352       pr "    return -1;\n";
7353       pr "  }\n";
7354
7355       let parse_integer fn fntyp rtyp range name i =
7356         pr "  {\n";
7357         pr "    strtol_error xerr;\n";
7358         pr "    %s r;\n" fntyp;
7359         pr "\n";
7360         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7361         pr "    if (xerr != LONGINT_OK) {\n";
7362         pr "      fprintf (stderr,\n";
7363         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7364         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7365         pr "      return -1;\n";
7366         pr "    }\n";
7367         (match range with
7368          | None -> ()
7369          | Some (min, max, comment) ->
7370              pr "    /* %s */\n" comment;
7371              pr "    if (r < %s || r > %s) {\n" min max;
7372              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7373                name;
7374              pr "      return -1;\n";
7375              pr "    }\n";
7376              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7377         );
7378         pr "    %s = r;\n" name;
7379         pr "  }\n";
7380       in
7381
7382       iteri (
7383         fun i ->
7384           function
7385           | Device name
7386           | String name ->
7387               pr "  %s = argv[%d];\n" name i
7388           | Pathname name
7389           | Dev_or_Path name ->
7390               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7391               pr "  if (%s == NULL) return -1;\n" name
7392           | OptString name ->
7393               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7394                 name i i
7395           | FileIn name ->
7396               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7397                 name i i
7398           | FileOut name ->
7399               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7400                 name i i
7401           | StringList name | DeviceList name ->
7402               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7403               pr "  if (%s == NULL) return -1;\n" name;
7404           | Bool name ->
7405               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7406           | Int name ->
7407               let range =
7408                 let min = "(-(2LL<<30))"
7409                 and max = "((2LL<<30)-1)"
7410                 and comment =
7411                   "The Int type in the generator is a signed 31 bit int." in
7412                 Some (min, max, comment) in
7413               parse_integer "xstrtoll" "long long" "int" range name i
7414           | Int64 name ->
7415               parse_integer "xstrtoll" "long long" "int64_t" None name i
7416       ) (snd style);
7417
7418       (* Call C API function. *)
7419       let fn =
7420         try find_map (function FishAction n -> Some n | _ -> None) flags
7421         with Not_found -> sprintf "guestfs_%s" name in
7422       pr "  r = %s " fn;
7423       generate_c_call_args ~handle:"g" style;
7424       pr ";\n";
7425
7426       List.iter (
7427         function
7428         | Device name | String name
7429         | OptString name | FileIn name | FileOut name | Bool name
7430         | Int name | Int64 name -> ()
7431         | Pathname name | Dev_or_Path name ->
7432             pr "  free (%s);\n" name
7433         | StringList name | DeviceList name ->
7434             pr "  free_strings (%s);\n" name
7435       ) (snd style);
7436
7437       (* Check return value for errors and display command results. *)
7438       (match fst style with
7439        | RErr -> pr "  return r;\n"
7440        | RInt _ ->
7441            pr "  if (r == -1) return -1;\n";
7442            pr "  printf (\"%%d\\n\", r);\n";
7443            pr "  return 0;\n"
7444        | RInt64 _ ->
7445            pr "  if (r == -1) return -1;\n";
7446            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7447            pr "  return 0;\n"
7448        | RBool _ ->
7449            pr "  if (r == -1) return -1;\n";
7450            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7451            pr "  return 0;\n"
7452        | RConstString _ ->
7453            pr "  if (r == NULL) return -1;\n";
7454            pr "  printf (\"%%s\\n\", r);\n";
7455            pr "  return 0;\n"
7456        | RConstOptString _ ->
7457            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7458            pr "  return 0;\n"
7459        | RString _ ->
7460            pr "  if (r == NULL) return -1;\n";
7461            pr "  printf (\"%%s\\n\", r);\n";
7462            pr "  free (r);\n";
7463            pr "  return 0;\n"
7464        | RStringList _ ->
7465            pr "  if (r == NULL) return -1;\n";
7466            pr "  print_strings (r);\n";
7467            pr "  free_strings (r);\n";
7468            pr "  return 0;\n"
7469        | RStruct (_, typ) ->
7470            pr "  if (r == NULL) return -1;\n";
7471            pr "  print_%s (r);\n" typ;
7472            pr "  guestfs_free_%s (r);\n" typ;
7473            pr "  return 0;\n"
7474        | RStructList (_, typ) ->
7475            pr "  if (r == NULL) return -1;\n";
7476            pr "  print_%s_list (r);\n" typ;
7477            pr "  guestfs_free_%s_list (r);\n" typ;
7478            pr "  return 0;\n"
7479        | RHashtable _ ->
7480            pr "  if (r == NULL) return -1;\n";
7481            pr "  print_table (r);\n";
7482            pr "  free_strings (r);\n";
7483            pr "  return 0;\n"
7484        | RBufferOut _ ->
7485            pr "  if (r == NULL) return -1;\n";
7486            pr "  if (full_write (1, r, size) != size) {\n";
7487            pr "    perror (\"write\");\n";
7488            pr "    free (r);\n";
7489            pr "    return -1;\n";
7490            pr "  }\n";
7491            pr "  free (r);\n";
7492            pr "  return 0;\n"
7493       );
7494       pr "}\n";
7495       pr "\n"
7496   ) all_functions;
7497
7498   (* run_action function *)
7499   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7500   pr "{\n";
7501   List.iter (
7502     fun (name, _, _, flags, _, _, _) ->
7503       let name2 = replace_char name '_' '-' in
7504       let alias =
7505         try find_map (function FishAlias n -> Some n | _ -> None) flags
7506         with Not_found -> name in
7507       pr "  if (";
7508       pr "STRCASEEQ (cmd, \"%s\")" name;
7509       if name <> name2 then
7510         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7511       if name <> alias then
7512         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7513       pr ")\n";
7514       pr "    return run_%s (cmd, argc, argv);\n" name;
7515       pr "  else\n";
7516   ) all_functions;
7517   pr "    {\n";
7518   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7519   pr "      if (command_num == 1)\n";
7520   pr "        extended_help_message ();\n";
7521   pr "      return -1;\n";
7522   pr "    }\n";
7523   pr "  return 0;\n";
7524   pr "}\n";
7525   pr "\n"
7526
7527 (* Readline completion for guestfish. *)
7528 and generate_fish_completion () =
7529   generate_header CStyle GPLv2plus;
7530
7531   let all_functions =
7532     List.filter (
7533       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7534     ) all_functions in
7535
7536   pr "\
7537 #include <config.h>
7538
7539 #include <stdio.h>
7540 #include <stdlib.h>
7541 #include <string.h>
7542
7543 #ifdef HAVE_LIBREADLINE
7544 #include <readline/readline.h>
7545 #endif
7546
7547 #include \"fish.h\"
7548
7549 #ifdef HAVE_LIBREADLINE
7550
7551 static const char *const commands[] = {
7552   BUILTIN_COMMANDS_FOR_COMPLETION,
7553 ";
7554
7555   (* Get the commands, including the aliases.  They don't need to be
7556    * sorted - the generator() function just does a dumb linear search.
7557    *)
7558   let commands =
7559     List.map (
7560       fun (name, _, _, flags, _, _, _) ->
7561         let name2 = replace_char name '_' '-' in
7562         let alias =
7563           try find_map (function FishAlias n -> Some n | _ -> None) flags
7564           with Not_found -> name in
7565
7566         if name <> alias then [name2; alias] else [name2]
7567     ) all_functions in
7568   let commands = List.flatten commands in
7569
7570   List.iter (pr "  \"%s\",\n") commands;
7571
7572   pr "  NULL
7573 };
7574
7575 static char *
7576 generator (const char *text, int state)
7577 {
7578   static int index, len;
7579   const char *name;
7580
7581   if (!state) {
7582     index = 0;
7583     len = strlen (text);
7584   }
7585
7586   rl_attempted_completion_over = 1;
7587
7588   while ((name = commands[index]) != NULL) {
7589     index++;
7590     if (STRCASEEQLEN (name, text, len))
7591       return strdup (name);
7592   }
7593
7594   return NULL;
7595 }
7596
7597 #endif /* HAVE_LIBREADLINE */
7598
7599 #ifdef HAVE_RL_COMPLETION_MATCHES
7600 #define RL_COMPLETION_MATCHES rl_completion_matches
7601 #else
7602 #ifdef HAVE_COMPLETION_MATCHES
7603 #define RL_COMPLETION_MATCHES completion_matches
7604 #endif
7605 #endif /* else just fail if we don't have either symbol */
7606
7607 char **
7608 do_completion (const char *text, int start, int end)
7609 {
7610   char **matches = NULL;
7611
7612 #ifdef HAVE_LIBREADLINE
7613   rl_completion_append_character = ' ';
7614
7615   if (start == 0)
7616     matches = RL_COMPLETION_MATCHES (text, generator);
7617   else if (complete_dest_paths)
7618     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7619 #endif
7620
7621   return matches;
7622 }
7623 ";
7624
7625 (* Generate the POD documentation for guestfish. *)
7626 and generate_fish_actions_pod () =
7627   let all_functions_sorted =
7628     List.filter (
7629       fun (_, _, _, flags, _, _, _) ->
7630         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7631     ) all_functions_sorted in
7632
7633   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7634
7635   List.iter (
7636     fun (name, style, _, flags, _, _, longdesc) ->
7637       let longdesc =
7638         Str.global_substitute rex (
7639           fun s ->
7640             let sub =
7641               try Str.matched_group 1 s
7642               with Not_found ->
7643                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7644             "C<" ^ replace_char sub '_' '-' ^ ">"
7645         ) longdesc in
7646       let name = replace_char name '_' '-' in
7647       let alias =
7648         try find_map (function FishAlias n -> Some n | _ -> None) flags
7649         with Not_found -> name in
7650
7651       pr "=head2 %s" name;
7652       if name <> alias then
7653         pr " | %s" alias;
7654       pr "\n";
7655       pr "\n";
7656       pr " %s" name;
7657       List.iter (
7658         function
7659         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7660         | OptString n -> pr " %s" n
7661         | StringList n | DeviceList n -> pr " '%s ...'" n
7662         | Bool _ -> pr " true|false"
7663         | Int n -> pr " %s" n
7664         | Int64 n -> pr " %s" n
7665         | FileIn n | FileOut n -> pr " (%s|-)" n
7666       ) (snd style);
7667       pr "\n";
7668       pr "\n";
7669       pr "%s\n\n" longdesc;
7670
7671       if List.exists (function FileIn _ | FileOut _ -> true
7672                       | _ -> false) (snd style) then
7673         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7674
7675       if List.mem ProtocolLimitWarning flags then
7676         pr "%s\n\n" protocol_limit_warning;
7677
7678       if List.mem DangerWillRobinson flags then
7679         pr "%s\n\n" danger_will_robinson;
7680
7681       match deprecation_notice flags with
7682       | None -> ()
7683       | Some txt -> pr "%s\n\n" txt
7684   ) all_functions_sorted
7685
7686 (* Generate a C function prototype. *)
7687 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7688     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7689     ?(prefix = "")
7690     ?handle name style =
7691   if extern then pr "extern ";
7692   if static then pr "static ";
7693   (match fst style with
7694    | RErr -> pr "int "
7695    | RInt _ -> pr "int "
7696    | RInt64 _ -> pr "int64_t "
7697    | RBool _ -> pr "int "
7698    | RConstString _ | RConstOptString _ -> pr "const char *"
7699    | RString _ | RBufferOut _ -> pr "char *"
7700    | RStringList _ | RHashtable _ -> pr "char **"
7701    | RStruct (_, typ) ->
7702        if not in_daemon then pr "struct guestfs_%s *" typ
7703        else pr "guestfs_int_%s *" typ
7704    | RStructList (_, typ) ->
7705        if not in_daemon then pr "struct guestfs_%s_list *" typ
7706        else pr "guestfs_int_%s_list *" typ
7707   );
7708   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7709   pr "%s%s (" prefix name;
7710   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7711     pr "void"
7712   else (
7713     let comma = ref false in
7714     (match handle with
7715      | None -> ()
7716      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7717     );
7718     let next () =
7719       if !comma then (
7720         if single_line then pr ", " else pr ",\n\t\t"
7721       );
7722       comma := true
7723     in
7724     List.iter (
7725       function
7726       | Pathname n
7727       | Device n | Dev_or_Path n
7728       | String n
7729       | OptString n ->
7730           next ();
7731           pr "const char *%s" n
7732       | StringList n | DeviceList n ->
7733           next ();
7734           pr "char *const *%s" n
7735       | Bool n -> next (); pr "int %s" n
7736       | Int n -> next (); pr "int %s" n
7737       | Int64 n -> next (); pr "int64_t %s" n
7738       | FileIn n
7739       | FileOut n ->
7740           if not in_daemon then (next (); pr "const char *%s" n)
7741     ) (snd style);
7742     if is_RBufferOut then (next (); pr "size_t *size_r");
7743   );
7744   pr ")";
7745   if semicolon then pr ";";
7746   if newline then pr "\n"
7747
7748 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7749 and generate_c_call_args ?handle ?(decl = false) style =
7750   pr "(";
7751   let comma = ref false in
7752   let next () =
7753     if !comma then pr ", ";
7754     comma := true
7755   in
7756   (match handle with
7757    | None -> ()
7758    | Some handle -> pr "%s" handle; comma := true
7759   );
7760   List.iter (
7761     fun arg ->
7762       next ();
7763       pr "%s" (name_of_argt arg)
7764   ) (snd style);
7765   (* For RBufferOut calls, add implicit &size parameter. *)
7766   if not decl then (
7767     match fst style with
7768     | RBufferOut _ ->
7769         next ();
7770         pr "&size"
7771     | _ -> ()
7772   );
7773   pr ")"
7774
7775 (* Generate the OCaml bindings interface. *)
7776 and generate_ocaml_mli () =
7777   generate_header OCamlStyle LGPLv2plus;
7778
7779   pr "\
7780 (** For API documentation you should refer to the C API
7781     in the guestfs(3) manual page.  The OCaml API uses almost
7782     exactly the same calls. *)
7783
7784 type t
7785 (** A [guestfs_h] handle. *)
7786
7787 exception Error of string
7788 (** This exception is raised when there is an error. *)
7789
7790 exception Handle_closed of string
7791 (** This exception is raised if you use a {!Guestfs.t} handle
7792     after calling {!close} on it.  The string is the name of
7793     the function. *)
7794
7795 val create : unit -> t
7796 (** Create a {!Guestfs.t} handle. *)
7797
7798 val close : t -> unit
7799 (** Close the {!Guestfs.t} handle and free up all resources used
7800     by it immediately.
7801
7802     Handles are closed by the garbage collector when they become
7803     unreferenced, but callers can call this in order to provide
7804     predictable cleanup. *)
7805
7806 ";
7807   generate_ocaml_structure_decls ();
7808
7809   (* The actions. *)
7810   List.iter (
7811     fun (name, style, _, _, _, shortdesc, _) ->
7812       generate_ocaml_prototype name style;
7813       pr "(** %s *)\n" shortdesc;
7814       pr "\n"
7815   ) all_functions_sorted
7816
7817 (* Generate the OCaml bindings implementation. *)
7818 and generate_ocaml_ml () =
7819   generate_header OCamlStyle LGPLv2plus;
7820
7821   pr "\
7822 type t
7823
7824 exception Error of string
7825 exception Handle_closed of string
7826
7827 external create : unit -> t = \"ocaml_guestfs_create\"
7828 external close : t -> unit = \"ocaml_guestfs_close\"
7829
7830 (* Give the exceptions names, so they can be raised from the C code. *)
7831 let () =
7832   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7833   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7834
7835 ";
7836
7837   generate_ocaml_structure_decls ();
7838
7839   (* The actions. *)
7840   List.iter (
7841     fun (name, style, _, _, _, shortdesc, _) ->
7842       generate_ocaml_prototype ~is_external:true name style;
7843   ) all_functions_sorted
7844
7845 (* Generate the OCaml bindings C implementation. *)
7846 and generate_ocaml_c () =
7847   generate_header CStyle LGPLv2plus;
7848
7849   pr "\
7850 #include <stdio.h>
7851 #include <stdlib.h>
7852 #include <string.h>
7853
7854 #include <caml/config.h>
7855 #include <caml/alloc.h>
7856 #include <caml/callback.h>
7857 #include <caml/fail.h>
7858 #include <caml/memory.h>
7859 #include <caml/mlvalues.h>
7860 #include <caml/signals.h>
7861
7862 #include <guestfs.h>
7863
7864 #include \"guestfs_c.h\"
7865
7866 /* Copy a hashtable of string pairs into an assoc-list.  We return
7867  * the list in reverse order, but hashtables aren't supposed to be
7868  * ordered anyway.
7869  */
7870 static CAMLprim value
7871 copy_table (char * const * argv)
7872 {
7873   CAMLparam0 ();
7874   CAMLlocal5 (rv, pairv, kv, vv, cons);
7875   int i;
7876
7877   rv = Val_int (0);
7878   for (i = 0; argv[i] != NULL; i += 2) {
7879     kv = caml_copy_string (argv[i]);
7880     vv = caml_copy_string (argv[i+1]);
7881     pairv = caml_alloc (2, 0);
7882     Store_field (pairv, 0, kv);
7883     Store_field (pairv, 1, vv);
7884     cons = caml_alloc (2, 0);
7885     Store_field (cons, 1, rv);
7886     rv = cons;
7887     Store_field (cons, 0, pairv);
7888   }
7889
7890   CAMLreturn (rv);
7891 }
7892
7893 ";
7894
7895   (* Struct copy functions. *)
7896
7897   let emit_ocaml_copy_list_function typ =
7898     pr "static CAMLprim value\n";
7899     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7900     pr "{\n";
7901     pr "  CAMLparam0 ();\n";
7902     pr "  CAMLlocal2 (rv, v);\n";
7903     pr "  unsigned int i;\n";
7904     pr "\n";
7905     pr "  if (%ss->len == 0)\n" typ;
7906     pr "    CAMLreturn (Atom (0));\n";
7907     pr "  else {\n";
7908     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7909     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7910     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7911     pr "      caml_modify (&Field (rv, i), v);\n";
7912     pr "    }\n";
7913     pr "    CAMLreturn (rv);\n";
7914     pr "  }\n";
7915     pr "}\n";
7916     pr "\n";
7917   in
7918
7919   List.iter (
7920     fun (typ, cols) ->
7921       let has_optpercent_col =
7922         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7923
7924       pr "static CAMLprim value\n";
7925       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7926       pr "{\n";
7927       pr "  CAMLparam0 ();\n";
7928       if has_optpercent_col then
7929         pr "  CAMLlocal3 (rv, v, v2);\n"
7930       else
7931         pr "  CAMLlocal2 (rv, v);\n";
7932       pr "\n";
7933       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7934       iteri (
7935         fun i col ->
7936           (match col with
7937            | name, FString ->
7938                pr "  v = caml_copy_string (%s->%s);\n" typ name
7939            | name, FBuffer ->
7940                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7941                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7942                  typ name typ name
7943            | name, FUUID ->
7944                pr "  v = caml_alloc_string (32);\n";
7945                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7946            | name, (FBytes|FInt64|FUInt64) ->
7947                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7948            | name, (FInt32|FUInt32) ->
7949                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7950            | name, FOptPercent ->
7951                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7952                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7953                pr "    v = caml_alloc (1, 0);\n";
7954                pr "    Store_field (v, 0, v2);\n";
7955                pr "  } else /* None */\n";
7956                pr "    v = Val_int (0);\n";
7957            | name, FChar ->
7958                pr "  v = Val_int (%s->%s);\n" typ name
7959           );
7960           pr "  Store_field (rv, %d, v);\n" i
7961       ) cols;
7962       pr "  CAMLreturn (rv);\n";
7963       pr "}\n";
7964       pr "\n";
7965   ) structs;
7966
7967   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7968   List.iter (
7969     function
7970     | typ, (RStructListOnly | RStructAndList) ->
7971         (* generate the function for typ *)
7972         emit_ocaml_copy_list_function typ
7973     | typ, _ -> () (* empty *)
7974   ) (rstructs_used_by all_functions);
7975
7976   (* The wrappers. *)
7977   List.iter (
7978     fun (name, style, _, _, _, _, _) ->
7979       pr "/* Automatically generated wrapper for function\n";
7980       pr " * ";
7981       generate_ocaml_prototype name style;
7982       pr " */\n";
7983       pr "\n";
7984
7985       let params =
7986         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7987
7988       let needs_extra_vs =
7989         match fst style with RConstOptString _ -> true | _ -> false in
7990
7991       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7992       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7993       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7994       pr "\n";
7995
7996       pr "CAMLprim value\n";
7997       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7998       List.iter (pr ", value %s") (List.tl params);
7999       pr ")\n";
8000       pr "{\n";
8001
8002       (match params with
8003        | [p1; p2; p3; p4; p5] ->
8004            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8005        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8006            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8007            pr "  CAMLxparam%d (%s);\n"
8008              (List.length rest) (String.concat ", " rest)
8009        | ps ->
8010            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8011       );
8012       if not needs_extra_vs then
8013         pr "  CAMLlocal1 (rv);\n"
8014       else
8015         pr "  CAMLlocal3 (rv, v, v2);\n";
8016       pr "\n";
8017
8018       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8019       pr "  if (g == NULL)\n";
8020       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8021       pr "\n";
8022
8023       List.iter (
8024         function
8025         | Pathname n
8026         | Device n | Dev_or_Path n
8027         | String n
8028         | FileIn n
8029         | FileOut n ->
8030             pr "  const char *%s = String_val (%sv);\n" n n
8031         | OptString n ->
8032             pr "  const char *%s =\n" n;
8033             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8034               n n
8035         | StringList n | DeviceList n ->
8036             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8037         | Bool n ->
8038             pr "  int %s = Bool_val (%sv);\n" n n
8039         | Int n ->
8040             pr "  int %s = Int_val (%sv);\n" n n
8041         | Int64 n ->
8042             pr "  int64_t %s = Int64_val (%sv);\n" n n
8043       ) (snd style);
8044       let error_code =
8045         match fst style with
8046         | RErr -> pr "  int r;\n"; "-1"
8047         | RInt _ -> pr "  int r;\n"; "-1"
8048         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8049         | RBool _ -> pr "  int r;\n"; "-1"
8050         | RConstString _ | RConstOptString _ ->
8051             pr "  const char *r;\n"; "NULL"
8052         | RString _ -> pr "  char *r;\n"; "NULL"
8053         | RStringList _ ->
8054             pr "  int i;\n";
8055             pr "  char **r;\n";
8056             "NULL"
8057         | RStruct (_, typ) ->
8058             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8059         | RStructList (_, typ) ->
8060             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8061         | RHashtable _ ->
8062             pr "  int i;\n";
8063             pr "  char **r;\n";
8064             "NULL"
8065         | RBufferOut _ ->
8066             pr "  char *r;\n";
8067             pr "  size_t size;\n";
8068             "NULL" in
8069       pr "\n";
8070
8071       pr "  caml_enter_blocking_section ();\n";
8072       pr "  r = guestfs_%s " name;
8073       generate_c_call_args ~handle:"g" style;
8074       pr ";\n";
8075       pr "  caml_leave_blocking_section ();\n";
8076
8077       List.iter (
8078         function
8079         | StringList n | DeviceList n ->
8080             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8081         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8082         | Bool _ | Int _ | Int64 _
8083         | FileIn _ | FileOut _ -> ()
8084       ) (snd style);
8085
8086       pr "  if (r == %s)\n" error_code;
8087       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8088       pr "\n";
8089
8090       (match fst style with
8091        | RErr -> pr "  rv = Val_unit;\n"
8092        | RInt _ -> pr "  rv = Val_int (r);\n"
8093        | RInt64 _ ->
8094            pr "  rv = caml_copy_int64 (r);\n"
8095        | RBool _ -> pr "  rv = Val_bool (r);\n"
8096        | RConstString _ ->
8097            pr "  rv = caml_copy_string (r);\n"
8098        | RConstOptString _ ->
8099            pr "  if (r) { /* Some string */\n";
8100            pr "    v = caml_alloc (1, 0);\n";
8101            pr "    v2 = caml_copy_string (r);\n";
8102            pr "    Store_field (v, 0, v2);\n";
8103            pr "  } else /* None */\n";
8104            pr "    v = Val_int (0);\n";
8105        | RString _ ->
8106            pr "  rv = caml_copy_string (r);\n";
8107            pr "  free (r);\n"
8108        | RStringList _ ->
8109            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8110            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8111            pr "  free (r);\n"
8112        | RStruct (_, typ) ->
8113            pr "  rv = copy_%s (r);\n" typ;
8114            pr "  guestfs_free_%s (r);\n" typ;
8115        | RStructList (_, typ) ->
8116            pr "  rv = copy_%s_list (r);\n" typ;
8117            pr "  guestfs_free_%s_list (r);\n" typ;
8118        | RHashtable _ ->
8119            pr "  rv = copy_table (r);\n";
8120            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8121            pr "  free (r);\n";
8122        | RBufferOut _ ->
8123            pr "  rv = caml_alloc_string (size);\n";
8124            pr "  memcpy (String_val (rv), r, size);\n";
8125       );
8126
8127       pr "  CAMLreturn (rv);\n";
8128       pr "}\n";
8129       pr "\n";
8130
8131       if List.length params > 5 then (
8132         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8133         pr "CAMLprim value ";
8134         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8135         pr "CAMLprim value\n";
8136         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8137         pr "{\n";
8138         pr "  return ocaml_guestfs_%s (argv[0]" name;
8139         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8140         pr ");\n";
8141         pr "}\n";
8142         pr "\n"
8143       )
8144   ) all_functions_sorted
8145
8146 and generate_ocaml_structure_decls () =
8147   List.iter (
8148     fun (typ, cols) ->
8149       pr "type %s = {\n" typ;
8150       List.iter (
8151         function
8152         | name, FString -> pr "  %s : string;\n" name
8153         | name, FBuffer -> pr "  %s : string;\n" name
8154         | name, FUUID -> pr "  %s : string;\n" name
8155         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8156         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8157         | name, FChar -> pr "  %s : char;\n" name
8158         | name, FOptPercent -> pr "  %s : float option;\n" name
8159       ) cols;
8160       pr "}\n";
8161       pr "\n"
8162   ) structs
8163
8164 and generate_ocaml_prototype ?(is_external = false) name style =
8165   if is_external then pr "external " else pr "val ";
8166   pr "%s : t -> " name;
8167   List.iter (
8168     function
8169     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8170     | OptString _ -> pr "string option -> "
8171     | StringList _ | DeviceList _ -> pr "string array -> "
8172     | Bool _ -> pr "bool -> "
8173     | Int _ -> pr "int -> "
8174     | Int64 _ -> pr "int64 -> "
8175   ) (snd style);
8176   (match fst style with
8177    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8178    | RInt _ -> pr "int"
8179    | RInt64 _ -> pr "int64"
8180    | RBool _ -> pr "bool"
8181    | RConstString _ -> pr "string"
8182    | RConstOptString _ -> pr "string option"
8183    | RString _ | RBufferOut _ -> pr "string"
8184    | RStringList _ -> pr "string array"
8185    | RStruct (_, typ) -> pr "%s" typ
8186    | RStructList (_, typ) -> pr "%s array" typ
8187    | RHashtable _ -> pr "(string * string) list"
8188   );
8189   if is_external then (
8190     pr " = ";
8191     if List.length (snd style) + 1 > 5 then
8192       pr "\"ocaml_guestfs_%s_byte\" " name;
8193     pr "\"ocaml_guestfs_%s\"" name
8194   );
8195   pr "\n"
8196
8197 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8198 and generate_perl_xs () =
8199   generate_header CStyle LGPLv2plus;
8200
8201   pr "\
8202 #include \"EXTERN.h\"
8203 #include \"perl.h\"
8204 #include \"XSUB.h\"
8205
8206 #include <guestfs.h>
8207
8208 #ifndef PRId64
8209 #define PRId64 \"lld\"
8210 #endif
8211
8212 static SV *
8213 my_newSVll(long long val) {
8214 #ifdef USE_64_BIT_ALL
8215   return newSViv(val);
8216 #else
8217   char buf[100];
8218   int len;
8219   len = snprintf(buf, 100, \"%%\" PRId64, val);
8220   return newSVpv(buf, len);
8221 #endif
8222 }
8223
8224 #ifndef PRIu64
8225 #define PRIu64 \"llu\"
8226 #endif
8227
8228 static SV *
8229 my_newSVull(unsigned long long val) {
8230 #ifdef USE_64_BIT_ALL
8231   return newSVuv(val);
8232 #else
8233   char buf[100];
8234   int len;
8235   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8236   return newSVpv(buf, len);
8237 #endif
8238 }
8239
8240 /* http://www.perlmonks.org/?node_id=680842 */
8241 static char **
8242 XS_unpack_charPtrPtr (SV *arg) {
8243   char **ret;
8244   AV *av;
8245   I32 i;
8246
8247   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8248     croak (\"array reference expected\");
8249
8250   av = (AV *)SvRV (arg);
8251   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8252   if (!ret)
8253     croak (\"malloc failed\");
8254
8255   for (i = 0; i <= av_len (av); i++) {
8256     SV **elem = av_fetch (av, i, 0);
8257
8258     if (!elem || !*elem)
8259       croak (\"missing element in list\");
8260
8261     ret[i] = SvPV_nolen (*elem);
8262   }
8263
8264   ret[i] = NULL;
8265
8266   return ret;
8267 }
8268
8269 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8270
8271 PROTOTYPES: ENABLE
8272
8273 guestfs_h *
8274 _create ()
8275    CODE:
8276       RETVAL = guestfs_create ();
8277       if (!RETVAL)
8278         croak (\"could not create guestfs handle\");
8279       guestfs_set_error_handler (RETVAL, NULL, NULL);
8280  OUTPUT:
8281       RETVAL
8282
8283 void
8284 DESTROY (g)
8285       guestfs_h *g;
8286  PPCODE:
8287       guestfs_close (g);
8288
8289 ";
8290
8291   List.iter (
8292     fun (name, style, _, _, _, _, _) ->
8293       (match fst style with
8294        | RErr -> pr "void\n"
8295        | RInt _ -> pr "SV *\n"
8296        | RInt64 _ -> pr "SV *\n"
8297        | RBool _ -> pr "SV *\n"
8298        | RConstString _ -> pr "SV *\n"
8299        | RConstOptString _ -> pr "SV *\n"
8300        | RString _ -> pr "SV *\n"
8301        | RBufferOut _ -> pr "SV *\n"
8302        | RStringList _
8303        | RStruct _ | RStructList _
8304        | RHashtable _ ->
8305            pr "void\n" (* all lists returned implictly on the stack *)
8306       );
8307       (* Call and arguments. *)
8308       pr "%s " name;
8309       generate_c_call_args ~handle:"g" ~decl:true style;
8310       pr "\n";
8311       pr "      guestfs_h *g;\n";
8312       iteri (
8313         fun i ->
8314           function
8315           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8316               pr "      char *%s;\n" n
8317           | OptString n ->
8318               (* http://www.perlmonks.org/?node_id=554277
8319                * Note that the implicit handle argument means we have
8320                * to add 1 to the ST(x) operator.
8321                *)
8322               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8323           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8324           | Bool n -> pr "      int %s;\n" n
8325           | Int n -> pr "      int %s;\n" n
8326           | Int64 n -> pr "      int64_t %s;\n" n
8327       ) (snd style);
8328
8329       let do_cleanups () =
8330         List.iter (
8331           function
8332           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8333           | Bool _ | Int _ | Int64 _
8334           | FileIn _ | FileOut _ -> ()
8335           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8336         ) (snd style)
8337       in
8338
8339       (* Code. *)
8340       (match fst style with
8341        | RErr ->
8342            pr "PREINIT:\n";
8343            pr "      int r;\n";
8344            pr " PPCODE:\n";
8345            pr "      r = guestfs_%s " name;
8346            generate_c_call_args ~handle:"g" style;
8347            pr ";\n";
8348            do_cleanups ();
8349            pr "      if (r == -1)\n";
8350            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8351        | RInt n
8352        | RBool n ->
8353            pr "PREINIT:\n";
8354            pr "      int %s;\n" n;
8355            pr "   CODE:\n";
8356            pr "      %s = guestfs_%s " n name;
8357            generate_c_call_args ~handle:"g" style;
8358            pr ";\n";
8359            do_cleanups ();
8360            pr "      if (%s == -1)\n" n;
8361            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8362            pr "      RETVAL = newSViv (%s);\n" n;
8363            pr " OUTPUT:\n";
8364            pr "      RETVAL\n"
8365        | RInt64 n ->
8366            pr "PREINIT:\n";
8367            pr "      int64_t %s;\n" n;
8368            pr "   CODE:\n";
8369            pr "      %s = guestfs_%s " n name;
8370            generate_c_call_args ~handle:"g" style;
8371            pr ";\n";
8372            do_cleanups ();
8373            pr "      if (%s == -1)\n" n;
8374            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8375            pr "      RETVAL = my_newSVll (%s);\n" n;
8376            pr " OUTPUT:\n";
8377            pr "      RETVAL\n"
8378        | RConstString n ->
8379            pr "PREINIT:\n";
8380            pr "      const char *%s;\n" n;
8381            pr "   CODE:\n";
8382            pr "      %s = guestfs_%s " n name;
8383            generate_c_call_args ~handle:"g" style;
8384            pr ";\n";
8385            do_cleanups ();
8386            pr "      if (%s == NULL)\n" n;
8387            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8388            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8389            pr " OUTPUT:\n";
8390            pr "      RETVAL\n"
8391        | RConstOptString n ->
8392            pr "PREINIT:\n";
8393            pr "      const char *%s;\n" n;
8394            pr "   CODE:\n";
8395            pr "      %s = guestfs_%s " n name;
8396            generate_c_call_args ~handle:"g" style;
8397            pr ";\n";
8398            do_cleanups ();
8399            pr "      if (%s == NULL)\n" n;
8400            pr "        RETVAL = &PL_sv_undef;\n";
8401            pr "      else\n";
8402            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8403            pr " OUTPUT:\n";
8404            pr "      RETVAL\n"
8405        | RString n ->
8406            pr "PREINIT:\n";
8407            pr "      char *%s;\n" n;
8408            pr "   CODE:\n";
8409            pr "      %s = guestfs_%s " n name;
8410            generate_c_call_args ~handle:"g" style;
8411            pr ";\n";
8412            do_cleanups ();
8413            pr "      if (%s == NULL)\n" n;
8414            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8415            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8416            pr "      free (%s);\n" n;
8417            pr " OUTPUT:\n";
8418            pr "      RETVAL\n"
8419        | RStringList n | RHashtable n ->
8420            pr "PREINIT:\n";
8421            pr "      char **%s;\n" n;
8422            pr "      int i, n;\n";
8423            pr " PPCODE:\n";
8424            pr "      %s = guestfs_%s " n name;
8425            generate_c_call_args ~handle:"g" style;
8426            pr ";\n";
8427            do_cleanups ();
8428            pr "      if (%s == NULL)\n" n;
8429            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8430            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8431            pr "      EXTEND (SP, n);\n";
8432            pr "      for (i = 0; i < n; ++i) {\n";
8433            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8434            pr "        free (%s[i]);\n" n;
8435            pr "      }\n";
8436            pr "      free (%s);\n" n;
8437        | RStruct (n, typ) ->
8438            let cols = cols_of_struct typ in
8439            generate_perl_struct_code typ cols name style n do_cleanups
8440        | RStructList (n, typ) ->
8441            let cols = cols_of_struct typ in
8442            generate_perl_struct_list_code typ cols name style n do_cleanups
8443        | RBufferOut n ->
8444            pr "PREINIT:\n";
8445            pr "      char *%s;\n" n;
8446            pr "      size_t size;\n";
8447            pr "   CODE:\n";
8448            pr "      %s = guestfs_%s " n name;
8449            generate_c_call_args ~handle:"g" style;
8450            pr ";\n";
8451            do_cleanups ();
8452            pr "      if (%s == NULL)\n" n;
8453            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8454            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8455            pr "      free (%s);\n" n;
8456            pr " OUTPUT:\n";
8457            pr "      RETVAL\n"
8458       );
8459
8460       pr "\n"
8461   ) all_functions
8462
8463 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8464   pr "PREINIT:\n";
8465   pr "      struct guestfs_%s_list *%s;\n" typ n;
8466   pr "      int i;\n";
8467   pr "      HV *hv;\n";
8468   pr " PPCODE:\n";
8469   pr "      %s = guestfs_%s " n name;
8470   generate_c_call_args ~handle:"g" style;
8471   pr ";\n";
8472   do_cleanups ();
8473   pr "      if (%s == NULL)\n" n;
8474   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8475   pr "      EXTEND (SP, %s->len);\n" n;
8476   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8477   pr "        hv = newHV ();\n";
8478   List.iter (
8479     function
8480     | name, FString ->
8481         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8482           name (String.length name) n name
8483     | name, FUUID ->
8484         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8485           name (String.length name) n name
8486     | name, FBuffer ->
8487         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8488           name (String.length name) n name n name
8489     | name, (FBytes|FUInt64) ->
8490         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8491           name (String.length name) n name
8492     | name, FInt64 ->
8493         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8494           name (String.length name) n name
8495     | name, (FInt32|FUInt32) ->
8496         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8497           name (String.length name) n name
8498     | name, FChar ->
8499         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8500           name (String.length name) n name
8501     | name, FOptPercent ->
8502         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8503           name (String.length name) n name
8504   ) cols;
8505   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8506   pr "      }\n";
8507   pr "      guestfs_free_%s_list (%s);\n" typ n
8508
8509 and generate_perl_struct_code typ cols name style n do_cleanups =
8510   pr "PREINIT:\n";
8511   pr "      struct guestfs_%s *%s;\n" typ n;
8512   pr " PPCODE:\n";
8513   pr "      %s = guestfs_%s " n name;
8514   generate_c_call_args ~handle:"g" style;
8515   pr ";\n";
8516   do_cleanups ();
8517   pr "      if (%s == NULL)\n" n;
8518   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8519   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8520   List.iter (
8521     fun ((name, _) as col) ->
8522       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8523
8524       match col with
8525       | name, FString ->
8526           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8527             n name
8528       | name, FBuffer ->
8529           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8530             n name n name
8531       | name, FUUID ->
8532           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8533             n name
8534       | name, (FBytes|FUInt64) ->
8535           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8536             n name
8537       | name, FInt64 ->
8538           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8539             n name
8540       | name, (FInt32|FUInt32) ->
8541           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8542             n name
8543       | name, FChar ->
8544           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8545             n name
8546       | name, FOptPercent ->
8547           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8548             n name
8549   ) cols;
8550   pr "      free (%s);\n" n
8551
8552 (* Generate Sys/Guestfs.pm. *)
8553 and generate_perl_pm () =
8554   generate_header HashStyle LGPLv2plus;
8555
8556   pr "\
8557 =pod
8558
8559 =head1 NAME
8560
8561 Sys::Guestfs - Perl bindings for libguestfs
8562
8563 =head1 SYNOPSIS
8564
8565  use Sys::Guestfs;
8566
8567  my $h = Sys::Guestfs->new ();
8568  $h->add_drive ('guest.img');
8569  $h->launch ();
8570  $h->mount ('/dev/sda1', '/');
8571  $h->touch ('/hello');
8572  $h->sync ();
8573
8574 =head1 DESCRIPTION
8575
8576 The C<Sys::Guestfs> module provides a Perl XS binding to the
8577 libguestfs API for examining and modifying virtual machine
8578 disk images.
8579
8580 Amongst the things this is good for: making batch configuration
8581 changes to guests, getting disk used/free statistics (see also:
8582 virt-df), migrating between virtualization systems (see also:
8583 virt-p2v), performing partial backups, performing partial guest
8584 clones, cloning guests and changing registry/UUID/hostname info, and
8585 much else besides.
8586
8587 Libguestfs uses Linux kernel and qemu code, and can access any type of
8588 guest filesystem that Linux and qemu can, including but not limited
8589 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8590 schemes, qcow, qcow2, vmdk.
8591
8592 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8593 LVs, what filesystem is in each LV, etc.).  It can also run commands
8594 in the context of the guest.  Also you can access filesystems over
8595 FUSE.
8596
8597 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8598 functions for using libguestfs from Perl, including integration
8599 with libvirt.
8600
8601 =head1 ERRORS
8602
8603 All errors turn into calls to C<croak> (see L<Carp(3)>).
8604
8605 =head1 METHODS
8606
8607 =over 4
8608
8609 =cut
8610
8611 package Sys::Guestfs;
8612
8613 use strict;
8614 use warnings;
8615
8616 require XSLoader;
8617 XSLoader::load ('Sys::Guestfs');
8618
8619 =item $h = Sys::Guestfs->new ();
8620
8621 Create a new guestfs handle.
8622
8623 =cut
8624
8625 sub new {
8626   my $proto = shift;
8627   my $class = ref ($proto) || $proto;
8628
8629   my $self = Sys::Guestfs::_create ();
8630   bless $self, $class;
8631   return $self;
8632 }
8633
8634 ";
8635
8636   (* Actions.  We only need to print documentation for these as
8637    * they are pulled in from the XS code automatically.
8638    *)
8639   List.iter (
8640     fun (name, style, _, flags, _, _, longdesc) ->
8641       if not (List.mem NotInDocs flags) then (
8642         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8643         pr "=item ";
8644         generate_perl_prototype name style;
8645         pr "\n\n";
8646         pr "%s\n\n" longdesc;
8647         if List.mem ProtocolLimitWarning flags then
8648           pr "%s\n\n" protocol_limit_warning;
8649         if List.mem DangerWillRobinson flags then
8650           pr "%s\n\n" danger_will_robinson;
8651         match deprecation_notice flags with
8652         | None -> ()
8653         | Some txt -> pr "%s\n\n" txt
8654       )
8655   ) all_functions_sorted;
8656
8657   (* End of file. *)
8658   pr "\
8659 =cut
8660
8661 1;
8662
8663 =back
8664
8665 =head1 COPYRIGHT
8666
8667 Copyright (C) %s Red Hat Inc.
8668
8669 =head1 LICENSE
8670
8671 Please see the file COPYING.LIB for the full license.
8672
8673 =head1 SEE ALSO
8674
8675 L<guestfs(3)>,
8676 L<guestfish(1)>,
8677 L<http://libguestfs.org>,
8678 L<Sys::Guestfs::Lib(3)>.
8679
8680 =cut
8681 " copyright_years
8682
8683 and generate_perl_prototype name style =
8684   (match fst style with
8685    | RErr -> ()
8686    | RBool n
8687    | RInt n
8688    | RInt64 n
8689    | RConstString n
8690    | RConstOptString n
8691    | RString n
8692    | RBufferOut n -> pr "$%s = " n
8693    | RStruct (n,_)
8694    | RHashtable n -> pr "%%%s = " n
8695    | RStringList n
8696    | RStructList (n,_) -> pr "@%s = " n
8697   );
8698   pr "$h->%s (" name;
8699   let comma = ref false in
8700   List.iter (
8701     fun arg ->
8702       if !comma then pr ", ";
8703       comma := true;
8704       match arg with
8705       | Pathname n | Device n | Dev_or_Path n | String n
8706       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8707           pr "$%s" n
8708       | StringList n | DeviceList n ->
8709           pr "\\@%s" n
8710   ) (snd style);
8711   pr ");"
8712
8713 (* Generate Python C module. *)
8714 and generate_python_c () =
8715   generate_header CStyle LGPLv2plus;
8716
8717   pr "\
8718 #include <Python.h>
8719
8720 #include <stdio.h>
8721 #include <stdlib.h>
8722 #include <assert.h>
8723
8724 #include \"guestfs.h\"
8725
8726 typedef struct {
8727   PyObject_HEAD
8728   guestfs_h *g;
8729 } Pyguestfs_Object;
8730
8731 static guestfs_h *
8732 get_handle (PyObject *obj)
8733 {
8734   assert (obj);
8735   assert (obj != Py_None);
8736   return ((Pyguestfs_Object *) obj)->g;
8737 }
8738
8739 static PyObject *
8740 put_handle (guestfs_h *g)
8741 {
8742   assert (g);
8743   return
8744     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8745 }
8746
8747 /* This list should be freed (but not the strings) after use. */
8748 static char **
8749 get_string_list (PyObject *obj)
8750 {
8751   int i, len;
8752   char **r;
8753
8754   assert (obj);
8755
8756   if (!PyList_Check (obj)) {
8757     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8758     return NULL;
8759   }
8760
8761   len = PyList_Size (obj);
8762   r = malloc (sizeof (char *) * (len+1));
8763   if (r == NULL) {
8764     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8765     return NULL;
8766   }
8767
8768   for (i = 0; i < len; ++i)
8769     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8770   r[len] = NULL;
8771
8772   return r;
8773 }
8774
8775 static PyObject *
8776 put_string_list (char * const * const argv)
8777 {
8778   PyObject *list;
8779   int argc, i;
8780
8781   for (argc = 0; argv[argc] != NULL; ++argc)
8782     ;
8783
8784   list = PyList_New (argc);
8785   for (i = 0; i < argc; ++i)
8786     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8787
8788   return list;
8789 }
8790
8791 static PyObject *
8792 put_table (char * const * const argv)
8793 {
8794   PyObject *list, *item;
8795   int argc, i;
8796
8797   for (argc = 0; argv[argc] != NULL; ++argc)
8798     ;
8799
8800   list = PyList_New (argc >> 1);
8801   for (i = 0; i < argc; i += 2) {
8802     item = PyTuple_New (2);
8803     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8804     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8805     PyList_SetItem (list, i >> 1, item);
8806   }
8807
8808   return list;
8809 }
8810
8811 static void
8812 free_strings (char **argv)
8813 {
8814   int argc;
8815
8816   for (argc = 0; argv[argc] != NULL; ++argc)
8817     free (argv[argc]);
8818   free (argv);
8819 }
8820
8821 static PyObject *
8822 py_guestfs_create (PyObject *self, PyObject *args)
8823 {
8824   guestfs_h *g;
8825
8826   g = guestfs_create ();
8827   if (g == NULL) {
8828     PyErr_SetString (PyExc_RuntimeError,
8829                      \"guestfs.create: failed to allocate handle\");
8830     return NULL;
8831   }
8832   guestfs_set_error_handler (g, NULL, NULL);
8833   return put_handle (g);
8834 }
8835
8836 static PyObject *
8837 py_guestfs_close (PyObject *self, PyObject *args)
8838 {
8839   PyObject *py_g;
8840   guestfs_h *g;
8841
8842   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8843     return NULL;
8844   g = get_handle (py_g);
8845
8846   guestfs_close (g);
8847
8848   Py_INCREF (Py_None);
8849   return Py_None;
8850 }
8851
8852 ";
8853
8854   let emit_put_list_function typ =
8855     pr "static PyObject *\n";
8856     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8857     pr "{\n";
8858     pr "  PyObject *list;\n";
8859     pr "  int i;\n";
8860     pr "\n";
8861     pr "  list = PyList_New (%ss->len);\n" typ;
8862     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8863     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8864     pr "  return list;\n";
8865     pr "};\n";
8866     pr "\n"
8867   in
8868
8869   (* Structures, turned into Python dictionaries. *)
8870   List.iter (
8871     fun (typ, cols) ->
8872       pr "static PyObject *\n";
8873       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8874       pr "{\n";
8875       pr "  PyObject *dict;\n";
8876       pr "\n";
8877       pr "  dict = PyDict_New ();\n";
8878       List.iter (
8879         function
8880         | name, FString ->
8881             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8882             pr "                        PyString_FromString (%s->%s));\n"
8883               typ name
8884         | name, FBuffer ->
8885             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8886             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8887               typ name typ name
8888         | name, FUUID ->
8889             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8890             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8891               typ name
8892         | name, (FBytes|FUInt64) ->
8893             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8894             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8895               typ name
8896         | name, FInt64 ->
8897             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8898             pr "                        PyLong_FromLongLong (%s->%s));\n"
8899               typ name
8900         | name, FUInt32 ->
8901             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8902             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8903               typ name
8904         | name, FInt32 ->
8905             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8906             pr "                        PyLong_FromLong (%s->%s));\n"
8907               typ name
8908         | name, FOptPercent ->
8909             pr "  if (%s->%s >= 0)\n" typ name;
8910             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8911             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8912               typ name;
8913             pr "  else {\n";
8914             pr "    Py_INCREF (Py_None);\n";
8915             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8916             pr "  }\n"
8917         | name, FChar ->
8918             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8919             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8920       ) cols;
8921       pr "  return dict;\n";
8922       pr "};\n";
8923       pr "\n";
8924
8925   ) structs;
8926
8927   (* Emit a put_TYPE_list function definition only if that function is used. *)
8928   List.iter (
8929     function
8930     | typ, (RStructListOnly | RStructAndList) ->
8931         (* generate the function for typ *)
8932         emit_put_list_function typ
8933     | typ, _ -> () (* empty *)
8934   ) (rstructs_used_by all_functions);
8935
8936   (* Python wrapper functions. *)
8937   List.iter (
8938     fun (name, style, _, _, _, _, _) ->
8939       pr "static PyObject *\n";
8940       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8941       pr "{\n";
8942
8943       pr "  PyObject *py_g;\n";
8944       pr "  guestfs_h *g;\n";
8945       pr "  PyObject *py_r;\n";
8946
8947       let error_code =
8948         match fst style with
8949         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8950         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8951         | RConstString _ | RConstOptString _ ->
8952             pr "  const char *r;\n"; "NULL"
8953         | RString _ -> pr "  char *r;\n"; "NULL"
8954         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8955         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8956         | RStructList (_, typ) ->
8957             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8958         | RBufferOut _ ->
8959             pr "  char *r;\n";
8960             pr "  size_t size;\n";
8961             "NULL" in
8962
8963       List.iter (
8964         function
8965         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8966             pr "  const char *%s;\n" n
8967         | OptString n -> pr "  const char *%s;\n" n
8968         | StringList n | DeviceList n ->
8969             pr "  PyObject *py_%s;\n" n;
8970             pr "  char **%s;\n" n
8971         | Bool n -> pr "  int %s;\n" n
8972         | Int n -> pr "  int %s;\n" n
8973         | Int64 n -> pr "  long long %s;\n" n
8974       ) (snd style);
8975
8976       pr "\n";
8977
8978       (* Convert the parameters. *)
8979       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8980       List.iter (
8981         function
8982         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8983         | OptString _ -> pr "z"
8984         | StringList _ | DeviceList _ -> pr "O"
8985         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8986         | Int _ -> pr "i"
8987         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8988                              * emulate C's int/long/long long in Python?
8989                              *)
8990       ) (snd style);
8991       pr ":guestfs_%s\",\n" name;
8992       pr "                         &py_g";
8993       List.iter (
8994         function
8995         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8996         | OptString n -> pr ", &%s" n
8997         | StringList n | DeviceList n -> pr ", &py_%s" n
8998         | Bool n -> pr ", &%s" n
8999         | Int n -> pr ", &%s" n
9000         | Int64 n -> pr ", &%s" n
9001       ) (snd style);
9002
9003       pr "))\n";
9004       pr "    return NULL;\n";
9005
9006       pr "  g = get_handle (py_g);\n";
9007       List.iter (
9008         function
9009         | Pathname _ | Device _ | Dev_or_Path _ | String _
9010         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9011         | StringList n | DeviceList n ->
9012             pr "  %s = get_string_list (py_%s);\n" n n;
9013             pr "  if (!%s) return NULL;\n" n
9014       ) (snd style);
9015
9016       pr "\n";
9017
9018       pr "  r = guestfs_%s " name;
9019       generate_c_call_args ~handle:"g" style;
9020       pr ";\n";
9021
9022       List.iter (
9023         function
9024         | Pathname _ | Device _ | Dev_or_Path _ | String _
9025         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9026         | StringList n | DeviceList n ->
9027             pr "  free (%s);\n" n
9028       ) (snd style);
9029
9030       pr "  if (r == %s) {\n" error_code;
9031       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9032       pr "    return NULL;\n";
9033       pr "  }\n";
9034       pr "\n";
9035
9036       (match fst style with
9037        | RErr ->
9038            pr "  Py_INCREF (Py_None);\n";
9039            pr "  py_r = Py_None;\n"
9040        | RInt _
9041        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9042        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9043        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9044        | RConstOptString _ ->
9045            pr "  if (r)\n";
9046            pr "    py_r = PyString_FromString (r);\n";
9047            pr "  else {\n";
9048            pr "    Py_INCREF (Py_None);\n";
9049            pr "    py_r = Py_None;\n";
9050            pr "  }\n"
9051        | RString _ ->
9052            pr "  py_r = PyString_FromString (r);\n";
9053            pr "  free (r);\n"
9054        | RStringList _ ->
9055            pr "  py_r = put_string_list (r);\n";
9056            pr "  free_strings (r);\n"
9057        | RStruct (_, typ) ->
9058            pr "  py_r = put_%s (r);\n" typ;
9059            pr "  guestfs_free_%s (r);\n" typ
9060        | RStructList (_, typ) ->
9061            pr "  py_r = put_%s_list (r);\n" typ;
9062            pr "  guestfs_free_%s_list (r);\n" typ
9063        | RHashtable n ->
9064            pr "  py_r = put_table (r);\n";
9065            pr "  free_strings (r);\n"
9066        | RBufferOut _ ->
9067            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9068            pr "  free (r);\n"
9069       );
9070
9071       pr "  return py_r;\n";
9072       pr "}\n";
9073       pr "\n"
9074   ) all_functions;
9075
9076   (* Table of functions. *)
9077   pr "static PyMethodDef methods[] = {\n";
9078   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9079   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9080   List.iter (
9081     fun (name, _, _, _, _, _, _) ->
9082       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9083         name name
9084   ) all_functions;
9085   pr "  { NULL, NULL, 0, NULL }\n";
9086   pr "};\n";
9087   pr "\n";
9088
9089   (* Init function. *)
9090   pr "\
9091 void
9092 initlibguestfsmod (void)
9093 {
9094   static int initialized = 0;
9095
9096   if (initialized) return;
9097   Py_InitModule ((char *) \"libguestfsmod\", methods);
9098   initialized = 1;
9099 }
9100 "
9101
9102 (* Generate Python module. *)
9103 and generate_python_py () =
9104   generate_header HashStyle LGPLv2plus;
9105
9106   pr "\
9107 u\"\"\"Python bindings for libguestfs
9108
9109 import guestfs
9110 g = guestfs.GuestFS ()
9111 g.add_drive (\"guest.img\")
9112 g.launch ()
9113 parts = g.list_partitions ()
9114
9115 The guestfs module provides a Python binding to the libguestfs API
9116 for examining and modifying virtual machine disk images.
9117
9118 Amongst the things this is good for: making batch configuration
9119 changes to guests, getting disk used/free statistics (see also:
9120 virt-df), migrating between virtualization systems (see also:
9121 virt-p2v), performing partial backups, performing partial guest
9122 clones, cloning guests and changing registry/UUID/hostname info, and
9123 much else besides.
9124
9125 Libguestfs uses Linux kernel and qemu code, and can access any type of
9126 guest filesystem that Linux and qemu can, including but not limited
9127 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9128 schemes, qcow, qcow2, vmdk.
9129
9130 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9131 LVs, what filesystem is in each LV, etc.).  It can also run commands
9132 in the context of the guest.  Also you can access filesystems over
9133 FUSE.
9134
9135 Errors which happen while using the API are turned into Python
9136 RuntimeError exceptions.
9137
9138 To create a guestfs handle you usually have to perform the following
9139 sequence of calls:
9140
9141 # Create the handle, call add_drive at least once, and possibly
9142 # several times if the guest has multiple block devices:
9143 g = guestfs.GuestFS ()
9144 g.add_drive (\"guest.img\")
9145
9146 # Launch the qemu subprocess and wait for it to become ready:
9147 g.launch ()
9148
9149 # Now you can issue commands, for example:
9150 logvols = g.lvs ()
9151
9152 \"\"\"
9153
9154 import libguestfsmod
9155
9156 class GuestFS:
9157     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9158
9159     def __init__ (self):
9160         \"\"\"Create a new libguestfs handle.\"\"\"
9161         self._o = libguestfsmod.create ()
9162
9163     def __del__ (self):
9164         libguestfsmod.close (self._o)
9165
9166 ";
9167
9168   List.iter (
9169     fun (name, style, _, flags, _, _, longdesc) ->
9170       pr "    def %s " name;
9171       generate_py_call_args ~handle:"self" (snd style);
9172       pr ":\n";
9173
9174       if not (List.mem NotInDocs flags) then (
9175         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9176         let doc =
9177           match fst style with
9178           | RErr | RInt _ | RInt64 _ | RBool _
9179           | RConstOptString _ | RConstString _
9180           | RString _ | RBufferOut _ -> doc
9181           | RStringList _ ->
9182               doc ^ "\n\nThis function returns a list of strings."
9183           | RStruct (_, typ) ->
9184               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9185           | RStructList (_, typ) ->
9186               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9187           | RHashtable _ ->
9188               doc ^ "\n\nThis function returns a dictionary." in
9189         let doc =
9190           if List.mem ProtocolLimitWarning flags then
9191             doc ^ "\n\n" ^ protocol_limit_warning
9192           else doc in
9193         let doc =
9194           if List.mem DangerWillRobinson flags then
9195             doc ^ "\n\n" ^ danger_will_robinson
9196           else doc in
9197         let doc =
9198           match deprecation_notice flags with
9199           | None -> doc
9200           | Some txt -> doc ^ "\n\n" ^ txt in
9201         let doc = pod2text ~width:60 name doc in
9202         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9203         let doc = String.concat "\n        " doc in
9204         pr "        u\"\"\"%s\"\"\"\n" doc;
9205       );
9206       pr "        return libguestfsmod.%s " name;
9207       generate_py_call_args ~handle:"self._o" (snd style);
9208       pr "\n";
9209       pr "\n";
9210   ) all_functions
9211
9212 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9213 and generate_py_call_args ~handle args =
9214   pr "(%s" handle;
9215   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9216   pr ")"
9217
9218 (* Useful if you need the longdesc POD text as plain text.  Returns a
9219  * list of lines.
9220  *
9221  * Because this is very slow (the slowest part of autogeneration),
9222  * we memoize the results.
9223  *)
9224 and pod2text ~width name longdesc =
9225   let key = width, name, longdesc in
9226   try Hashtbl.find pod2text_memo key
9227   with Not_found ->
9228     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9229     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9230     close_out chan;
9231     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9232     let chan = open_process_in cmd in
9233     let lines = ref [] in
9234     let rec loop i =
9235       let line = input_line chan in
9236       if i = 1 then             (* discard the first line of output *)
9237         loop (i+1)
9238       else (
9239         let line = triml line in
9240         lines := line :: !lines;
9241         loop (i+1)
9242       ) in
9243     let lines = try loop 1 with End_of_file -> List.rev !lines in
9244     unlink filename;
9245     (match close_process_in chan with
9246      | WEXITED 0 -> ()
9247      | WEXITED i ->
9248          failwithf "pod2text: process exited with non-zero status (%d)" i
9249      | WSIGNALED i | WSTOPPED i ->
9250          failwithf "pod2text: process signalled or stopped by signal %d" i
9251     );
9252     Hashtbl.add pod2text_memo key lines;
9253     pod2text_memo_updated ();
9254     lines
9255
9256 (* Generate ruby bindings. *)
9257 and generate_ruby_c () =
9258   generate_header CStyle LGPLv2plus;
9259
9260   pr "\
9261 #include <stdio.h>
9262 #include <stdlib.h>
9263
9264 #include <ruby.h>
9265
9266 #include \"guestfs.h\"
9267
9268 #include \"extconf.h\"
9269
9270 /* For Ruby < 1.9 */
9271 #ifndef RARRAY_LEN
9272 #define RARRAY_LEN(r) (RARRAY((r))->len)
9273 #endif
9274
9275 static VALUE m_guestfs;                 /* guestfs module */
9276 static VALUE c_guestfs;                 /* guestfs_h handle */
9277 static VALUE e_Error;                   /* used for all errors */
9278
9279 static void ruby_guestfs_free (void *p)
9280 {
9281   if (!p) return;
9282   guestfs_close ((guestfs_h *) p);
9283 }
9284
9285 static VALUE ruby_guestfs_create (VALUE m)
9286 {
9287   guestfs_h *g;
9288
9289   g = guestfs_create ();
9290   if (!g)
9291     rb_raise (e_Error, \"failed to create guestfs handle\");
9292
9293   /* Don't print error messages to stderr by default. */
9294   guestfs_set_error_handler (g, NULL, NULL);
9295
9296   /* Wrap it, and make sure the close function is called when the
9297    * handle goes away.
9298    */
9299   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9300 }
9301
9302 static VALUE ruby_guestfs_close (VALUE gv)
9303 {
9304   guestfs_h *g;
9305   Data_Get_Struct (gv, guestfs_h, g);
9306
9307   ruby_guestfs_free (g);
9308   DATA_PTR (gv) = NULL;
9309
9310   return Qnil;
9311 }
9312
9313 ";
9314
9315   List.iter (
9316     fun (name, style, _, _, _, _, _) ->
9317       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9318       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9319       pr ")\n";
9320       pr "{\n";
9321       pr "  guestfs_h *g;\n";
9322       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9323       pr "  if (!g)\n";
9324       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9325         name;
9326       pr "\n";
9327
9328       List.iter (
9329         function
9330         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9331             pr "  Check_Type (%sv, T_STRING);\n" n;
9332             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9333             pr "  if (!%s)\n" n;
9334             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9335             pr "              \"%s\", \"%s\");\n" n name
9336         | OptString n ->
9337             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9338         | StringList n | DeviceList n ->
9339             pr "  char **%s;\n" n;
9340             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9341             pr "  {\n";
9342             pr "    int i, len;\n";
9343             pr "    len = RARRAY_LEN (%sv);\n" n;
9344             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9345               n;
9346             pr "    for (i = 0; i < len; ++i) {\n";
9347             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9348             pr "      %s[i] = StringValueCStr (v);\n" n;
9349             pr "    }\n";
9350             pr "    %s[len] = NULL;\n" n;
9351             pr "  }\n";
9352         | Bool n ->
9353             pr "  int %s = RTEST (%sv);\n" n n
9354         | Int n ->
9355             pr "  int %s = NUM2INT (%sv);\n" n n
9356         | Int64 n ->
9357             pr "  long long %s = NUM2LL (%sv);\n" n n
9358       ) (snd style);
9359       pr "\n";
9360
9361       let error_code =
9362         match fst style with
9363         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9364         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9365         | RConstString _ | RConstOptString _ ->
9366             pr "  const char *r;\n"; "NULL"
9367         | RString _ -> pr "  char *r;\n"; "NULL"
9368         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9369         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9370         | RStructList (_, typ) ->
9371             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9372         | RBufferOut _ ->
9373             pr "  char *r;\n";
9374             pr "  size_t size;\n";
9375             "NULL" in
9376       pr "\n";
9377
9378       pr "  r = guestfs_%s " name;
9379       generate_c_call_args ~handle:"g" style;
9380       pr ";\n";
9381
9382       List.iter (
9383         function
9384         | Pathname _ | Device _ | Dev_or_Path _ | String _
9385         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9386         | StringList n | DeviceList n ->
9387             pr "  free (%s);\n" n
9388       ) (snd style);
9389
9390       pr "  if (r == %s)\n" error_code;
9391       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9392       pr "\n";
9393
9394       (match fst style with
9395        | RErr ->
9396            pr "  return Qnil;\n"
9397        | RInt _ | RBool _ ->
9398            pr "  return INT2NUM (r);\n"
9399        | RInt64 _ ->
9400            pr "  return ULL2NUM (r);\n"
9401        | RConstString _ ->
9402            pr "  return rb_str_new2 (r);\n";
9403        | RConstOptString _ ->
9404            pr "  if (r)\n";
9405            pr "    return rb_str_new2 (r);\n";
9406            pr "  else\n";
9407            pr "    return Qnil;\n";
9408        | RString _ ->
9409            pr "  VALUE rv = rb_str_new2 (r);\n";
9410            pr "  free (r);\n";
9411            pr "  return rv;\n";
9412        | RStringList _ ->
9413            pr "  int i, len = 0;\n";
9414            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9415            pr "  VALUE rv = rb_ary_new2 (len);\n";
9416            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9417            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9418            pr "    free (r[i]);\n";
9419            pr "  }\n";
9420            pr "  free (r);\n";
9421            pr "  return rv;\n"
9422        | RStruct (_, typ) ->
9423            let cols = cols_of_struct typ in
9424            generate_ruby_struct_code typ cols
9425        | RStructList (_, typ) ->
9426            let cols = cols_of_struct typ in
9427            generate_ruby_struct_list_code typ cols
9428        | RHashtable _ ->
9429            pr "  VALUE rv = rb_hash_new ();\n";
9430            pr "  int i;\n";
9431            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9432            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9433            pr "    free (r[i]);\n";
9434            pr "    free (r[i+1]);\n";
9435            pr "  }\n";
9436            pr "  free (r);\n";
9437            pr "  return rv;\n"
9438        | RBufferOut _ ->
9439            pr "  VALUE rv = rb_str_new (r, size);\n";
9440            pr "  free (r);\n";
9441            pr "  return rv;\n";
9442       );
9443
9444       pr "}\n";
9445       pr "\n"
9446   ) all_functions;
9447
9448   pr "\
9449 /* Initialize the module. */
9450 void Init__guestfs ()
9451 {
9452   m_guestfs = rb_define_module (\"Guestfs\");
9453   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9454   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9455
9456   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9457   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9458
9459 ";
9460   (* Define the rest of the methods. *)
9461   List.iter (
9462     fun (name, style, _, _, _, _, _) ->
9463       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9464       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9465   ) all_functions;
9466
9467   pr "}\n"
9468
9469 (* Ruby code to return a struct. *)
9470 and generate_ruby_struct_code typ cols =
9471   pr "  VALUE rv = rb_hash_new ();\n";
9472   List.iter (
9473     function
9474     | name, FString ->
9475         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9476     | name, FBuffer ->
9477         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9478     | name, FUUID ->
9479         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9480     | name, (FBytes|FUInt64) ->
9481         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9482     | name, FInt64 ->
9483         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9484     | name, FUInt32 ->
9485         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9486     | name, FInt32 ->
9487         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9488     | name, FOptPercent ->
9489         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9490     | name, FChar -> (* XXX wrong? *)
9491         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9492   ) cols;
9493   pr "  guestfs_free_%s (r);\n" typ;
9494   pr "  return rv;\n"
9495
9496 (* Ruby code to return a struct list. *)
9497 and generate_ruby_struct_list_code typ cols =
9498   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9499   pr "  int i;\n";
9500   pr "  for (i = 0; i < r->len; ++i) {\n";
9501   pr "    VALUE hv = rb_hash_new ();\n";
9502   List.iter (
9503     function
9504     | name, FString ->
9505         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9506     | name, FBuffer ->
9507         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
9508     | name, FUUID ->
9509         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9510     | name, (FBytes|FUInt64) ->
9511         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9512     | name, FInt64 ->
9513         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9514     | name, FUInt32 ->
9515         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9516     | name, FInt32 ->
9517         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9518     | name, FOptPercent ->
9519         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9520     | name, FChar -> (* XXX wrong? *)
9521         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9522   ) cols;
9523   pr "    rb_ary_push (rv, hv);\n";
9524   pr "  }\n";
9525   pr "  guestfs_free_%s_list (r);\n" typ;
9526   pr "  return rv;\n"
9527
9528 (* Generate Java bindings GuestFS.java file. *)
9529 and generate_java_java () =
9530   generate_header CStyle LGPLv2plus;
9531
9532   pr "\
9533 package com.redhat.et.libguestfs;
9534
9535 import java.util.HashMap;
9536 import com.redhat.et.libguestfs.LibGuestFSException;
9537 import com.redhat.et.libguestfs.PV;
9538 import com.redhat.et.libguestfs.VG;
9539 import com.redhat.et.libguestfs.LV;
9540 import com.redhat.et.libguestfs.Stat;
9541 import com.redhat.et.libguestfs.StatVFS;
9542 import com.redhat.et.libguestfs.IntBool;
9543 import com.redhat.et.libguestfs.Dirent;
9544
9545 /**
9546  * The GuestFS object is a libguestfs handle.
9547  *
9548  * @author rjones
9549  */
9550 public class GuestFS {
9551   // Load the native code.
9552   static {
9553     System.loadLibrary (\"guestfs_jni\");
9554   }
9555
9556   /**
9557    * The native guestfs_h pointer.
9558    */
9559   long g;
9560
9561   /**
9562    * Create a libguestfs handle.
9563    *
9564    * @throws LibGuestFSException
9565    */
9566   public GuestFS () throws LibGuestFSException
9567   {
9568     g = _create ();
9569   }
9570   private native long _create () throws LibGuestFSException;
9571
9572   /**
9573    * Close a libguestfs handle.
9574    *
9575    * You can also leave handles to be collected by the garbage
9576    * collector, but this method ensures that the resources used
9577    * by the handle are freed up immediately.  If you call any
9578    * other methods after closing the handle, you will get an
9579    * exception.
9580    *
9581    * @throws LibGuestFSException
9582    */
9583   public void close () throws LibGuestFSException
9584   {
9585     if (g != 0)
9586       _close (g);
9587     g = 0;
9588   }
9589   private native void _close (long g) throws LibGuestFSException;
9590
9591   public void finalize () throws LibGuestFSException
9592   {
9593     close ();
9594   }
9595
9596 ";
9597
9598   List.iter (
9599     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9600       if not (List.mem NotInDocs flags); then (
9601         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9602         let doc =
9603           if List.mem ProtocolLimitWarning flags then
9604             doc ^ "\n\n" ^ protocol_limit_warning
9605           else doc in
9606         let doc =
9607           if List.mem DangerWillRobinson flags then
9608             doc ^ "\n\n" ^ danger_will_robinson
9609           else doc in
9610         let doc =
9611           match deprecation_notice flags with
9612           | None -> doc
9613           | Some txt -> doc ^ "\n\n" ^ txt in
9614         let doc = pod2text ~width:60 name doc in
9615         let doc = List.map (            (* RHBZ#501883 *)
9616           function
9617           | "" -> "<p>"
9618           | nonempty -> nonempty
9619         ) doc in
9620         let doc = String.concat "\n   * " doc in
9621
9622         pr "  /**\n";
9623         pr "   * %s\n" shortdesc;
9624         pr "   * <p>\n";
9625         pr "   * %s\n" doc;
9626         pr "   * @throws LibGuestFSException\n";
9627         pr "   */\n";
9628         pr "  ";
9629       );
9630       generate_java_prototype ~public:true ~semicolon:false name style;
9631       pr "\n";
9632       pr "  {\n";
9633       pr "    if (g == 0)\n";
9634       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9635         name;
9636       pr "    ";
9637       if fst style <> RErr then pr "return ";
9638       pr "_%s " name;
9639       generate_java_call_args ~handle:"g" (snd style);
9640       pr ";\n";
9641       pr "  }\n";
9642       pr "  ";
9643       generate_java_prototype ~privat:true ~native:true name style;
9644       pr "\n";
9645       pr "\n";
9646   ) all_functions;
9647
9648   pr "}\n"
9649
9650 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9651 and generate_java_call_args ~handle args =
9652   pr "(%s" handle;
9653   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9654   pr ")"
9655
9656 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9657     ?(semicolon=true) name style =
9658   if privat then pr "private ";
9659   if public then pr "public ";
9660   if native then pr "native ";
9661
9662   (* return type *)
9663   (match fst style with
9664    | RErr -> pr "void ";
9665    | RInt _ -> pr "int ";
9666    | RInt64 _ -> pr "long ";
9667    | RBool _ -> pr "boolean ";
9668    | RConstString _ | RConstOptString _ | RString _
9669    | RBufferOut _ -> pr "String ";
9670    | RStringList _ -> pr "String[] ";
9671    | RStruct (_, typ) ->
9672        let name = java_name_of_struct typ in
9673        pr "%s " name;
9674    | RStructList (_, typ) ->
9675        let name = java_name_of_struct typ in
9676        pr "%s[] " name;
9677    | RHashtable _ -> pr "HashMap<String,String> ";
9678   );
9679
9680   if native then pr "_%s " name else pr "%s " name;
9681   pr "(";
9682   let needs_comma = ref false in
9683   if native then (
9684     pr "long g";
9685     needs_comma := true
9686   );
9687
9688   (* args *)
9689   List.iter (
9690     fun arg ->
9691       if !needs_comma then pr ", ";
9692       needs_comma := true;
9693
9694       match arg with
9695       | Pathname n
9696       | Device n | Dev_or_Path n
9697       | String n
9698       | OptString n
9699       | FileIn n
9700       | FileOut n ->
9701           pr "String %s" n
9702       | StringList n | DeviceList n ->
9703           pr "String[] %s" n
9704       | Bool n ->
9705           pr "boolean %s" n
9706       | Int n ->
9707           pr "int %s" n
9708       | Int64 n ->
9709           pr "long %s" n
9710   ) (snd style);
9711
9712   pr ")\n";
9713   pr "    throws LibGuestFSException";
9714   if semicolon then pr ";"
9715
9716 and generate_java_struct jtyp cols () =
9717   generate_header CStyle LGPLv2plus;
9718
9719   pr "\
9720 package com.redhat.et.libguestfs;
9721
9722 /**
9723  * Libguestfs %s structure.
9724  *
9725  * @author rjones
9726  * @see GuestFS
9727  */
9728 public class %s {
9729 " jtyp jtyp;
9730
9731   List.iter (
9732     function
9733     | name, FString
9734     | name, FUUID
9735     | name, FBuffer -> pr "  public String %s;\n" name
9736     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9737     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9738     | name, FChar -> pr "  public char %s;\n" name
9739     | name, FOptPercent ->
9740         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9741         pr "  public float %s;\n" name
9742   ) cols;
9743
9744   pr "}\n"
9745
9746 and generate_java_c () =
9747   generate_header CStyle LGPLv2plus;
9748
9749   pr "\
9750 #include <stdio.h>
9751 #include <stdlib.h>
9752 #include <string.h>
9753
9754 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9755 #include \"guestfs.h\"
9756
9757 /* Note that this function returns.  The exception is not thrown
9758  * until after the wrapper function returns.
9759  */
9760 static void
9761 throw_exception (JNIEnv *env, const char *msg)
9762 {
9763   jclass cl;
9764   cl = (*env)->FindClass (env,
9765                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9766   (*env)->ThrowNew (env, cl, msg);
9767 }
9768
9769 JNIEXPORT jlong JNICALL
9770 Java_com_redhat_et_libguestfs_GuestFS__1create
9771   (JNIEnv *env, jobject obj)
9772 {
9773   guestfs_h *g;
9774
9775   g = guestfs_create ();
9776   if (g == NULL) {
9777     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9778     return 0;
9779   }
9780   guestfs_set_error_handler (g, NULL, NULL);
9781   return (jlong) (long) g;
9782 }
9783
9784 JNIEXPORT void JNICALL
9785 Java_com_redhat_et_libguestfs_GuestFS__1close
9786   (JNIEnv *env, jobject obj, jlong jg)
9787 {
9788   guestfs_h *g = (guestfs_h *) (long) jg;
9789   guestfs_close (g);
9790 }
9791
9792 ";
9793
9794   List.iter (
9795     fun (name, style, _, _, _, _, _) ->
9796       pr "JNIEXPORT ";
9797       (match fst style with
9798        | RErr -> pr "void ";
9799        | RInt _ -> pr "jint ";
9800        | RInt64 _ -> pr "jlong ";
9801        | RBool _ -> pr "jboolean ";
9802        | RConstString _ | RConstOptString _ | RString _
9803        | RBufferOut _ -> pr "jstring ";
9804        | RStruct _ | RHashtable _ ->
9805            pr "jobject ";
9806        | RStringList _ | RStructList _ ->
9807            pr "jobjectArray ";
9808       );
9809       pr "JNICALL\n";
9810       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9811       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9812       pr "\n";
9813       pr "  (JNIEnv *env, jobject obj, jlong jg";
9814       List.iter (
9815         function
9816         | Pathname n
9817         | Device n | Dev_or_Path n
9818         | String n
9819         | OptString n
9820         | FileIn n
9821         | FileOut n ->
9822             pr ", jstring j%s" n
9823         | StringList n | DeviceList n ->
9824             pr ", jobjectArray j%s" n
9825         | Bool n ->
9826             pr ", jboolean j%s" n
9827         | Int n ->
9828             pr ", jint j%s" n
9829         | Int64 n ->
9830             pr ", jlong j%s" n
9831       ) (snd style);
9832       pr ")\n";
9833       pr "{\n";
9834       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9835       let error_code, no_ret =
9836         match fst style with
9837         | RErr -> pr "  int r;\n"; "-1", ""
9838         | RBool _
9839         | RInt _ -> pr "  int r;\n"; "-1", "0"
9840         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9841         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9842         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9843         | RString _ ->
9844             pr "  jstring jr;\n";
9845             pr "  char *r;\n"; "NULL", "NULL"
9846         | RStringList _ ->
9847             pr "  jobjectArray jr;\n";
9848             pr "  int r_len;\n";
9849             pr "  jclass cl;\n";
9850             pr "  jstring jstr;\n";
9851             pr "  char **r;\n"; "NULL", "NULL"
9852         | RStruct (_, typ) ->
9853             pr "  jobject jr;\n";
9854             pr "  jclass cl;\n";
9855             pr "  jfieldID fl;\n";
9856             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9857         | RStructList (_, typ) ->
9858             pr "  jobjectArray jr;\n";
9859             pr "  jclass cl;\n";
9860             pr "  jfieldID fl;\n";
9861             pr "  jobject jfl;\n";
9862             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9863         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9864         | RBufferOut _ ->
9865             pr "  jstring jr;\n";
9866             pr "  char *r;\n";
9867             pr "  size_t size;\n";
9868             "NULL", "NULL" in
9869       List.iter (
9870         function
9871         | Pathname n
9872         | Device n | Dev_or_Path n
9873         | String n
9874         | OptString n
9875         | FileIn n
9876         | FileOut n ->
9877             pr "  const char *%s;\n" n
9878         | StringList n | DeviceList n ->
9879             pr "  int %s_len;\n" n;
9880             pr "  const char **%s;\n" n
9881         | Bool n
9882         | Int n ->
9883             pr "  int %s;\n" n
9884         | Int64 n ->
9885             pr "  int64_t %s;\n" n
9886       ) (snd style);
9887
9888       let needs_i =
9889         (match fst style with
9890          | RStringList _ | RStructList _ -> true
9891          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9892          | RConstOptString _
9893          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9894           List.exists (function
9895                        | StringList _ -> true
9896                        | DeviceList _ -> true
9897                        | _ -> false) (snd style) in
9898       if needs_i then
9899         pr "  int i;\n";
9900
9901       pr "\n";
9902
9903       (* Get the parameters. *)
9904       List.iter (
9905         function
9906         | Pathname n
9907         | Device n | Dev_or_Path n
9908         | String n
9909         | FileIn n
9910         | FileOut n ->
9911             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9912         | OptString n ->
9913             (* This is completely undocumented, but Java null becomes
9914              * a NULL parameter.
9915              *)
9916             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9917         | StringList n | DeviceList n ->
9918             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9919             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9920             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9921             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9922               n;
9923             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9924             pr "  }\n";
9925             pr "  %s[%s_len] = NULL;\n" n n;
9926         | Bool n
9927         | Int n
9928         | Int64 n ->
9929             pr "  %s = j%s;\n" n n
9930       ) (snd style);
9931
9932       (* Make the call. *)
9933       pr "  r = guestfs_%s " name;
9934       generate_c_call_args ~handle:"g" style;
9935       pr ";\n";
9936
9937       (* Release the parameters. *)
9938       List.iter (
9939         function
9940         | Pathname n
9941         | Device n | Dev_or_Path n
9942         | String n
9943         | FileIn n
9944         | FileOut n ->
9945             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9946         | OptString n ->
9947             pr "  if (j%s)\n" n;
9948             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9949         | StringList n | DeviceList n ->
9950             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9951             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9952               n;
9953             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9954             pr "  }\n";
9955             pr "  free (%s);\n" n
9956         | Bool n
9957         | Int n
9958         | Int64 n -> ()
9959       ) (snd style);
9960
9961       (* Check for errors. *)
9962       pr "  if (r == %s) {\n" error_code;
9963       pr "    throw_exception (env, guestfs_last_error (g));\n";
9964       pr "    return %s;\n" no_ret;
9965       pr "  }\n";
9966
9967       (* Return value. *)
9968       (match fst style with
9969        | RErr -> ()
9970        | RInt _ -> pr "  return (jint) r;\n"
9971        | RBool _ -> pr "  return (jboolean) r;\n"
9972        | RInt64 _ -> pr "  return (jlong) r;\n"
9973        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9974        | RConstOptString _ ->
9975            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9976        | RString _ ->
9977            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9978            pr "  free (r);\n";
9979            pr "  return jr;\n"
9980        | RStringList _ ->
9981            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9982            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9983            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9984            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9985            pr "  for (i = 0; i < r_len; ++i) {\n";
9986            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9987            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9988            pr "    free (r[i]);\n";
9989            pr "  }\n";
9990            pr "  free (r);\n";
9991            pr "  return jr;\n"
9992        | RStruct (_, typ) ->
9993            let jtyp = java_name_of_struct typ in
9994            let cols = cols_of_struct typ in
9995            generate_java_struct_return typ jtyp cols
9996        | RStructList (_, typ) ->
9997            let jtyp = java_name_of_struct typ in
9998            let cols = cols_of_struct typ in
9999            generate_java_struct_list_return typ jtyp cols
10000        | RHashtable _ ->
10001            (* XXX *)
10002            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10003            pr "  return NULL;\n"
10004        | RBufferOut _ ->
10005            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10006            pr "  free (r);\n";
10007            pr "  return jr;\n"
10008       );
10009
10010       pr "}\n";
10011       pr "\n"
10012   ) all_functions
10013
10014 and generate_java_struct_return typ jtyp cols =
10015   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10016   pr "  jr = (*env)->AllocObject (env, cl);\n";
10017   List.iter (
10018     function
10019     | name, FString ->
10020         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10021         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10022     | name, FUUID ->
10023         pr "  {\n";
10024         pr "    char s[33];\n";
10025         pr "    memcpy (s, r->%s, 32);\n" name;
10026         pr "    s[32] = 0;\n";
10027         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10028         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10029         pr "  }\n";
10030     | name, FBuffer ->
10031         pr "  {\n";
10032         pr "    int len = r->%s_len;\n" name;
10033         pr "    char s[len+1];\n";
10034         pr "    memcpy (s, r->%s, len);\n" name;
10035         pr "    s[len] = 0;\n";
10036         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10037         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10038         pr "  }\n";
10039     | name, (FBytes|FUInt64|FInt64) ->
10040         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10041         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10042     | name, (FUInt32|FInt32) ->
10043         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10044         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10045     | name, FOptPercent ->
10046         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10047         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10048     | name, FChar ->
10049         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10050         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10051   ) cols;
10052   pr "  free (r);\n";
10053   pr "  return jr;\n"
10054
10055 and generate_java_struct_list_return typ jtyp cols =
10056   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10057   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10058   pr "  for (i = 0; i < r->len; ++i) {\n";
10059   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10060   List.iter (
10061     function
10062     | name, FString ->
10063         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10064         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10065     | name, FUUID ->
10066         pr "    {\n";
10067         pr "      char s[33];\n";
10068         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10069         pr "      s[32] = 0;\n";
10070         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10071         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10072         pr "    }\n";
10073     | name, FBuffer ->
10074         pr "    {\n";
10075         pr "      int len = r->val[i].%s_len;\n" name;
10076         pr "      char s[len+1];\n";
10077         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10078         pr "      s[len] = 0;\n";
10079         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10080         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10081         pr "    }\n";
10082     | name, (FBytes|FUInt64|FInt64) ->
10083         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10084         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10085     | name, (FUInt32|FInt32) ->
10086         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10087         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10088     | name, FOptPercent ->
10089         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10090         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10091     | name, FChar ->
10092         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10093         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10094   ) cols;
10095   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10096   pr "  }\n";
10097   pr "  guestfs_free_%s_list (r);\n" typ;
10098   pr "  return jr;\n"
10099
10100 and generate_java_makefile_inc () =
10101   generate_header HashStyle GPLv2plus;
10102
10103   pr "java_built_sources = \\\n";
10104   List.iter (
10105     fun (typ, jtyp) ->
10106         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10107   ) java_structs;
10108   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10109
10110 and generate_haskell_hs () =
10111   generate_header HaskellStyle LGPLv2plus;
10112
10113   (* XXX We only know how to generate partial FFI for Haskell
10114    * at the moment.  Please help out!
10115    *)
10116   let can_generate style =
10117     match style with
10118     | RErr, _
10119     | RInt _, _
10120     | RInt64 _, _ -> true
10121     | RBool _, _
10122     | RConstString _, _
10123     | RConstOptString _, _
10124     | RString _, _
10125     | RStringList _, _
10126     | RStruct _, _
10127     | RStructList _, _
10128     | RHashtable _, _
10129     | RBufferOut _, _ -> false in
10130
10131   pr "\
10132 {-# INCLUDE <guestfs.h> #-}
10133 {-# LANGUAGE ForeignFunctionInterface #-}
10134
10135 module Guestfs (
10136   create";
10137
10138   (* List out the names of the actions we want to export. *)
10139   List.iter (
10140     fun (name, style, _, _, _, _, _) ->
10141       if can_generate style then pr ",\n  %s" name
10142   ) all_functions;
10143
10144   pr "
10145   ) where
10146
10147 -- Unfortunately some symbols duplicate ones already present
10148 -- in Prelude.  We don't know which, so we hard-code a list
10149 -- here.
10150 import Prelude hiding (truncate)
10151
10152 import Foreign
10153 import Foreign.C
10154 import Foreign.C.Types
10155 import IO
10156 import Control.Exception
10157 import Data.Typeable
10158
10159 data GuestfsS = GuestfsS            -- represents the opaque C struct
10160 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10161 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10162
10163 -- XXX define properly later XXX
10164 data PV = PV
10165 data VG = VG
10166 data LV = LV
10167 data IntBool = IntBool
10168 data Stat = Stat
10169 data StatVFS = StatVFS
10170 data Hashtable = Hashtable
10171
10172 foreign import ccall unsafe \"guestfs_create\" c_create
10173   :: IO GuestfsP
10174 foreign import ccall unsafe \"&guestfs_close\" c_close
10175   :: FunPtr (GuestfsP -> IO ())
10176 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10177   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10178
10179 create :: IO GuestfsH
10180 create = do
10181   p <- c_create
10182   c_set_error_handler p nullPtr nullPtr
10183   h <- newForeignPtr c_close p
10184   return h
10185
10186 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10187   :: GuestfsP -> IO CString
10188
10189 -- last_error :: GuestfsH -> IO (Maybe String)
10190 -- last_error h = do
10191 --   str <- withForeignPtr h (\\p -> c_last_error p)
10192 --   maybePeek peekCString str
10193
10194 last_error :: GuestfsH -> IO (String)
10195 last_error h = do
10196   str <- withForeignPtr h (\\p -> c_last_error p)
10197   if (str == nullPtr)
10198     then return \"no error\"
10199     else peekCString str
10200
10201 ";
10202
10203   (* Generate wrappers for each foreign function. *)
10204   List.iter (
10205     fun (name, style, _, _, _, _, _) ->
10206       if can_generate style then (
10207         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10208         pr "  :: ";
10209         generate_haskell_prototype ~handle:"GuestfsP" style;
10210         pr "\n";
10211         pr "\n";
10212         pr "%s :: " name;
10213         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10214         pr "\n";
10215         pr "%s %s = do\n" name
10216           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10217         pr "  r <- ";
10218         (* Convert pointer arguments using with* functions. *)
10219         List.iter (
10220           function
10221           | FileIn n
10222           | FileOut n
10223           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10224           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10225           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10226           | Bool _ | Int _ | Int64 _ -> ()
10227         ) (snd style);
10228         (* Convert integer arguments. *)
10229         let args =
10230           List.map (
10231             function
10232             | Bool n -> sprintf "(fromBool %s)" n
10233             | Int n -> sprintf "(fromIntegral %s)" n
10234             | Int64 n -> sprintf "(fromIntegral %s)" n
10235             | FileIn n | FileOut n
10236             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10237           ) (snd style) in
10238         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10239           (String.concat " " ("p" :: args));
10240         (match fst style with
10241          | RErr | RInt _ | RInt64 _ | RBool _ ->
10242              pr "  if (r == -1)\n";
10243              pr "    then do\n";
10244              pr "      err <- last_error h\n";
10245              pr "      fail err\n";
10246          | RConstString _ | RConstOptString _ | RString _
10247          | RStringList _ | RStruct _
10248          | RStructList _ | RHashtable _ | RBufferOut _ ->
10249              pr "  if (r == nullPtr)\n";
10250              pr "    then do\n";
10251              pr "      err <- last_error h\n";
10252              pr "      fail err\n";
10253         );
10254         (match fst style with
10255          | RErr ->
10256              pr "    else return ()\n"
10257          | RInt _ ->
10258              pr "    else return (fromIntegral r)\n"
10259          | RInt64 _ ->
10260              pr "    else return (fromIntegral r)\n"
10261          | RBool _ ->
10262              pr "    else return (toBool r)\n"
10263          | RConstString _
10264          | RConstOptString _
10265          | RString _
10266          | RStringList _
10267          | RStruct _
10268          | RStructList _
10269          | RHashtable _
10270          | RBufferOut _ ->
10271              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10272         );
10273         pr "\n";
10274       )
10275   ) all_functions
10276
10277 and generate_haskell_prototype ~handle ?(hs = false) style =
10278   pr "%s -> " handle;
10279   let string = if hs then "String" else "CString" in
10280   let int = if hs then "Int" else "CInt" in
10281   let bool = if hs then "Bool" else "CInt" in
10282   let int64 = if hs then "Integer" else "Int64" in
10283   List.iter (
10284     fun arg ->
10285       (match arg with
10286        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10287        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10288        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10289        | Bool _ -> pr "%s" bool
10290        | Int _ -> pr "%s" int
10291        | Int64 _ -> pr "%s" int
10292        | FileIn _ -> pr "%s" string
10293        | FileOut _ -> pr "%s" string
10294       );
10295       pr " -> ";
10296   ) (snd style);
10297   pr "IO (";
10298   (match fst style with
10299    | RErr -> if not hs then pr "CInt"
10300    | RInt _ -> pr "%s" int
10301    | RInt64 _ -> pr "%s" int64
10302    | RBool _ -> pr "%s" bool
10303    | RConstString _ -> pr "%s" string
10304    | RConstOptString _ -> pr "Maybe %s" string
10305    | RString _ -> pr "%s" string
10306    | RStringList _ -> pr "[%s]" string
10307    | RStruct (_, typ) ->
10308        let name = java_name_of_struct typ in
10309        pr "%s" name
10310    | RStructList (_, typ) ->
10311        let name = java_name_of_struct typ in
10312        pr "[%s]" name
10313    | RHashtable _ -> pr "Hashtable"
10314    | RBufferOut _ -> pr "%s" string
10315   );
10316   pr ")"
10317
10318 and generate_csharp () =
10319   generate_header CPlusPlusStyle LGPLv2plus;
10320
10321   (* XXX Make this configurable by the C# assembly users. *)
10322   let library = "libguestfs.so.0" in
10323
10324   pr "\
10325 // These C# bindings are highly experimental at present.
10326 //
10327 // Firstly they only work on Linux (ie. Mono).  In order to get them
10328 // to work on Windows (ie. .Net) you would need to port the library
10329 // itself to Windows first.
10330 //
10331 // The second issue is that some calls are known to be incorrect and
10332 // can cause Mono to segfault.  Particularly: calls which pass or
10333 // return string[], or return any structure value.  This is because
10334 // we haven't worked out the correct way to do this from C#.
10335 //
10336 // The third issue is that when compiling you get a lot of warnings.
10337 // We are not sure whether the warnings are important or not.
10338 //
10339 // Fourthly we do not routinely build or test these bindings as part
10340 // of the make && make check cycle, which means that regressions might
10341 // go unnoticed.
10342 //
10343 // Suggestions and patches are welcome.
10344
10345 // To compile:
10346 //
10347 // gmcs Libguestfs.cs
10348 // mono Libguestfs.exe
10349 //
10350 // (You'll probably want to add a Test class / static main function
10351 // otherwise this won't do anything useful).
10352
10353 using System;
10354 using System.IO;
10355 using System.Runtime.InteropServices;
10356 using System.Runtime.Serialization;
10357 using System.Collections;
10358
10359 namespace Guestfs
10360 {
10361   class Error : System.ApplicationException
10362   {
10363     public Error (string message) : base (message) {}
10364     protected Error (SerializationInfo info, StreamingContext context) {}
10365   }
10366
10367   class Guestfs
10368   {
10369     IntPtr _handle;
10370
10371     [DllImport (\"%s\")]
10372     static extern IntPtr guestfs_create ();
10373
10374     public Guestfs ()
10375     {
10376       _handle = guestfs_create ();
10377       if (_handle == IntPtr.Zero)
10378         throw new Error (\"could not create guestfs handle\");
10379     }
10380
10381     [DllImport (\"%s\")]
10382     static extern void guestfs_close (IntPtr h);
10383
10384     ~Guestfs ()
10385     {
10386       guestfs_close (_handle);
10387     }
10388
10389     [DllImport (\"%s\")]
10390     static extern string guestfs_last_error (IntPtr h);
10391
10392 " library library library;
10393
10394   (* Generate C# structure bindings.  We prefix struct names with
10395    * underscore because C# cannot have conflicting struct names and
10396    * method names (eg. "class stat" and "stat").
10397    *)
10398   List.iter (
10399     fun (typ, cols) ->
10400       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10401       pr "    public class _%s {\n" typ;
10402       List.iter (
10403         function
10404         | name, FChar -> pr "      char %s;\n" name
10405         | name, FString -> pr "      string %s;\n" name
10406         | name, FBuffer ->
10407             pr "      uint %s_len;\n" name;
10408             pr "      string %s;\n" name
10409         | name, FUUID ->
10410             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10411             pr "      string %s;\n" name
10412         | name, FUInt32 -> pr "      uint %s;\n" name
10413         | name, FInt32 -> pr "      int %s;\n" name
10414         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10415         | name, FInt64 -> pr "      long %s;\n" name
10416         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10417       ) cols;
10418       pr "    }\n";
10419       pr "\n"
10420   ) structs;
10421
10422   (* Generate C# function bindings. *)
10423   List.iter (
10424     fun (name, style, _, _, _, shortdesc, _) ->
10425       let rec csharp_return_type () =
10426         match fst style with
10427         | RErr -> "void"
10428         | RBool n -> "bool"
10429         | RInt n -> "int"
10430         | RInt64 n -> "long"
10431         | RConstString n
10432         | RConstOptString n
10433         | RString n
10434         | RBufferOut n -> "string"
10435         | RStruct (_,n) -> "_" ^ n
10436         | RHashtable n -> "Hashtable"
10437         | RStringList n -> "string[]"
10438         | RStructList (_,n) -> sprintf "_%s[]" n
10439
10440       and c_return_type () =
10441         match fst style with
10442         | RErr
10443         | RBool _
10444         | RInt _ -> "int"
10445         | RInt64 _ -> "long"
10446         | RConstString _
10447         | RConstOptString _
10448         | RString _
10449         | RBufferOut _ -> "string"
10450         | RStruct (_,n) -> "_" ^ n
10451         | RHashtable _
10452         | RStringList _ -> "string[]"
10453         | RStructList (_,n) -> sprintf "_%s[]" n
10454
10455       and c_error_comparison () =
10456         match fst style with
10457         | RErr
10458         | RBool _
10459         | RInt _
10460         | RInt64 _ -> "== -1"
10461         | RConstString _
10462         | RConstOptString _
10463         | RString _
10464         | RBufferOut _
10465         | RStruct (_,_)
10466         | RHashtable _
10467         | RStringList _
10468         | RStructList (_,_) -> "== null"
10469
10470       and generate_extern_prototype () =
10471         pr "    static extern %s guestfs_%s (IntPtr h"
10472           (c_return_type ()) name;
10473         List.iter (
10474           function
10475           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10476           | FileIn n | FileOut n ->
10477               pr ", [In] string %s" n
10478           | StringList n | DeviceList n ->
10479               pr ", [In] string[] %s" n
10480           | Bool n ->
10481               pr ", bool %s" n
10482           | Int n ->
10483               pr ", int %s" n
10484           | Int64 n ->
10485               pr ", long %s" n
10486         ) (snd style);
10487         pr ");\n"
10488
10489       and generate_public_prototype () =
10490         pr "    public %s %s (" (csharp_return_type ()) name;
10491         let comma = ref false in
10492         let next () =
10493           if !comma then pr ", ";
10494           comma := true
10495         in
10496         List.iter (
10497           function
10498           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10499           | FileIn n | FileOut n ->
10500               next (); pr "string %s" n
10501           | StringList n | DeviceList n ->
10502               next (); pr "string[] %s" n
10503           | Bool n ->
10504               next (); pr "bool %s" n
10505           | Int n ->
10506               next (); pr "int %s" n
10507           | Int64 n ->
10508               next (); pr "long %s" n
10509         ) (snd style);
10510         pr ")\n"
10511
10512       and generate_call () =
10513         pr "guestfs_%s (_handle" name;
10514         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10515         pr ");\n";
10516       in
10517
10518       pr "    [DllImport (\"%s\")]\n" library;
10519       generate_extern_prototype ();
10520       pr "\n";
10521       pr "    /// <summary>\n";
10522       pr "    /// %s\n" shortdesc;
10523       pr "    /// </summary>\n";
10524       generate_public_prototype ();
10525       pr "    {\n";
10526       pr "      %s r;\n" (c_return_type ());
10527       pr "      r = ";
10528       generate_call ();
10529       pr "      if (r %s)\n" (c_error_comparison ());
10530       pr "        throw new Error (guestfs_last_error (_handle));\n";
10531       (match fst style with
10532        | RErr -> ()
10533        | RBool _ ->
10534            pr "      return r != 0 ? true : false;\n"
10535        | RHashtable _ ->
10536            pr "      Hashtable rr = new Hashtable ();\n";
10537            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10538            pr "        rr.Add (r[i], r[i+1]);\n";
10539            pr "      return rr;\n"
10540        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10541        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10542        | RStructList _ ->
10543            pr "      return r;\n"
10544       );
10545       pr "    }\n";
10546       pr "\n";
10547   ) all_functions_sorted;
10548
10549   pr "  }
10550 }
10551 "
10552
10553 and generate_bindtests () =
10554   generate_header CStyle LGPLv2plus;
10555
10556   pr "\
10557 #include <stdio.h>
10558 #include <stdlib.h>
10559 #include <inttypes.h>
10560 #include <string.h>
10561
10562 #include \"guestfs.h\"
10563 #include \"guestfs-internal.h\"
10564 #include \"guestfs-internal-actions.h\"
10565 #include \"guestfs_protocol.h\"
10566
10567 #define error guestfs_error
10568 #define safe_calloc guestfs_safe_calloc
10569 #define safe_malloc guestfs_safe_malloc
10570
10571 static void
10572 print_strings (char *const *argv)
10573 {
10574   int argc;
10575
10576   printf (\"[\");
10577   for (argc = 0; argv[argc] != NULL; ++argc) {
10578     if (argc > 0) printf (\", \");
10579     printf (\"\\\"%%s\\\"\", argv[argc]);
10580   }
10581   printf (\"]\\n\");
10582 }
10583
10584 /* The test0 function prints its parameters to stdout. */
10585 ";
10586
10587   let test0, tests =
10588     match test_functions with
10589     | [] -> assert false
10590     | test0 :: tests -> test0, tests in
10591
10592   let () =
10593     let (name, style, _, _, _, _, _) = test0 in
10594     generate_prototype ~extern:false ~semicolon:false ~newline:true
10595       ~handle:"g" ~prefix:"guestfs__" name style;
10596     pr "{\n";
10597     List.iter (
10598       function
10599       | Pathname n
10600       | Device n | Dev_or_Path n
10601       | String n
10602       | FileIn n
10603       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10604       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10605       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10606       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10607       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10608       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10609     ) (snd style);
10610     pr "  /* Java changes stdout line buffering so we need this: */\n";
10611     pr "  fflush (stdout);\n";
10612     pr "  return 0;\n";
10613     pr "}\n";
10614     pr "\n" in
10615
10616   List.iter (
10617     fun (name, style, _, _, _, _, _) ->
10618       if String.sub name (String.length name - 3) 3 <> "err" then (
10619         pr "/* Test normal return. */\n";
10620         generate_prototype ~extern:false ~semicolon:false ~newline:true
10621           ~handle:"g" ~prefix:"guestfs__" name style;
10622         pr "{\n";
10623         (match fst style with
10624          | RErr ->
10625              pr "  return 0;\n"
10626          | RInt _ ->
10627              pr "  int r;\n";
10628              pr "  sscanf (val, \"%%d\", &r);\n";
10629              pr "  return r;\n"
10630          | RInt64 _ ->
10631              pr "  int64_t r;\n";
10632              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10633              pr "  return r;\n"
10634          | RBool _ ->
10635              pr "  return STREQ (val, \"true\");\n"
10636          | RConstString _
10637          | RConstOptString _ ->
10638              (* Can't return the input string here.  Return a static
10639               * string so we ensure we get a segfault if the caller
10640               * tries to free it.
10641               *)
10642              pr "  return \"static string\";\n"
10643          | RString _ ->
10644              pr "  return strdup (val);\n"
10645          | RStringList _ ->
10646              pr "  char **strs;\n";
10647              pr "  int n, i;\n";
10648              pr "  sscanf (val, \"%%d\", &n);\n";
10649              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10650              pr "  for (i = 0; i < n; ++i) {\n";
10651              pr "    strs[i] = safe_malloc (g, 16);\n";
10652              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10653              pr "  }\n";
10654              pr "  strs[n] = NULL;\n";
10655              pr "  return strs;\n"
10656          | RStruct (_, typ) ->
10657              pr "  struct guestfs_%s *r;\n" typ;
10658              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10659              pr "  return r;\n"
10660          | RStructList (_, typ) ->
10661              pr "  struct guestfs_%s_list *r;\n" typ;
10662              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10663              pr "  sscanf (val, \"%%d\", &r->len);\n";
10664              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10665              pr "  return r;\n"
10666          | RHashtable _ ->
10667              pr "  char **strs;\n";
10668              pr "  int n, i;\n";
10669              pr "  sscanf (val, \"%%d\", &n);\n";
10670              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10671              pr "  for (i = 0; i < n; ++i) {\n";
10672              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10673              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10674              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10675              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10676              pr "  }\n";
10677              pr "  strs[n*2] = NULL;\n";
10678              pr "  return strs;\n"
10679          | RBufferOut _ ->
10680              pr "  return strdup (val);\n"
10681         );
10682         pr "}\n";
10683         pr "\n"
10684       ) else (
10685         pr "/* Test error return. */\n";
10686         generate_prototype ~extern:false ~semicolon:false ~newline:true
10687           ~handle:"g" ~prefix:"guestfs__" name style;
10688         pr "{\n";
10689         pr "  error (g, \"error\");\n";
10690         (match fst style with
10691          | RErr | RInt _ | RInt64 _ | RBool _ ->
10692              pr "  return -1;\n"
10693          | RConstString _ | RConstOptString _
10694          | RString _ | RStringList _ | RStruct _
10695          | RStructList _
10696          | RHashtable _
10697          | RBufferOut _ ->
10698              pr "  return NULL;\n"
10699         );
10700         pr "}\n";
10701         pr "\n"
10702       )
10703   ) tests
10704
10705 and generate_ocaml_bindtests () =
10706   generate_header OCamlStyle GPLv2plus;
10707
10708   pr "\
10709 let () =
10710   let g = Guestfs.create () in
10711 ";
10712
10713   let mkargs args =
10714     String.concat " " (
10715       List.map (
10716         function
10717         | CallString s -> "\"" ^ s ^ "\""
10718         | CallOptString None -> "None"
10719         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10720         | CallStringList xs ->
10721             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10722         | CallInt i when i >= 0 -> string_of_int i
10723         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10724         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10725         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10726         | CallBool b -> string_of_bool b
10727       ) args
10728     )
10729   in
10730
10731   generate_lang_bindtests (
10732     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10733   );
10734
10735   pr "print_endline \"EOF\"\n"
10736
10737 and generate_perl_bindtests () =
10738   pr "#!/usr/bin/perl -w\n";
10739   generate_header HashStyle GPLv2plus;
10740
10741   pr "\
10742 use strict;
10743
10744 use Sys::Guestfs;
10745
10746 my $g = Sys::Guestfs->new ();
10747 ";
10748
10749   let mkargs args =
10750     String.concat ", " (
10751       List.map (
10752         function
10753         | CallString s -> "\"" ^ s ^ "\""
10754         | CallOptString None -> "undef"
10755         | CallOptString (Some s) -> sprintf "\"%s\"" s
10756         | CallStringList xs ->
10757             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10758         | CallInt i -> string_of_int i
10759         | CallInt64 i -> Int64.to_string i
10760         | CallBool b -> if b then "1" else "0"
10761       ) args
10762     )
10763   in
10764
10765   generate_lang_bindtests (
10766     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10767   );
10768
10769   pr "print \"EOF\\n\"\n"
10770
10771 and generate_python_bindtests () =
10772   generate_header HashStyle GPLv2plus;
10773
10774   pr "\
10775 import guestfs
10776
10777 g = guestfs.GuestFS ()
10778 ";
10779
10780   let mkargs args =
10781     String.concat ", " (
10782       List.map (
10783         function
10784         | CallString s -> "\"" ^ s ^ "\""
10785         | CallOptString None -> "None"
10786         | CallOptString (Some s) -> sprintf "\"%s\"" s
10787         | CallStringList xs ->
10788             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10789         | CallInt i -> string_of_int i
10790         | CallInt64 i -> Int64.to_string i
10791         | CallBool b -> if b then "1" else "0"
10792       ) args
10793     )
10794   in
10795
10796   generate_lang_bindtests (
10797     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10798   );
10799
10800   pr "print \"EOF\"\n"
10801
10802 and generate_ruby_bindtests () =
10803   generate_header HashStyle GPLv2plus;
10804
10805   pr "\
10806 require 'guestfs'
10807
10808 g = Guestfs::create()
10809 ";
10810
10811   let mkargs args =
10812     String.concat ", " (
10813       List.map (
10814         function
10815         | CallString s -> "\"" ^ s ^ "\""
10816         | CallOptString None -> "nil"
10817         | CallOptString (Some s) -> sprintf "\"%s\"" s
10818         | CallStringList xs ->
10819             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10820         | CallInt i -> string_of_int i
10821         | CallInt64 i -> Int64.to_string i
10822         | CallBool b -> string_of_bool b
10823       ) args
10824     )
10825   in
10826
10827   generate_lang_bindtests (
10828     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10829   );
10830
10831   pr "print \"EOF\\n\"\n"
10832
10833 and generate_java_bindtests () =
10834   generate_header CStyle GPLv2plus;
10835
10836   pr "\
10837 import com.redhat.et.libguestfs.*;
10838
10839 public class Bindtests {
10840     public static void main (String[] argv)
10841     {
10842         try {
10843             GuestFS g = new GuestFS ();
10844 ";
10845
10846   let mkargs args =
10847     String.concat ", " (
10848       List.map (
10849         function
10850         | CallString s -> "\"" ^ s ^ "\""
10851         | CallOptString None -> "null"
10852         | CallOptString (Some s) -> sprintf "\"%s\"" s
10853         | CallStringList xs ->
10854             "new String[]{" ^
10855               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10856         | CallInt i -> string_of_int i
10857         | CallInt64 i -> Int64.to_string i
10858         | CallBool b -> string_of_bool b
10859       ) args
10860     )
10861   in
10862
10863   generate_lang_bindtests (
10864     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10865   );
10866
10867   pr "
10868             System.out.println (\"EOF\");
10869         }
10870         catch (Exception exn) {
10871             System.err.println (exn);
10872             System.exit (1);
10873         }
10874     }
10875 }
10876 "
10877
10878 and generate_haskell_bindtests () =
10879   generate_header HaskellStyle GPLv2plus;
10880
10881   pr "\
10882 module Bindtests where
10883 import qualified Guestfs
10884
10885 main = do
10886   g <- Guestfs.create
10887 ";
10888
10889   let mkargs args =
10890     String.concat " " (
10891       List.map (
10892         function
10893         | CallString s -> "\"" ^ s ^ "\""
10894         | CallOptString None -> "Nothing"
10895         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10896         | CallStringList xs ->
10897             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10898         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10899         | CallInt i -> string_of_int i
10900         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10901         | CallInt64 i -> Int64.to_string i
10902         | CallBool true -> "True"
10903         | CallBool false -> "False"
10904       ) args
10905     )
10906   in
10907
10908   generate_lang_bindtests (
10909     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10910   );
10911
10912   pr "  putStrLn \"EOF\"\n"
10913
10914 (* Language-independent bindings tests - we do it this way to
10915  * ensure there is parity in testing bindings across all languages.
10916  *)
10917 and generate_lang_bindtests call =
10918   call "test0" [CallString "abc"; CallOptString (Some "def");
10919                 CallStringList []; CallBool false;
10920                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10921   call "test0" [CallString "abc"; CallOptString None;
10922                 CallStringList []; CallBool false;
10923                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10924   call "test0" [CallString ""; CallOptString (Some "def");
10925                 CallStringList []; CallBool false;
10926                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10927   call "test0" [CallString ""; CallOptString (Some "");
10928                 CallStringList []; CallBool false;
10929                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10930   call "test0" [CallString "abc"; CallOptString (Some "def");
10931                 CallStringList ["1"]; CallBool false;
10932                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10933   call "test0" [CallString "abc"; CallOptString (Some "def");
10934                 CallStringList ["1"; "2"]; CallBool false;
10935                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10936   call "test0" [CallString "abc"; CallOptString (Some "def");
10937                 CallStringList ["1"]; CallBool true;
10938                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10939   call "test0" [CallString "abc"; CallOptString (Some "def");
10940                 CallStringList ["1"]; CallBool false;
10941                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10942   call "test0" [CallString "abc"; CallOptString (Some "def");
10943                 CallStringList ["1"]; CallBool false;
10944                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10945   call "test0" [CallString "abc"; CallOptString (Some "def");
10946                 CallStringList ["1"]; CallBool false;
10947                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10948   call "test0" [CallString "abc"; CallOptString (Some "def");
10949                 CallStringList ["1"]; CallBool false;
10950                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10951   call "test0" [CallString "abc"; CallOptString (Some "def");
10952                 CallStringList ["1"]; CallBool false;
10953                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10954   call "test0" [CallString "abc"; CallOptString (Some "def");
10955                 CallStringList ["1"]; CallBool false;
10956                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10957
10958 (* XXX Add here tests of the return and error functions. *)
10959
10960 (* Code to generator bindings for virt-inspector.  Currently only
10961  * implemented for OCaml code (for virt-p2v 2.0).
10962  *)
10963 let rng_input = "inspector/virt-inspector.rng"
10964
10965 (* Read the input file and parse it into internal structures.  This is
10966  * by no means a complete RELAX NG parser, but is just enough to be
10967  * able to parse the specific input file.
10968  *)
10969 type rng =
10970   | Element of string * rng list        (* <element name=name/> *)
10971   | Attribute of string * rng list        (* <attribute name=name/> *)
10972   | Interleave of rng list                (* <interleave/> *)
10973   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10974   | OneOrMore of rng                        (* <oneOrMore/> *)
10975   | Optional of rng                        (* <optional/> *)
10976   | Choice of string list                (* <choice><value/>*</choice> *)
10977   | Value of string                        (* <value>str</value> *)
10978   | Text                                (* <text/> *)
10979
10980 let rec string_of_rng = function
10981   | Element (name, xs) ->
10982       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10983   | Attribute (name, xs) ->
10984       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10985   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10986   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10987   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10988   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10989   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10990   | Value value -> "Value \"" ^ value ^ "\""
10991   | Text -> "Text"
10992
10993 and string_of_rng_list xs =
10994   String.concat ", " (List.map string_of_rng xs)
10995
10996 let rec parse_rng ?defines context = function
10997   | [] -> []
10998   | Xml.Element ("element", ["name", name], children) :: rest ->
10999       Element (name, parse_rng ?defines context children)
11000       :: parse_rng ?defines context rest
11001   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11002       Attribute (name, parse_rng ?defines context children)
11003       :: parse_rng ?defines context rest
11004   | Xml.Element ("interleave", [], children) :: rest ->
11005       Interleave (parse_rng ?defines context children)
11006       :: parse_rng ?defines context rest
11007   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11008       let rng = parse_rng ?defines context [child] in
11009       (match rng with
11010        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11011        | _ ->
11012            failwithf "%s: <zeroOrMore> contains more than one child element"
11013              context
11014       )
11015   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11016       let rng = parse_rng ?defines context [child] in
11017       (match rng with
11018        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11019        | _ ->
11020            failwithf "%s: <oneOrMore> contains more than one child element"
11021              context
11022       )
11023   | Xml.Element ("optional", [], [child]) :: rest ->
11024       let rng = parse_rng ?defines context [child] in
11025       (match rng with
11026        | [child] -> Optional child :: parse_rng ?defines context rest
11027        | _ ->
11028            failwithf "%s: <optional> contains more than one child element"
11029              context
11030       )
11031   | Xml.Element ("choice", [], children) :: rest ->
11032       let values = List.map (
11033         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11034         | _ ->
11035             failwithf "%s: can't handle anything except <value> in <choice>"
11036               context
11037       ) children in
11038       Choice values
11039       :: parse_rng ?defines context rest
11040   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11041       Value value :: parse_rng ?defines context rest
11042   | Xml.Element ("text", [], []) :: rest ->
11043       Text :: parse_rng ?defines context rest
11044   | Xml.Element ("ref", ["name", name], []) :: rest ->
11045       (* Look up the reference.  Because of limitations in this parser,
11046        * we can't handle arbitrarily nested <ref> yet.  You can only
11047        * use <ref> from inside <start>.
11048        *)
11049       (match defines with
11050        | None ->
11051            failwithf "%s: contains <ref>, but no refs are defined yet" context
11052        | Some map ->
11053            let rng = StringMap.find name map in
11054            rng @ parse_rng ?defines context rest
11055       )
11056   | x :: _ ->
11057       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11058
11059 let grammar =
11060   let xml = Xml.parse_file rng_input in
11061   match xml with
11062   | Xml.Element ("grammar", _,
11063                  Xml.Element ("start", _, gram) :: defines) ->
11064       (* The <define/> elements are referenced in the <start> section,
11065        * so build a map of those first.
11066        *)
11067       let defines = List.fold_left (
11068         fun map ->
11069           function Xml.Element ("define", ["name", name], defn) ->
11070             StringMap.add name defn map
11071           | _ ->
11072               failwithf "%s: expected <define name=name/>" rng_input
11073       ) StringMap.empty defines in
11074       let defines = StringMap.mapi parse_rng defines in
11075
11076       (* Parse the <start> clause, passing the defines. *)
11077       parse_rng ~defines "<start>" gram
11078   | _ ->
11079       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11080         rng_input
11081
11082 let name_of_field = function
11083   | Element (name, _) | Attribute (name, _)
11084   | ZeroOrMore (Element (name, _))
11085   | OneOrMore (Element (name, _))
11086   | Optional (Element (name, _)) -> name
11087   | Optional (Attribute (name, _)) -> name
11088   | Text -> (* an unnamed field in an element *)
11089       "data"
11090   | rng ->
11091       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11092
11093 (* At the moment this function only generates OCaml types.  However we
11094  * should parameterize it later so it can generate types/structs in a
11095  * variety of languages.
11096  *)
11097 let generate_types xs =
11098   (* A simple type is one that can be printed out directly, eg.
11099    * "string option".  A complex type is one which has a name and has
11100    * to be defined via another toplevel definition, eg. a struct.
11101    *
11102    * generate_type generates code for either simple or complex types.
11103    * In the simple case, it returns the string ("string option").  In
11104    * the complex case, it returns the name ("mountpoint").  In the
11105    * complex case it has to print out the definition before returning,
11106    * so it should only be called when we are at the beginning of a
11107    * new line (BOL context).
11108    *)
11109   let rec generate_type = function
11110     | Text ->                                (* string *)
11111         "string", true
11112     | Choice values ->                        (* [`val1|`val2|...] *)
11113         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11114     | ZeroOrMore rng ->                        (* <rng> list *)
11115         let t, is_simple = generate_type rng in
11116         t ^ " list (* 0 or more *)", is_simple
11117     | OneOrMore rng ->                        (* <rng> list *)
11118         let t, is_simple = generate_type rng in
11119         t ^ " list (* 1 or more *)", is_simple
11120                                         (* virt-inspector hack: bool *)
11121     | Optional (Attribute (name, [Value "1"])) ->
11122         "bool", true
11123     | Optional rng ->                        (* <rng> list *)
11124         let t, is_simple = generate_type rng in
11125         t ^ " option", is_simple
11126                                         (* type name = { fields ... } *)
11127     | Element (name, fields) when is_attrs_interleave fields ->
11128         generate_type_struct name (get_attrs_interleave fields)
11129     | Element (name, [field])                (* type name = field *)
11130     | Attribute (name, [field]) ->
11131         let t, is_simple = generate_type field in
11132         if is_simple then (t, true)
11133         else (
11134           pr "type %s = %s\n" name t;
11135           name, false
11136         )
11137     | Element (name, fields) ->              (* type name = { fields ... } *)
11138         generate_type_struct name fields
11139     | rng ->
11140         failwithf "generate_type failed at: %s" (string_of_rng rng)
11141
11142   and is_attrs_interleave = function
11143     | [Interleave _] -> true
11144     | Attribute _ :: fields -> is_attrs_interleave fields
11145     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11146     | _ -> false
11147
11148   and get_attrs_interleave = function
11149     | [Interleave fields] -> fields
11150     | ((Attribute _) as field) :: fields
11151     | ((Optional (Attribute _)) as field) :: fields ->
11152         field :: get_attrs_interleave fields
11153     | _ -> assert false
11154
11155   and generate_types xs =
11156     List.iter (fun x -> ignore (generate_type x)) xs
11157
11158   and generate_type_struct name fields =
11159     (* Calculate the types of the fields first.  We have to do this
11160      * before printing anything so we are still in BOL context.
11161      *)
11162     let types = List.map fst (List.map generate_type fields) in
11163
11164     (* Special case of a struct containing just a string and another
11165      * field.  Turn it into an assoc list.
11166      *)
11167     match types with
11168     | ["string"; other] ->
11169         let fname1, fname2 =
11170           match fields with
11171           | [f1; f2] -> name_of_field f1, name_of_field f2
11172           | _ -> assert false in
11173         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11174         name, false
11175
11176     | types ->
11177         pr "type %s = {\n" name;
11178         List.iter (
11179           fun (field, ftype) ->
11180             let fname = name_of_field field in
11181             pr "  %s_%s : %s;\n" name fname ftype
11182         ) (List.combine fields types);
11183         pr "}\n";
11184         (* Return the name of this type, and
11185          * false because it's not a simple type.
11186          *)
11187         name, false
11188   in
11189
11190   generate_types xs
11191
11192 let generate_parsers xs =
11193   (* As for generate_type above, generate_parser makes a parser for
11194    * some type, and returns the name of the parser it has generated.
11195    * Because it (may) need to print something, it should always be
11196    * called in BOL context.
11197    *)
11198   let rec generate_parser = function
11199     | Text ->                                (* string *)
11200         "string_child_or_empty"
11201     | Choice values ->                        (* [`val1|`val2|...] *)
11202         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11203           (String.concat "|"
11204              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11205     | ZeroOrMore rng ->                        (* <rng> list *)
11206         let pa = generate_parser rng in
11207         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11208     | OneOrMore rng ->                        (* <rng> list *)
11209         let pa = generate_parser rng in
11210         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11211                                         (* virt-inspector hack: bool *)
11212     | Optional (Attribute (name, [Value "1"])) ->
11213         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11214     | Optional rng ->                        (* <rng> list *)
11215         let pa = generate_parser rng in
11216         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11217                                         (* type name = { fields ... } *)
11218     | Element (name, fields) when is_attrs_interleave fields ->
11219         generate_parser_struct name (get_attrs_interleave fields)
11220     | Element (name, [field]) ->        (* type name = field *)
11221         let pa = generate_parser field in
11222         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11223         pr "let %s =\n" parser_name;
11224         pr "  %s\n" pa;
11225         pr "let parse_%s = %s\n" name parser_name;
11226         parser_name
11227     | Attribute (name, [field]) ->
11228         let pa = generate_parser field in
11229         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11230         pr "let %s =\n" parser_name;
11231         pr "  %s\n" pa;
11232         pr "let parse_%s = %s\n" name parser_name;
11233         parser_name
11234     | Element (name, fields) ->              (* type name = { fields ... } *)
11235         generate_parser_struct name ([], fields)
11236     | rng ->
11237         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11238
11239   and is_attrs_interleave = function
11240     | [Interleave _] -> true
11241     | Attribute _ :: fields -> is_attrs_interleave fields
11242     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11243     | _ -> false
11244
11245   and get_attrs_interleave = function
11246     | [Interleave fields] -> [], fields
11247     | ((Attribute _) as field) :: fields
11248     | ((Optional (Attribute _)) as field) :: fields ->
11249         let attrs, interleaves = get_attrs_interleave fields in
11250         (field :: attrs), interleaves
11251     | _ -> assert false
11252
11253   and generate_parsers xs =
11254     List.iter (fun x -> ignore (generate_parser x)) xs
11255
11256   and generate_parser_struct name (attrs, interleaves) =
11257     (* Generate parsers for the fields first.  We have to do this
11258      * before printing anything so we are still in BOL context.
11259      *)
11260     let fields = attrs @ interleaves in
11261     let pas = List.map generate_parser fields in
11262
11263     (* Generate an intermediate tuple from all the fields first.
11264      * If the type is just a string + another field, then we will
11265      * return this directly, otherwise it is turned into a record.
11266      *
11267      * RELAX NG note: This code treats <interleave> and plain lists of
11268      * fields the same.  In other words, it doesn't bother enforcing
11269      * any ordering of fields in the XML.
11270      *)
11271     pr "let parse_%s x =\n" name;
11272     pr "  let t = (\n    ";
11273     let comma = ref false in
11274     List.iter (
11275       fun x ->
11276         if !comma then pr ",\n    ";
11277         comma := true;
11278         match x with
11279         | Optional (Attribute (fname, [field])), pa ->
11280             pr "%s x" pa
11281         | Optional (Element (fname, [field])), pa ->
11282             pr "%s (optional_child %S x)" pa fname
11283         | Attribute (fname, [Text]), _ ->
11284             pr "attribute %S x" fname
11285         | (ZeroOrMore _ | OneOrMore _), pa ->
11286             pr "%s x" pa
11287         | Text, pa ->
11288             pr "%s x" pa
11289         | (field, pa) ->
11290             let fname = name_of_field field in
11291             pr "%s (child %S x)" pa fname
11292     ) (List.combine fields pas);
11293     pr "\n  ) in\n";
11294
11295     (match fields with
11296      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11297          pr "  t\n"
11298
11299      | _ ->
11300          pr "  (Obj.magic t : %s)\n" name
11301 (*
11302          List.iter (
11303            function
11304            | (Optional (Attribute (fname, [field])), pa) ->
11305                pr "  %s_%s =\n" name fname;
11306                pr "    %s x;\n" pa
11307            | (Optional (Element (fname, [field])), pa) ->
11308                pr "  %s_%s =\n" name fname;
11309                pr "    (let x = optional_child %S x in\n" fname;
11310                pr "     %s x);\n" pa
11311            | (field, pa) ->
11312                let fname = name_of_field field in
11313                pr "  %s_%s =\n" name fname;
11314                pr "    (let x = child %S x in\n" fname;
11315                pr "     %s x);\n" pa
11316          ) (List.combine fields pas);
11317          pr "}\n"
11318 *)
11319     );
11320     sprintf "parse_%s" name
11321   in
11322
11323   generate_parsers xs
11324
11325 (* Generate ocaml/guestfs_inspector.mli. *)
11326 let generate_ocaml_inspector_mli () =
11327   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11328
11329   pr "\
11330 (** This is an OCaml language binding to the external [virt-inspector]
11331     program.
11332
11333     For more information, please read the man page [virt-inspector(1)].
11334 *)
11335
11336 ";
11337
11338   generate_types grammar;
11339   pr "(** The nested information returned from the {!inspect} function. *)\n";
11340   pr "\n";
11341
11342   pr "\
11343 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11344 (** To inspect a libvirt domain called [name], pass a singleton
11345     list: [inspect [name]].  When using libvirt only, you may
11346     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11347
11348     To inspect a disk image or images, pass a list of the filenames
11349     of the disk images: [inspect filenames]
11350
11351     This function inspects the given guest or disk images and
11352     returns a list of operating system(s) found and a large amount
11353     of information about them.  In the vast majority of cases,
11354     a virtual machine only contains a single operating system.
11355
11356     If the optional [~xml] parameter is given, then this function
11357     skips running the external virt-inspector program and just
11358     parses the given XML directly (which is expected to be XML
11359     produced from a previous run of virt-inspector).  The list of
11360     names and connect URI are ignored in this case.
11361
11362     This function can throw a wide variety of exceptions, for example
11363     if the external virt-inspector program cannot be found, or if
11364     it doesn't generate valid XML.
11365 *)
11366 "
11367
11368 (* Generate ocaml/guestfs_inspector.ml. *)
11369 let generate_ocaml_inspector_ml () =
11370   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11371
11372   pr "open Unix\n";
11373   pr "\n";
11374
11375   generate_types grammar;
11376   pr "\n";
11377
11378   pr "\
11379 (* Misc functions which are used by the parser code below. *)
11380 let first_child = function
11381   | Xml.Element (_, _, c::_) -> c
11382   | Xml.Element (name, _, []) ->
11383       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11384   | Xml.PCData str ->
11385       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11386
11387 let string_child_or_empty = function
11388   | Xml.Element (_, _, [Xml.PCData s]) -> s
11389   | Xml.Element (_, _, []) -> \"\"
11390   | Xml.Element (x, _, _) ->
11391       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11392                 x ^ \" instead\")
11393   | Xml.PCData str ->
11394       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11395
11396 let optional_child name xml =
11397   let children = Xml.children xml in
11398   try
11399     Some (List.find (function
11400                      | Xml.Element (n, _, _) when n = name -> true
11401                      | _ -> false) children)
11402   with
11403     Not_found -> None
11404
11405 let child name xml =
11406   match optional_child name xml with
11407   | Some c -> c
11408   | None ->
11409       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11410
11411 let attribute name xml =
11412   try Xml.attrib xml name
11413   with Xml.No_attribute _ ->
11414     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11415
11416 ";
11417
11418   generate_parsers grammar;
11419   pr "\n";
11420
11421   pr "\
11422 (* Run external virt-inspector, then use parser to parse the XML. *)
11423 let inspect ?connect ?xml names =
11424   let xml =
11425     match xml with
11426     | None ->
11427         if names = [] then invalid_arg \"inspect: no names given\";
11428         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11429           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11430           names in
11431         let cmd = List.map Filename.quote cmd in
11432         let cmd = String.concat \" \" cmd in
11433         let chan = open_process_in cmd in
11434         let xml = Xml.parse_in chan in
11435         (match close_process_in chan with
11436          | WEXITED 0 -> ()
11437          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11438          | WSIGNALED i | WSTOPPED i ->
11439              failwith (\"external virt-inspector command died or stopped on sig \" ^
11440                        string_of_int i)
11441         );
11442         xml
11443     | Some doc ->
11444         Xml.parse_string doc in
11445   parse_operatingsystems xml
11446 "
11447
11448 (* This is used to generate the src/MAX_PROC_NR file which
11449  * contains the maximum procedure number, a surrogate for the
11450  * ABI version number.  See src/Makefile.am for the details.
11451  *)
11452 and generate_max_proc_nr () =
11453   let proc_nrs = List.map (
11454     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11455   ) daemon_functions in
11456
11457   let max_proc_nr = List.fold_left max 0 proc_nrs in
11458
11459   pr "%d\n" max_proc_nr
11460
11461 let output_to filename k =
11462   let filename_new = filename ^ ".new" in
11463   chan := open_out filename_new;
11464   k ();
11465   close_out !chan;
11466   chan := Pervasives.stdout;
11467
11468   (* Is the new file different from the current file? *)
11469   if Sys.file_exists filename && files_equal filename filename_new then
11470     unlink filename_new                 (* same, so skip it *)
11471   else (
11472     (* different, overwrite old one *)
11473     (try chmod filename 0o644 with Unix_error _ -> ());
11474     rename filename_new filename;
11475     chmod filename 0o444;
11476     printf "written %s\n%!" filename;
11477   )
11478
11479 let perror msg = function
11480   | Unix_error (err, _, _) ->
11481       eprintf "%s: %s\n" msg (error_message err)
11482   | exn ->
11483       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11484
11485 (* Main program. *)
11486 let () =
11487   let lock_fd =
11488     try openfile "HACKING" [O_RDWR] 0
11489     with
11490     | Unix_error (ENOENT, _, _) ->
11491         eprintf "\
11492 You are probably running this from the wrong directory.
11493 Run it from the top source directory using the command
11494   src/generator.ml
11495 ";
11496         exit 1
11497     | exn ->
11498         perror "open: HACKING" exn;
11499         exit 1 in
11500
11501   (* Acquire a lock so parallel builds won't try to run the generator
11502    * twice at the same time.  Subsequent builds will wait for the first
11503    * one to finish.  Note the lock is released implicitly when the
11504    * program exits.
11505    *)
11506   (try lockf lock_fd F_LOCK 1
11507    with exn ->
11508      perror "lock: HACKING" exn;
11509      exit 1);
11510
11511   check_functions ();
11512
11513   output_to "src/guestfs_protocol.x" generate_xdr;
11514   output_to "src/guestfs-structs.h" generate_structs_h;
11515   output_to "src/guestfs-actions.h" generate_actions_h;
11516   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11517   output_to "src/guestfs-actions.c" generate_client_actions;
11518   output_to "src/guestfs-bindtests.c" generate_bindtests;
11519   output_to "src/guestfs-structs.pod" generate_structs_pod;
11520   output_to "src/guestfs-actions.pod" generate_actions_pod;
11521   output_to "src/guestfs-availability.pod" generate_availability_pod;
11522   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11523   output_to "src/libguestfs.syms" generate_linker_script;
11524   output_to "daemon/actions.h" generate_daemon_actions_h;
11525   output_to "daemon/stubs.c" generate_daemon_actions;
11526   output_to "daemon/names.c" generate_daemon_names;
11527   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11528   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11529   output_to "capitests/tests.c" generate_tests;
11530   output_to "fish/cmds.c" generate_fish_cmds;
11531   output_to "fish/completion.c" generate_fish_completion;
11532   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11533   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11534   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11535   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11536   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11537   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11538   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11539   output_to "perl/Guestfs.xs" generate_perl_xs;
11540   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11541   output_to "perl/bindtests.pl" generate_perl_bindtests;
11542   output_to "python/guestfs-py.c" generate_python_c;
11543   output_to "python/guestfs.py" generate_python_py;
11544   output_to "python/bindtests.py" generate_python_bindtests;
11545   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11546   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11547   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11548
11549   List.iter (
11550     fun (typ, jtyp) ->
11551       let cols = cols_of_struct typ in
11552       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11553       output_to filename (generate_java_struct jtyp cols);
11554   ) java_structs;
11555
11556   output_to "java/Makefile.inc" generate_java_makefile_inc;
11557   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11558   output_to "java/Bindtests.java" generate_java_bindtests;
11559   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11560   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11561   output_to "csharp/Libguestfs.cs" generate_csharp;
11562
11563   (* Always generate this file last, and unconditionally.  It's used
11564    * by the Makefile to know when we must re-run the generator.
11565    *)
11566   let chan = open_out "src/stamp-generator" in
11567   fprintf chan "1\n";
11568   close_out chan;
11569
11570   printf "generated %d lines of code\n" !lines