50ae91d07d4592b362f54d01cb4806b203ed24ea
[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 ]
4447
4448 let all_functions = non_daemon_functions @ daemon_functions
4449
4450 (* In some places we want the functions to be displayed sorted
4451  * alphabetically, so this is useful:
4452  *)
4453 let all_functions_sorted =
4454   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4455                compare n1 n2) all_functions
4456
4457 (* Field types for structures. *)
4458 type field =
4459   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4460   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4461   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4462   | FUInt32
4463   | FInt32
4464   | FUInt64
4465   | FInt64
4466   | FBytes                      (* Any int measure that counts bytes. *)
4467   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4468   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4469
4470 (* Because we generate extra parsing code for LVM command line tools,
4471  * we have to pull out the LVM columns separately here.
4472  *)
4473 let lvm_pv_cols = [
4474   "pv_name", FString;
4475   "pv_uuid", FUUID;
4476   "pv_fmt", FString;
4477   "pv_size", FBytes;
4478   "dev_size", FBytes;
4479   "pv_free", FBytes;
4480   "pv_used", FBytes;
4481   "pv_attr", FString (* XXX *);
4482   "pv_pe_count", FInt64;
4483   "pv_pe_alloc_count", FInt64;
4484   "pv_tags", FString;
4485   "pe_start", FBytes;
4486   "pv_mda_count", FInt64;
4487   "pv_mda_free", FBytes;
4488   (* Not in Fedora 10:
4489      "pv_mda_size", FBytes;
4490   *)
4491 ]
4492 let lvm_vg_cols = [
4493   "vg_name", FString;
4494   "vg_uuid", FUUID;
4495   "vg_fmt", FString;
4496   "vg_attr", FString (* XXX *);
4497   "vg_size", FBytes;
4498   "vg_free", FBytes;
4499   "vg_sysid", FString;
4500   "vg_extent_size", FBytes;
4501   "vg_extent_count", FInt64;
4502   "vg_free_count", FInt64;
4503   "max_lv", FInt64;
4504   "max_pv", FInt64;
4505   "pv_count", FInt64;
4506   "lv_count", FInt64;
4507   "snap_count", FInt64;
4508   "vg_seqno", FInt64;
4509   "vg_tags", FString;
4510   "vg_mda_count", FInt64;
4511   "vg_mda_free", FBytes;
4512   (* Not in Fedora 10:
4513      "vg_mda_size", FBytes;
4514   *)
4515 ]
4516 let lvm_lv_cols = [
4517   "lv_name", FString;
4518   "lv_uuid", FUUID;
4519   "lv_attr", FString (* XXX *);
4520   "lv_major", FInt64;
4521   "lv_minor", FInt64;
4522   "lv_kernel_major", FInt64;
4523   "lv_kernel_minor", FInt64;
4524   "lv_size", FBytes;
4525   "seg_count", FInt64;
4526   "origin", FString;
4527   "snap_percent", FOptPercent;
4528   "copy_percent", FOptPercent;
4529   "move_pv", FString;
4530   "lv_tags", FString;
4531   "mirror_log", FString;
4532   "modules", FString;
4533 ]
4534
4535 (* Names and fields in all structures (in RStruct and RStructList)
4536  * that we support.
4537  *)
4538 let structs = [
4539   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4540    * not use this struct in any new code.
4541    *)
4542   "int_bool", [
4543     "i", FInt32;                (* for historical compatibility *)
4544     "b", FInt32;                (* for historical compatibility *)
4545   ];
4546
4547   (* LVM PVs, VGs, LVs. *)
4548   "lvm_pv", lvm_pv_cols;
4549   "lvm_vg", lvm_vg_cols;
4550   "lvm_lv", lvm_lv_cols;
4551
4552   (* Column names and types from stat structures.
4553    * NB. Can't use things like 'st_atime' because glibc header files
4554    * define some of these as macros.  Ugh.
4555    *)
4556   "stat", [
4557     "dev", FInt64;
4558     "ino", FInt64;
4559     "mode", FInt64;
4560     "nlink", FInt64;
4561     "uid", FInt64;
4562     "gid", FInt64;
4563     "rdev", FInt64;
4564     "size", FInt64;
4565     "blksize", FInt64;
4566     "blocks", FInt64;
4567     "atime", FInt64;
4568     "mtime", FInt64;
4569     "ctime", FInt64;
4570   ];
4571   "statvfs", [
4572     "bsize", FInt64;
4573     "frsize", FInt64;
4574     "blocks", FInt64;
4575     "bfree", FInt64;
4576     "bavail", FInt64;
4577     "files", FInt64;
4578     "ffree", FInt64;
4579     "favail", FInt64;
4580     "fsid", FInt64;
4581     "flag", FInt64;
4582     "namemax", FInt64;
4583   ];
4584
4585   (* Column names in dirent structure. *)
4586   "dirent", [
4587     "ino", FInt64;
4588     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4589     "ftyp", FChar;
4590     "name", FString;
4591   ];
4592
4593   (* Version numbers. *)
4594   "version", [
4595     "major", FInt64;
4596     "minor", FInt64;
4597     "release", FInt64;
4598     "extra", FString;
4599   ];
4600
4601   (* Extended attribute. *)
4602   "xattr", [
4603     "attrname", FString;
4604     "attrval", FBuffer;
4605   ];
4606
4607   (* Inotify events. *)
4608   "inotify_event", [
4609     "in_wd", FInt64;
4610     "in_mask", FUInt32;
4611     "in_cookie", FUInt32;
4612     "in_name", FString;
4613   ];
4614
4615   (* Partition table entry. *)
4616   "partition", [
4617     "part_num", FInt32;
4618     "part_start", FBytes;
4619     "part_end", FBytes;
4620     "part_size", FBytes;
4621   ];
4622 ] (* end of structs *)
4623
4624 (* Ugh, Java has to be different ..
4625  * These names are also used by the Haskell bindings.
4626  *)
4627 let java_structs = [
4628   "int_bool", "IntBool";
4629   "lvm_pv", "PV";
4630   "lvm_vg", "VG";
4631   "lvm_lv", "LV";
4632   "stat", "Stat";
4633   "statvfs", "StatVFS";
4634   "dirent", "Dirent";
4635   "version", "Version";
4636   "xattr", "XAttr";
4637   "inotify_event", "INotifyEvent";
4638   "partition", "Partition";
4639 ]
4640
4641 (* What structs are actually returned. *)
4642 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4643
4644 (* Returns a list of RStruct/RStructList structs that are returned
4645  * by any function.  Each element of returned list is a pair:
4646  *
4647  * (structname, RStructOnly)
4648  *    == there exists function which returns RStruct (_, structname)
4649  * (structname, RStructListOnly)
4650  *    == there exists function which returns RStructList (_, structname)
4651  * (structname, RStructAndList)
4652  *    == there are functions returning both RStruct (_, structname)
4653  *                                      and RStructList (_, structname)
4654  *)
4655 let rstructs_used_by functions =
4656   (* ||| is a "logical OR" for rstructs_used_t *)
4657   let (|||) a b =
4658     match a, b with
4659     | RStructAndList, _
4660     | _, RStructAndList -> RStructAndList
4661     | RStructOnly, RStructListOnly
4662     | RStructListOnly, RStructOnly -> RStructAndList
4663     | RStructOnly, RStructOnly -> RStructOnly
4664     | RStructListOnly, RStructListOnly -> RStructListOnly
4665   in
4666
4667   let h = Hashtbl.create 13 in
4668
4669   (* if elem->oldv exists, update entry using ||| operator,
4670    * else just add elem->newv to the hash
4671    *)
4672   let update elem newv =
4673     try  let oldv = Hashtbl.find h elem in
4674          Hashtbl.replace h elem (newv ||| oldv)
4675     with Not_found -> Hashtbl.add h elem newv
4676   in
4677
4678   List.iter (
4679     fun (_, style, _, _, _, _, _) ->
4680       match fst style with
4681       | RStruct (_, structname) -> update structname RStructOnly
4682       | RStructList (_, structname) -> update structname RStructListOnly
4683       | _ -> ()
4684   ) functions;
4685
4686   (* return key->values as a list of (key,value) *)
4687   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4688
4689 (* Used for testing language bindings. *)
4690 type callt =
4691   | CallString of string
4692   | CallOptString of string option
4693   | CallStringList of string list
4694   | CallInt of int
4695   | CallInt64 of int64
4696   | CallBool of bool
4697
4698 (* Used to memoize the result of pod2text. *)
4699 let pod2text_memo_filename = "src/.pod2text.data"
4700 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4701   try
4702     let chan = open_in pod2text_memo_filename in
4703     let v = input_value chan in
4704     close_in chan;
4705     v
4706   with
4707     _ -> Hashtbl.create 13
4708 let pod2text_memo_updated () =
4709   let chan = open_out pod2text_memo_filename in
4710   output_value chan pod2text_memo;
4711   close_out chan
4712
4713 (* Useful functions.
4714  * Note we don't want to use any external OCaml libraries which
4715  * makes this a bit harder than it should be.
4716  *)
4717 module StringMap = Map.Make (String)
4718
4719 let failwithf fs = ksprintf failwith fs
4720
4721 let unique = let i = ref 0 in fun () -> incr i; !i
4722
4723 let replace_char s c1 c2 =
4724   let s2 = String.copy s in
4725   let r = ref false in
4726   for i = 0 to String.length s2 - 1 do
4727     if String.unsafe_get s2 i = c1 then (
4728       String.unsafe_set s2 i c2;
4729       r := true
4730     )
4731   done;
4732   if not !r then s else s2
4733
4734 let isspace c =
4735   c = ' '
4736   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4737
4738 let triml ?(test = isspace) str =
4739   let i = ref 0 in
4740   let n = ref (String.length str) in
4741   while !n > 0 && test str.[!i]; do
4742     decr n;
4743     incr i
4744   done;
4745   if !i = 0 then str
4746   else String.sub str !i !n
4747
4748 let trimr ?(test = isspace) str =
4749   let n = ref (String.length str) in
4750   while !n > 0 && test str.[!n-1]; do
4751     decr n
4752   done;
4753   if !n = String.length str then str
4754   else String.sub str 0 !n
4755
4756 let trim ?(test = isspace) str =
4757   trimr ~test (triml ~test str)
4758
4759 let rec find s sub =
4760   let len = String.length s in
4761   let sublen = String.length sub in
4762   let rec loop i =
4763     if i <= len-sublen then (
4764       let rec loop2 j =
4765         if j < sublen then (
4766           if s.[i+j] = sub.[j] then loop2 (j+1)
4767           else -1
4768         ) else
4769           i (* found *)
4770       in
4771       let r = loop2 0 in
4772       if r = -1 then loop (i+1) else r
4773     ) else
4774       -1 (* not found *)
4775   in
4776   loop 0
4777
4778 let rec replace_str s s1 s2 =
4779   let len = String.length s in
4780   let sublen = String.length s1 in
4781   let i = find s s1 in
4782   if i = -1 then s
4783   else (
4784     let s' = String.sub s 0 i in
4785     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4786     s' ^ s2 ^ replace_str s'' s1 s2
4787   )
4788
4789 let rec string_split sep str =
4790   let len = String.length str in
4791   let seplen = String.length sep in
4792   let i = find str sep in
4793   if i = -1 then [str]
4794   else (
4795     let s' = String.sub str 0 i in
4796     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4797     s' :: string_split sep s''
4798   )
4799
4800 let files_equal n1 n2 =
4801   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4802   match Sys.command cmd with
4803   | 0 -> true
4804   | 1 -> false
4805   | i -> failwithf "%s: failed with error code %d" cmd i
4806
4807 let rec filter_map f = function
4808   | [] -> []
4809   | x :: xs ->
4810       match f x with
4811       | Some y -> y :: filter_map f xs
4812       | None -> filter_map f xs
4813
4814 let rec find_map f = function
4815   | [] -> raise Not_found
4816   | x :: xs ->
4817       match f x with
4818       | Some y -> y
4819       | None -> find_map f xs
4820
4821 let iteri f xs =
4822   let rec loop i = function
4823     | [] -> ()
4824     | x :: xs -> f i x; loop (i+1) xs
4825   in
4826   loop 0 xs
4827
4828 let mapi f xs =
4829   let rec loop i = function
4830     | [] -> []
4831     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4832   in
4833   loop 0 xs
4834
4835 let count_chars c str =
4836   let count = ref 0 in
4837   for i = 0 to String.length str - 1 do
4838     if c = String.unsafe_get str i then incr count
4839   done;
4840   !count
4841
4842 let name_of_argt = function
4843   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4844   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4845   | FileIn n | FileOut n -> n
4846
4847 let java_name_of_struct typ =
4848   try List.assoc typ java_structs
4849   with Not_found ->
4850     failwithf
4851       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4852
4853 let cols_of_struct typ =
4854   try List.assoc typ structs
4855   with Not_found ->
4856     failwithf "cols_of_struct: unknown struct %s" typ
4857
4858 let seq_of_test = function
4859   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4860   | TestOutputListOfDevices (s, _)
4861   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4862   | TestOutputTrue s | TestOutputFalse s
4863   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4864   | TestOutputStruct (s, _)
4865   | TestLastFail s -> s
4866
4867 (* Handling for function flags. *)
4868 let protocol_limit_warning =
4869   "Because of the message protocol, there is a transfer limit
4870 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4871
4872 let danger_will_robinson =
4873   "B<This command is dangerous.  Without careful use you
4874 can easily destroy all your data>."
4875
4876 let deprecation_notice flags =
4877   try
4878     let alt =
4879       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4880     let txt =
4881       sprintf "This function is deprecated.
4882 In new code, use the C<%s> call instead.
4883
4884 Deprecated functions will not be removed from the API, but the
4885 fact that they are deprecated indicates that there are problems
4886 with correct use of these functions." alt in
4887     Some txt
4888   with
4889     Not_found -> None
4890
4891 (* Create list of optional groups. *)
4892 let optgroups =
4893   let h = Hashtbl.create 13 in
4894   List.iter (
4895     fun (name, _, _, flags, _, _, _) ->
4896       List.iter (
4897         function
4898         | Optional group ->
4899             let names = try Hashtbl.find h group with Not_found -> [] in
4900             Hashtbl.replace h group (name :: names)
4901         | _ -> ()
4902       ) flags
4903   ) daemon_functions;
4904   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4905   let groups =
4906     List.map (
4907       fun group -> group, List.sort compare (Hashtbl.find h group)
4908     ) groups in
4909   List.sort (fun x y -> compare (fst x) (fst y)) groups
4910
4911 (* Check function names etc. for consistency. *)
4912 let check_functions () =
4913   let contains_uppercase str =
4914     let len = String.length str in
4915     let rec loop i =
4916       if i >= len then false
4917       else (
4918         let c = str.[i] in
4919         if c >= 'A' && c <= 'Z' then true
4920         else loop (i+1)
4921       )
4922     in
4923     loop 0
4924   in
4925
4926   (* Check function names. *)
4927   List.iter (
4928     fun (name, _, _, _, _, _, _) ->
4929       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4930         failwithf "function name %s does not need 'guestfs' prefix" name;
4931       if name = "" then
4932         failwithf "function name is empty";
4933       if name.[0] < 'a' || name.[0] > 'z' then
4934         failwithf "function name %s must start with lowercase a-z" name;
4935       if String.contains name '-' then
4936         failwithf "function name %s should not contain '-', use '_' instead."
4937           name
4938   ) all_functions;
4939
4940   (* Check function parameter/return names. *)
4941   List.iter (
4942     fun (name, style, _, _, _, _, _) ->
4943       let check_arg_ret_name n =
4944         if contains_uppercase n then
4945           failwithf "%s param/ret %s should not contain uppercase chars"
4946             name n;
4947         if String.contains n '-' || String.contains n '_' then
4948           failwithf "%s param/ret %s should not contain '-' or '_'"
4949             name n;
4950         if n = "value" then
4951           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;
4952         if n = "int" || n = "char" || n = "short" || n = "long" then
4953           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4954         if n = "i" || n = "n" then
4955           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4956         if n = "argv" || n = "args" then
4957           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4958
4959         (* List Haskell, OCaml and C keywords here.
4960          * http://www.haskell.org/haskellwiki/Keywords
4961          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4962          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4963          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4964          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4965          * Omitting _-containing words, since they're handled above.
4966          * Omitting the OCaml reserved word, "val", is ok,
4967          * and saves us from renaming several parameters.
4968          *)
4969         let reserved = [
4970           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4971           "char"; "class"; "const"; "constraint"; "continue"; "data";
4972           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4973           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4974           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4975           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4976           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4977           "interface";
4978           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4979           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4980           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4981           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4982           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4983           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4984           "volatile"; "when"; "where"; "while";
4985           ] in
4986         if List.mem n reserved then
4987           failwithf "%s has param/ret using reserved word %s" name n;
4988       in
4989
4990       (match fst style with
4991        | RErr -> ()
4992        | RInt n | RInt64 n | RBool n
4993        | RConstString n | RConstOptString n | RString n
4994        | RStringList n | RStruct (n, _) | RStructList (n, _)
4995        | RHashtable n | RBufferOut n ->
4996            check_arg_ret_name n
4997       );
4998       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4999   ) all_functions;
5000
5001   (* Check short descriptions. *)
5002   List.iter (
5003     fun (name, _, _, _, _, shortdesc, _) ->
5004       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5005         failwithf "short description of %s should begin with lowercase." name;
5006       let c = shortdesc.[String.length shortdesc-1] in
5007       if c = '\n' || c = '.' then
5008         failwithf "short description of %s should not end with . or \\n." name
5009   ) all_functions;
5010
5011   (* Check long dscriptions. *)
5012   List.iter (
5013     fun (name, _, _, _, _, _, longdesc) ->
5014       if longdesc.[String.length longdesc-1] = '\n' then
5015         failwithf "long description of %s should not end with \\n." name
5016   ) all_functions;
5017
5018   (* Check proc_nrs. *)
5019   List.iter (
5020     fun (name, _, proc_nr, _, _, _, _) ->
5021       if proc_nr <= 0 then
5022         failwithf "daemon function %s should have proc_nr > 0" name
5023   ) daemon_functions;
5024
5025   List.iter (
5026     fun (name, _, proc_nr, _, _, _, _) ->
5027       if proc_nr <> -1 then
5028         failwithf "non-daemon function %s should have proc_nr -1" name
5029   ) non_daemon_functions;
5030
5031   let proc_nrs =
5032     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5033       daemon_functions in
5034   let proc_nrs =
5035     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5036   let rec loop = function
5037     | [] -> ()
5038     | [_] -> ()
5039     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5040         loop rest
5041     | (name1,nr1) :: (name2,nr2) :: _ ->
5042         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5043           name1 name2 nr1 nr2
5044   in
5045   loop proc_nrs;
5046
5047   (* Check tests. *)
5048   List.iter (
5049     function
5050       (* Ignore functions that have no tests.  We generate a
5051        * warning when the user does 'make check' instead.
5052        *)
5053     | name, _, _, _, [], _, _ -> ()
5054     | name, _, _, _, tests, _, _ ->
5055         let funcs =
5056           List.map (
5057             fun (_, _, test) ->
5058               match seq_of_test test with
5059               | [] ->
5060                   failwithf "%s has a test containing an empty sequence" name
5061               | cmds -> List.map List.hd cmds
5062           ) tests in
5063         let funcs = List.flatten funcs in
5064
5065         let tested = List.mem name funcs in
5066
5067         if not tested then
5068           failwithf "function %s has tests but does not test itself" name
5069   ) all_functions
5070
5071 (* 'pr' prints to the current output file. *)
5072 let chan = ref Pervasives.stdout
5073 let lines = ref 0
5074 let pr fs =
5075   ksprintf
5076     (fun str ->
5077        let i = count_chars '\n' str in
5078        lines := !lines + i;
5079        output_string !chan str
5080     ) fs
5081
5082 let copyright_years =
5083   let this_year = 1900 + (localtime (time ())).tm_year in
5084   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5085
5086 (* Generate a header block in a number of standard styles. *)
5087 type comment_style =
5088     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5089 type license = GPLv2plus | LGPLv2plus
5090
5091 let generate_header ?(extra_inputs = []) comment license =
5092   let inputs = "src/generator.ml" :: extra_inputs in
5093   let c = match comment with
5094     | CStyle ->         pr "/* "; " *"
5095     | CPlusPlusStyle -> pr "// "; "//"
5096     | HashStyle ->      pr "# ";  "#"
5097     | OCamlStyle ->     pr "(* "; " *"
5098     | HaskellStyle ->   pr "{- "; "  " in
5099   pr "libguestfs generated file\n";
5100   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5101   List.iter (pr "%s   %s\n" c) inputs;
5102   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5103   pr "%s\n" c;
5104   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5105   pr "%s\n" c;
5106   (match license with
5107    | GPLv2plus ->
5108        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5109        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5110        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5111        pr "%s (at your option) any later version.\n" c;
5112        pr "%s\n" c;
5113        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5114        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5115        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5116        pr "%s GNU General Public License for more details.\n" c;
5117        pr "%s\n" c;
5118        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5119        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5120        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5121
5122    | LGPLv2plus ->
5123        pr "%s This library is free software; you can redistribute it and/or\n" c;
5124        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5125        pr "%s License as published by the Free Software Foundation; either\n" c;
5126        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5127        pr "%s\n" c;
5128        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5129        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5130        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5131        pr "%s Lesser General Public License for more details.\n" c;
5132        pr "%s\n" c;
5133        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5134        pr "%s License along with this library; if not, write to the Free Software\n" c;
5135        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5136   );
5137   (match comment with
5138    | CStyle -> pr " */\n"
5139    | CPlusPlusStyle
5140    | HashStyle -> ()
5141    | OCamlStyle -> pr " *)\n"
5142    | HaskellStyle -> pr "-}\n"
5143   );
5144   pr "\n"
5145
5146 (* Start of main code generation functions below this line. *)
5147
5148 (* Generate the pod documentation for the C API. *)
5149 let rec generate_actions_pod () =
5150   List.iter (
5151     fun (shortname, style, _, flags, _, _, longdesc) ->
5152       if not (List.mem NotInDocs flags) then (
5153         let name = "guestfs_" ^ shortname in
5154         pr "=head2 %s\n\n" name;
5155         pr " ";
5156         generate_prototype ~extern:false ~handle:"handle" name style;
5157         pr "\n\n";
5158         pr "%s\n\n" longdesc;
5159         (match fst style with
5160          | RErr ->
5161              pr "This function returns 0 on success or -1 on error.\n\n"
5162          | RInt _ ->
5163              pr "On error this function returns -1.\n\n"
5164          | RInt64 _ ->
5165              pr "On error this function returns -1.\n\n"
5166          | RBool _ ->
5167              pr "This function returns a C truth value on success or -1 on error.\n\n"
5168          | RConstString _ ->
5169              pr "This function returns a string, or NULL on error.
5170 The string is owned by the guest handle and must I<not> be freed.\n\n"
5171          | RConstOptString _ ->
5172              pr "This function returns a string which may be NULL.
5173 There is way to return an error from this function.
5174 The string is owned by the guest handle and must I<not> be freed.\n\n"
5175          | RString _ ->
5176              pr "This function returns a string, or NULL on error.
5177 I<The caller must free the returned string after use>.\n\n"
5178          | RStringList _ ->
5179              pr "This function returns a NULL-terminated array of strings
5180 (like L<environ(3)>), or NULL if there was an error.
5181 I<The caller must free the strings and the array after use>.\n\n"
5182          | RStruct (_, typ) ->
5183              pr "This function returns a C<struct guestfs_%s *>,
5184 or NULL if there was an error.
5185 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5186          | RStructList (_, typ) ->
5187              pr "This function returns a C<struct guestfs_%s_list *>
5188 (see E<lt>guestfs-structs.hE<gt>),
5189 or NULL if there was an error.
5190 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5191          | RHashtable _ ->
5192              pr "This function returns a NULL-terminated array of
5193 strings, or NULL if there was an error.
5194 The array of strings will always have length C<2n+1>, where
5195 C<n> keys and values alternate, followed by the trailing NULL entry.
5196 I<The caller must free the strings and the array after use>.\n\n"
5197          | RBufferOut _ ->
5198              pr "This function returns a buffer, or NULL on error.
5199 The size of the returned buffer is written to C<*size_r>.
5200 I<The caller must free the returned buffer after use>.\n\n"
5201         );
5202         if List.mem ProtocolLimitWarning flags then
5203           pr "%s\n\n" protocol_limit_warning;
5204         if List.mem DangerWillRobinson flags then
5205           pr "%s\n\n" danger_will_robinson;
5206         match deprecation_notice flags with
5207         | None -> ()
5208         | Some txt -> pr "%s\n\n" txt
5209       )
5210   ) all_functions_sorted
5211
5212 and generate_structs_pod () =
5213   (* Structs documentation. *)
5214   List.iter (
5215     fun (typ, cols) ->
5216       pr "=head2 guestfs_%s\n" typ;
5217       pr "\n";
5218       pr " struct guestfs_%s {\n" typ;
5219       List.iter (
5220         function
5221         | name, FChar -> pr "   char %s;\n" name
5222         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5223         | name, FInt32 -> pr "   int32_t %s;\n" name
5224         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5225         | name, FInt64 -> pr "   int64_t %s;\n" name
5226         | name, FString -> pr "   char *%s;\n" name
5227         | name, FBuffer ->
5228             pr "   /* The next two fields describe a byte array. */\n";
5229             pr "   uint32_t %s_len;\n" name;
5230             pr "   char *%s;\n" name
5231         | name, FUUID ->
5232             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5233             pr "   char %s[32];\n" name
5234         | name, FOptPercent ->
5235             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5236             pr "   float %s;\n" name
5237       ) cols;
5238       pr " };\n";
5239       pr " \n";
5240       pr " struct guestfs_%s_list {\n" typ;
5241       pr "   uint32_t len; /* Number of elements in list. */\n";
5242       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5243       pr " };\n";
5244       pr " \n";
5245       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5246       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5247         typ typ;
5248       pr "\n"
5249   ) structs
5250
5251 and generate_availability_pod () =
5252   (* Availability documentation. *)
5253   pr "=over 4\n";
5254   pr "\n";
5255   List.iter (
5256     fun (group, functions) ->
5257       pr "=item B<%s>\n" group;
5258       pr "\n";
5259       pr "The following functions:\n";
5260       List.iter (pr "L</guestfs_%s>\n") functions;
5261       pr "\n"
5262   ) optgroups;
5263   pr "=back\n";
5264   pr "\n"
5265
5266 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5267  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5268  *
5269  * We have to use an underscore instead of a dash because otherwise
5270  * rpcgen generates incorrect code.
5271  *
5272  * This header is NOT exported to clients, but see also generate_structs_h.
5273  *)
5274 and generate_xdr () =
5275   generate_header CStyle LGPLv2plus;
5276
5277   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5278   pr "typedef string str<>;\n";
5279   pr "\n";
5280
5281   (* Internal structures. *)
5282   List.iter (
5283     function
5284     | typ, cols ->
5285         pr "struct guestfs_int_%s {\n" typ;
5286         List.iter (function
5287                    | name, FChar -> pr "  char %s;\n" name
5288                    | name, FString -> pr "  string %s<>;\n" name
5289                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5290                    | name, FUUID -> pr "  opaque %s[32];\n" name
5291                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5292                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5293                    | name, FOptPercent -> pr "  float %s;\n" name
5294                   ) cols;
5295         pr "};\n";
5296         pr "\n";
5297         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5298         pr "\n";
5299   ) structs;
5300
5301   List.iter (
5302     fun (shortname, style, _, _, _, _, _) ->
5303       let name = "guestfs_" ^ shortname in
5304
5305       (match snd style with
5306        | [] -> ()
5307        | args ->
5308            pr "struct %s_args {\n" name;
5309            List.iter (
5310              function
5311              | Pathname n | Device n | Dev_or_Path n | String n ->
5312                  pr "  string %s<>;\n" n
5313              | OptString n -> pr "  str *%s;\n" n
5314              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5315              | Bool n -> pr "  bool %s;\n" n
5316              | Int n -> pr "  int %s;\n" n
5317              | Int64 n -> pr "  hyper %s;\n" n
5318              | FileIn _ | FileOut _ -> ()
5319            ) args;
5320            pr "};\n\n"
5321       );
5322       (match fst style with
5323        | RErr -> ()
5324        | RInt n ->
5325            pr "struct %s_ret {\n" name;
5326            pr "  int %s;\n" n;
5327            pr "};\n\n"
5328        | RInt64 n ->
5329            pr "struct %s_ret {\n" name;
5330            pr "  hyper %s;\n" n;
5331            pr "};\n\n"
5332        | RBool n ->
5333            pr "struct %s_ret {\n" name;
5334            pr "  bool %s;\n" n;
5335            pr "};\n\n"
5336        | RConstString _ | RConstOptString _ ->
5337            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5338        | RString n ->
5339            pr "struct %s_ret {\n" name;
5340            pr "  string %s<>;\n" n;
5341            pr "};\n\n"
5342        | RStringList n ->
5343            pr "struct %s_ret {\n" name;
5344            pr "  str %s<>;\n" n;
5345            pr "};\n\n"
5346        | RStruct (n, typ) ->
5347            pr "struct %s_ret {\n" name;
5348            pr "  guestfs_int_%s %s;\n" typ n;
5349            pr "};\n\n"
5350        | RStructList (n, typ) ->
5351            pr "struct %s_ret {\n" name;
5352            pr "  guestfs_int_%s_list %s;\n" typ n;
5353            pr "};\n\n"
5354        | RHashtable n ->
5355            pr "struct %s_ret {\n" name;
5356            pr "  str %s<>;\n" n;
5357            pr "};\n\n"
5358        | RBufferOut n ->
5359            pr "struct %s_ret {\n" name;
5360            pr "  opaque %s<>;\n" n;
5361            pr "};\n\n"
5362       );
5363   ) daemon_functions;
5364
5365   (* Table of procedure numbers. *)
5366   pr "enum guestfs_procedure {\n";
5367   List.iter (
5368     fun (shortname, _, proc_nr, _, _, _, _) ->
5369       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5370   ) daemon_functions;
5371   pr "  GUESTFS_PROC_NR_PROCS\n";
5372   pr "};\n";
5373   pr "\n";
5374
5375   (* Having to choose a maximum message size is annoying for several
5376    * reasons (it limits what we can do in the API), but it (a) makes
5377    * the protocol a lot simpler, and (b) provides a bound on the size
5378    * of the daemon which operates in limited memory space.
5379    *)
5380   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5381   pr "\n";
5382
5383   (* Message header, etc. *)
5384   pr "\
5385 /* The communication protocol is now documented in the guestfs(3)
5386  * manpage.
5387  */
5388
5389 const GUESTFS_PROGRAM = 0x2000F5F5;
5390 const GUESTFS_PROTOCOL_VERSION = 1;
5391
5392 /* These constants must be larger than any possible message length. */
5393 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5394 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5395
5396 enum guestfs_message_direction {
5397   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5398   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5399 };
5400
5401 enum guestfs_message_status {
5402   GUESTFS_STATUS_OK = 0,
5403   GUESTFS_STATUS_ERROR = 1
5404 };
5405
5406 const GUESTFS_ERROR_LEN = 256;
5407
5408 struct guestfs_message_error {
5409   string error_message<GUESTFS_ERROR_LEN>;
5410 };
5411
5412 struct guestfs_message_header {
5413   unsigned prog;                     /* GUESTFS_PROGRAM */
5414   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5415   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5416   guestfs_message_direction direction;
5417   unsigned serial;                   /* message serial number */
5418   guestfs_message_status status;
5419 };
5420
5421 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5422
5423 struct guestfs_chunk {
5424   int cancel;                        /* if non-zero, transfer is cancelled */
5425   /* data size is 0 bytes if the transfer has finished successfully */
5426   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5427 };
5428 "
5429
5430 (* Generate the guestfs-structs.h file. *)
5431 and generate_structs_h () =
5432   generate_header CStyle LGPLv2plus;
5433
5434   (* This is a public exported header file containing various
5435    * structures.  The structures are carefully written to have
5436    * exactly the same in-memory format as the XDR structures that
5437    * we use on the wire to the daemon.  The reason for creating
5438    * copies of these structures here is just so we don't have to
5439    * export the whole of guestfs_protocol.h (which includes much
5440    * unrelated and XDR-dependent stuff that we don't want to be
5441    * public, or required by clients).
5442    *
5443    * To reiterate, we will pass these structures to and from the
5444    * client with a simple assignment or memcpy, so the format
5445    * must be identical to what rpcgen / the RFC defines.
5446    *)
5447
5448   (* Public structures. *)
5449   List.iter (
5450     fun (typ, cols) ->
5451       pr "struct guestfs_%s {\n" typ;
5452       List.iter (
5453         function
5454         | name, FChar -> pr "  char %s;\n" name
5455         | name, FString -> pr "  char *%s;\n" name
5456         | name, FBuffer ->
5457             pr "  uint32_t %s_len;\n" name;
5458             pr "  char *%s;\n" name
5459         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5460         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5461         | name, FInt32 -> pr "  int32_t %s;\n" name
5462         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5463         | name, FInt64 -> pr "  int64_t %s;\n" name
5464         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5465       ) cols;
5466       pr "};\n";
5467       pr "\n";
5468       pr "struct guestfs_%s_list {\n" typ;
5469       pr "  uint32_t len;\n";
5470       pr "  struct guestfs_%s *val;\n" typ;
5471       pr "};\n";
5472       pr "\n";
5473       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5474       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5475       pr "\n"
5476   ) structs
5477
5478 (* Generate the guestfs-actions.h file. *)
5479 and generate_actions_h () =
5480   generate_header CStyle LGPLv2plus;
5481   List.iter (
5482     fun (shortname, style, _, _, _, _, _) ->
5483       let name = "guestfs_" ^ shortname in
5484       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5485         name style
5486   ) all_functions
5487
5488 (* Generate the guestfs-internal-actions.h file. *)
5489 and generate_internal_actions_h () =
5490   generate_header CStyle LGPLv2plus;
5491   List.iter (
5492     fun (shortname, style, _, _, _, _, _) ->
5493       let name = "guestfs__" ^ shortname in
5494       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5495         name style
5496   ) non_daemon_functions
5497
5498 (* Generate the client-side dispatch stubs. *)
5499 and generate_client_actions () =
5500   generate_header CStyle LGPLv2plus;
5501
5502   pr "\
5503 #include <stdio.h>
5504 #include <stdlib.h>
5505 #include <stdint.h>
5506 #include <string.h>
5507 #include <inttypes.h>
5508
5509 #include \"guestfs.h\"
5510 #include \"guestfs-internal.h\"
5511 #include \"guestfs-internal-actions.h\"
5512 #include \"guestfs_protocol.h\"
5513
5514 #define error guestfs_error
5515 //#define perrorf guestfs_perrorf
5516 #define safe_malloc guestfs_safe_malloc
5517 #define safe_realloc guestfs_safe_realloc
5518 //#define safe_strdup guestfs_safe_strdup
5519 #define safe_memdup guestfs_safe_memdup
5520
5521 /* Check the return message from a call for validity. */
5522 static int
5523 check_reply_header (guestfs_h *g,
5524                     const struct guestfs_message_header *hdr,
5525                     unsigned int proc_nr, unsigned int serial)
5526 {
5527   if (hdr->prog != GUESTFS_PROGRAM) {
5528     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5529     return -1;
5530   }
5531   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5532     error (g, \"wrong protocol version (%%d/%%d)\",
5533            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5534     return -1;
5535   }
5536   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5537     error (g, \"unexpected message direction (%%d/%%d)\",
5538            hdr->direction, GUESTFS_DIRECTION_REPLY);
5539     return -1;
5540   }
5541   if (hdr->proc != proc_nr) {
5542     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5543     return -1;
5544   }
5545   if (hdr->serial != serial) {
5546     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5547     return -1;
5548   }
5549
5550   return 0;
5551 }
5552
5553 /* Check we are in the right state to run a high-level action. */
5554 static int
5555 check_state (guestfs_h *g, const char *caller)
5556 {
5557   if (!guestfs__is_ready (g)) {
5558     if (guestfs__is_config (g) || guestfs__is_launching (g))
5559       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5560         caller);
5561     else
5562       error (g, \"%%s called from the wrong state, %%d != READY\",
5563         caller, guestfs__get_state (g));
5564     return -1;
5565   }
5566   return 0;
5567 }
5568
5569 ";
5570
5571   (* Generate code to generate guestfish call traces. *)
5572   let trace_call shortname style =
5573     pr "  if (guestfs__get_trace (g)) {\n";
5574
5575     let needs_i =
5576       List.exists (function
5577                    | StringList _ | DeviceList _ -> true
5578                    | _ -> false) (snd style) in
5579     if needs_i then (
5580       pr "    int i;\n";
5581       pr "\n"
5582     );
5583
5584     pr "    printf (\"%s\");\n" shortname;
5585     List.iter (
5586       function
5587       | String n                        (* strings *)
5588       | Device n
5589       | Pathname n
5590       | Dev_or_Path n
5591       | FileIn n
5592       | FileOut n ->
5593           (* guestfish doesn't support string escaping, so neither do we *)
5594           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5595       | OptString n ->                  (* string option *)
5596           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5597           pr "    else printf (\" null\");\n"
5598       | StringList n
5599       | DeviceList n ->                 (* string list *)
5600           pr "    putchar (' ');\n";
5601           pr "    putchar ('\"');\n";
5602           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5603           pr "      if (i > 0) putchar (' ');\n";
5604           pr "      fputs (%s[i], stdout);\n" n;
5605           pr "    }\n";
5606           pr "    putchar ('\"');\n";
5607       | Bool n ->                       (* boolean *)
5608           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5609       | Int n ->                        (* int *)
5610           pr "    printf (\" %%d\", %s);\n" n
5611       | Int64 n ->
5612           pr "    printf (\" %%\" PRIi64, %s);\n" n
5613     ) (snd style);
5614     pr "    putchar ('\\n');\n";
5615     pr "  }\n";
5616     pr "\n";
5617   in
5618
5619   (* For non-daemon functions, generate a wrapper around each function. *)
5620   List.iter (
5621     fun (shortname, style, _, _, _, _, _) ->
5622       let name = "guestfs_" ^ shortname in
5623
5624       generate_prototype ~extern:false ~semicolon:false ~newline:true
5625         ~handle:"g" name style;
5626       pr "{\n";
5627       trace_call shortname style;
5628       pr "  return guestfs__%s " shortname;
5629       generate_c_call_args ~handle:"g" style;
5630       pr ";\n";
5631       pr "}\n";
5632       pr "\n"
5633   ) non_daemon_functions;
5634
5635   (* Client-side stubs for each function. *)
5636   List.iter (
5637     fun (shortname, style, _, _, _, _, _) ->
5638       let name = "guestfs_" ^ shortname in
5639
5640       (* Generate the action stub. *)
5641       generate_prototype ~extern:false ~semicolon:false ~newline:true
5642         ~handle:"g" name style;
5643
5644       let error_code =
5645         match fst style with
5646         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5647         | RConstString _ | RConstOptString _ ->
5648             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5649         | RString _ | RStringList _
5650         | RStruct _ | RStructList _
5651         | RHashtable _ | RBufferOut _ ->
5652             "NULL" in
5653
5654       pr "{\n";
5655
5656       (match snd style with
5657        | [] -> ()
5658        | _ -> pr "  struct %s_args args;\n" name
5659       );
5660
5661       pr "  guestfs_message_header hdr;\n";
5662       pr "  guestfs_message_error err;\n";
5663       let has_ret =
5664         match fst style with
5665         | RErr -> false
5666         | RConstString _ | RConstOptString _ ->
5667             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5668         | RInt _ | RInt64 _
5669         | RBool _ | RString _ | RStringList _
5670         | RStruct _ | RStructList _
5671         | RHashtable _ | RBufferOut _ ->
5672             pr "  struct %s_ret ret;\n" name;
5673             true in
5674
5675       pr "  int serial;\n";
5676       pr "  int r;\n";
5677       pr "\n";
5678       trace_call shortname style;
5679       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5680       pr "  guestfs___set_busy (g);\n";
5681       pr "\n";
5682
5683       (* Send the main header and arguments. *)
5684       (match snd style with
5685        | [] ->
5686            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5687              (String.uppercase shortname)
5688        | args ->
5689            List.iter (
5690              function
5691              | Pathname n | Device n | Dev_or_Path n | String n ->
5692                  pr "  args.%s = (char *) %s;\n" n n
5693              | OptString n ->
5694                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5695              | StringList n | DeviceList n ->
5696                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5697                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5698              | Bool n ->
5699                  pr "  args.%s = %s;\n" n n
5700              | Int n ->
5701                  pr "  args.%s = %s;\n" n n
5702              | Int64 n ->
5703                  pr "  args.%s = %s;\n" n n
5704              | FileIn _ | FileOut _ -> ()
5705            ) args;
5706            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5707              (String.uppercase shortname);
5708            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5709              name;
5710       );
5711       pr "  if (serial == -1) {\n";
5712       pr "    guestfs___end_busy (g);\n";
5713       pr "    return %s;\n" error_code;
5714       pr "  }\n";
5715       pr "\n";
5716
5717       (* Send any additional files (FileIn) requested. *)
5718       let need_read_reply_label = ref false in
5719       List.iter (
5720         function
5721         | FileIn n ->
5722             pr "  r = guestfs___send_file (g, %s);\n" n;
5723             pr "  if (r == -1) {\n";
5724             pr "    guestfs___end_busy (g);\n";
5725             pr "    return %s;\n" error_code;
5726             pr "  }\n";
5727             pr "  if (r == -2) /* daemon cancelled */\n";
5728             pr "    goto read_reply;\n";
5729             need_read_reply_label := true;
5730             pr "\n";
5731         | _ -> ()
5732       ) (snd style);
5733
5734       (* Wait for the reply from the remote end. *)
5735       if !need_read_reply_label then pr " read_reply:\n";
5736       pr "  memset (&hdr, 0, sizeof hdr);\n";
5737       pr "  memset (&err, 0, sizeof err);\n";
5738       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5739       pr "\n";
5740       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5741       if not has_ret then
5742         pr "NULL, NULL"
5743       else
5744         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5745       pr ");\n";
5746
5747       pr "  if (r == -1) {\n";
5748       pr "    guestfs___end_busy (g);\n";
5749       pr "    return %s;\n" error_code;
5750       pr "  }\n";
5751       pr "\n";
5752
5753       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5754         (String.uppercase shortname);
5755       pr "    guestfs___end_busy (g);\n";
5756       pr "    return %s;\n" error_code;
5757       pr "  }\n";
5758       pr "\n";
5759
5760       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5761       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5762       pr "    free (err.error_message);\n";
5763       pr "    guestfs___end_busy (g);\n";
5764       pr "    return %s;\n" error_code;
5765       pr "  }\n";
5766       pr "\n";
5767
5768       (* Expecting to receive further files (FileOut)? *)
5769       List.iter (
5770         function
5771         | FileOut n ->
5772             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5773             pr "    guestfs___end_busy (g);\n";
5774             pr "    return %s;\n" error_code;
5775             pr "  }\n";
5776             pr "\n";
5777         | _ -> ()
5778       ) (snd style);
5779
5780       pr "  guestfs___end_busy (g);\n";
5781
5782       (match fst style with
5783        | RErr -> pr "  return 0;\n"
5784        | RInt n | RInt64 n | RBool n ->
5785            pr "  return ret.%s;\n" n
5786        | RConstString _ | RConstOptString _ ->
5787            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5788        | RString n ->
5789            pr "  return ret.%s; /* caller will free */\n" n
5790        | RStringList n | RHashtable n ->
5791            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5792            pr "  ret.%s.%s_val =\n" n n;
5793            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5794            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5795              n n;
5796            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5797            pr "  return ret.%s.%s_val;\n" n n
5798        | RStruct (n, _) ->
5799            pr "  /* caller will free this */\n";
5800            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5801        | RStructList (n, _) ->
5802            pr "  /* caller will free this */\n";
5803            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5804        | RBufferOut n ->
5805            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5806            pr "   * _val might be NULL here.  To make the API saner for\n";
5807            pr "   * callers, we turn this case into a unique pointer (using\n";
5808            pr "   * malloc(1)).\n";
5809            pr "   */\n";
5810            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5811            pr "    *size_r = ret.%s.%s_len;\n" n n;
5812            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5813            pr "  } else {\n";
5814            pr "    free (ret.%s.%s_val);\n" n n;
5815            pr "    char *p = safe_malloc (g, 1);\n";
5816            pr "    *size_r = ret.%s.%s_len;\n" n n;
5817            pr "    return p;\n";
5818            pr "  }\n";
5819       );
5820
5821       pr "}\n\n"
5822   ) daemon_functions;
5823
5824   (* Functions to free structures. *)
5825   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5826   pr " * structure format is identical to the XDR format.  See note in\n";
5827   pr " * generator.ml.\n";
5828   pr " */\n";
5829   pr "\n";
5830
5831   List.iter (
5832     fun (typ, _) ->
5833       pr "void\n";
5834       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5835       pr "{\n";
5836       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5837       pr "  free (x);\n";
5838       pr "}\n";
5839       pr "\n";
5840
5841       pr "void\n";
5842       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5843       pr "{\n";
5844       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5845       pr "  free (x);\n";
5846       pr "}\n";
5847       pr "\n";
5848
5849   ) structs;
5850
5851 (* Generate daemon/actions.h. *)
5852 and generate_daemon_actions_h () =
5853   generate_header CStyle GPLv2plus;
5854
5855   pr "#include \"../src/guestfs_protocol.h\"\n";
5856   pr "\n";
5857
5858   List.iter (
5859     fun (name, style, _, _, _, _, _) ->
5860       generate_prototype
5861         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5862         name style;
5863   ) daemon_functions
5864
5865 (* Generate the linker script which controls the visibility of
5866  * symbols in the public ABI and ensures no other symbols get
5867  * exported accidentally.
5868  *)
5869 and generate_linker_script () =
5870   generate_header HashStyle GPLv2plus;
5871
5872   let globals = [
5873     "guestfs_create";
5874     "guestfs_close";
5875     "guestfs_get_error_handler";
5876     "guestfs_get_out_of_memory_handler";
5877     "guestfs_last_error";
5878     "guestfs_set_error_handler";
5879     "guestfs_set_launch_done_callback";
5880     "guestfs_set_log_message_callback";
5881     "guestfs_set_out_of_memory_handler";
5882     "guestfs_set_subprocess_quit_callback";
5883
5884     (* Unofficial parts of the API: the bindings code use these
5885      * functions, so it is useful to export them.
5886      *)
5887     "guestfs_safe_calloc";
5888     "guestfs_safe_malloc";
5889   ] in
5890   let functions =
5891     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5892       all_functions in
5893   let structs =
5894     List.concat (
5895       List.map (fun (typ, _) ->
5896                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5897         structs
5898     ) in
5899   let globals = List.sort compare (globals @ functions @ structs) in
5900
5901   pr "{\n";
5902   pr "    global:\n";
5903   List.iter (pr "        %s;\n") globals;
5904   pr "\n";
5905
5906   pr "    local:\n";
5907   pr "        *;\n";
5908   pr "};\n"
5909
5910 (* Generate the server-side stubs. *)
5911 and generate_daemon_actions () =
5912   generate_header CStyle GPLv2plus;
5913
5914   pr "#include <config.h>\n";
5915   pr "\n";
5916   pr "#include <stdio.h>\n";
5917   pr "#include <stdlib.h>\n";
5918   pr "#include <string.h>\n";
5919   pr "#include <inttypes.h>\n";
5920   pr "#include <rpc/types.h>\n";
5921   pr "#include <rpc/xdr.h>\n";
5922   pr "\n";
5923   pr "#include \"daemon.h\"\n";
5924   pr "#include \"c-ctype.h\"\n";
5925   pr "#include \"../src/guestfs_protocol.h\"\n";
5926   pr "#include \"actions.h\"\n";
5927   pr "\n";
5928
5929   List.iter (
5930     fun (name, style, _, _, _, _, _) ->
5931       (* Generate server-side stubs. *)
5932       pr "static void %s_stub (XDR *xdr_in)\n" name;
5933       pr "{\n";
5934       let error_code =
5935         match fst style with
5936         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5937         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5938         | RBool _ -> pr "  int r;\n"; "-1"
5939         | RConstString _ | RConstOptString _ ->
5940             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5941         | RString _ -> pr "  char *r;\n"; "NULL"
5942         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5943         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5944         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5945         | RBufferOut _ ->
5946             pr "  size_t size = 1;\n";
5947             pr "  char *r;\n";
5948             "NULL" in
5949
5950       (match snd style with
5951        | [] -> ()
5952        | args ->
5953            pr "  struct guestfs_%s_args args;\n" name;
5954            List.iter (
5955              function
5956              | Device n | Dev_or_Path n
5957              | Pathname n
5958              | String n -> ()
5959              | OptString n -> pr "  char *%s;\n" n
5960              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5961              | Bool n -> pr "  int %s;\n" n
5962              | Int n -> pr "  int %s;\n" n
5963              | Int64 n -> pr "  int64_t %s;\n" n
5964              | FileIn _ | FileOut _ -> ()
5965            ) args
5966       );
5967       pr "\n";
5968
5969       (match snd style with
5970        | [] -> ()
5971        | args ->
5972            pr "  memset (&args, 0, sizeof args);\n";
5973            pr "\n";
5974            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5975            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5976            pr "    return;\n";
5977            pr "  }\n";
5978            let pr_args n =
5979              pr "  char *%s = args.%s;\n" n n
5980            in
5981            let pr_list_handling_code n =
5982              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5983              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5984              pr "  if (%s == NULL) {\n" n;
5985              pr "    reply_with_perror (\"realloc\");\n";
5986              pr "    goto done;\n";
5987              pr "  }\n";
5988              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5989              pr "  args.%s.%s_val = %s;\n" n n n;
5990            in
5991            List.iter (
5992              function
5993              | Pathname n ->
5994                  pr_args n;
5995                  pr "  ABS_PATH (%s, goto done);\n" n;
5996              | Device n ->
5997                  pr_args n;
5998                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5999              | Dev_or_Path n ->
6000                  pr_args n;
6001                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6002              | String n -> pr_args n
6003              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6004              | StringList n ->
6005                  pr_list_handling_code n;
6006              | DeviceList n ->
6007                  pr_list_handling_code n;
6008                  pr "  /* Ensure that each is a device,\n";
6009                  pr "   * and perform device name translation. */\n";
6010                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6011                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6012                  pr "  }\n";
6013              | Bool n -> pr "  %s = args.%s;\n" n n
6014              | Int n -> pr "  %s = args.%s;\n" n n
6015              | Int64 n -> pr "  %s = args.%s;\n" n n
6016              | FileIn _ | FileOut _ -> ()
6017            ) args;
6018            pr "\n"
6019       );
6020
6021
6022       (* this is used at least for do_equal *)
6023       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6024         (* Emit NEED_ROOT just once, even when there are two or
6025            more Pathname args *)
6026         pr "  NEED_ROOT (goto done);\n";
6027       );
6028
6029       (* Don't want to call the impl with any FileIn or FileOut
6030        * parameters, since these go "outside" the RPC protocol.
6031        *)
6032       let args' =
6033         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6034           (snd style) in
6035       pr "  r = do_%s " name;
6036       generate_c_call_args (fst style, args');
6037       pr ";\n";
6038
6039       (match fst style with
6040        | RErr | RInt _ | RInt64 _ | RBool _
6041        | RConstString _ | RConstOptString _
6042        | RString _ | RStringList _ | RHashtable _
6043        | RStruct (_, _) | RStructList (_, _) ->
6044            pr "  if (r == %s)\n" error_code;
6045            pr "    /* do_%s has already called reply_with_error */\n" name;
6046            pr "    goto done;\n";
6047            pr "\n"
6048        | RBufferOut _ ->
6049            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6050            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6051            pr "   */\n";
6052            pr "  if (size == 1 && r == %s)\n" error_code;
6053            pr "    /* do_%s has already called reply_with_error */\n" name;
6054            pr "    goto done;\n";
6055            pr "\n"
6056       );
6057
6058       (* If there are any FileOut parameters, then the impl must
6059        * send its own reply.
6060        *)
6061       let no_reply =
6062         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6063       if no_reply then
6064         pr "  /* do_%s has already sent a reply */\n" name
6065       else (
6066         match fst style with
6067         | RErr -> pr "  reply (NULL, NULL);\n"
6068         | RInt n | RInt64 n | RBool n ->
6069             pr "  struct guestfs_%s_ret ret;\n" name;
6070             pr "  ret.%s = r;\n" n;
6071             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6072               name
6073         | RConstString _ | RConstOptString _ ->
6074             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6075         | RString n ->
6076             pr "  struct guestfs_%s_ret ret;\n" name;
6077             pr "  ret.%s = r;\n" n;
6078             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6079               name;
6080             pr "  free (r);\n"
6081         | RStringList n | RHashtable n ->
6082             pr "  struct guestfs_%s_ret ret;\n" name;
6083             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6084             pr "  ret.%s.%s_val = r;\n" n n;
6085             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6086               name;
6087             pr "  free_strings (r);\n"
6088         | RStruct (n, _) ->
6089             pr "  struct guestfs_%s_ret ret;\n" name;
6090             pr "  ret.%s = *r;\n" n;
6091             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6092               name;
6093             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6094               name
6095         | RStructList (n, _) ->
6096             pr "  struct guestfs_%s_ret ret;\n" name;
6097             pr "  ret.%s = *r;\n" n;
6098             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6099               name;
6100             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6101               name
6102         | RBufferOut n ->
6103             pr "  struct guestfs_%s_ret ret;\n" name;
6104             pr "  ret.%s.%s_val = r;\n" n n;
6105             pr "  ret.%s.%s_len = size;\n" n n;
6106             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6107               name;
6108             pr "  free (r);\n"
6109       );
6110
6111       (* Free the args. *)
6112       (match snd style with
6113        | [] ->
6114            pr "done: ;\n";
6115        | _ ->
6116            pr "done:\n";
6117            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6118              name
6119       );
6120
6121       pr "}\n\n";
6122   ) daemon_functions;
6123
6124   (* Dispatch function. *)
6125   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6126   pr "{\n";
6127   pr "  switch (proc_nr) {\n";
6128
6129   List.iter (
6130     fun (name, style, _, _, _, _, _) ->
6131       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6132       pr "      %s_stub (xdr_in);\n" name;
6133       pr "      break;\n"
6134   ) daemon_functions;
6135
6136   pr "    default:\n";
6137   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";
6138   pr "  }\n";
6139   pr "}\n";
6140   pr "\n";
6141
6142   (* LVM columns and tokenization functions. *)
6143   (* XXX This generates crap code.  We should rethink how we
6144    * do this parsing.
6145    *)
6146   List.iter (
6147     function
6148     | typ, cols ->
6149         pr "static const char *lvm_%s_cols = \"%s\";\n"
6150           typ (String.concat "," (List.map fst cols));
6151         pr "\n";
6152
6153         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6154         pr "{\n";
6155         pr "  char *tok, *p, *next;\n";
6156         pr "  int i, j;\n";
6157         pr "\n";
6158         (*
6159           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6160           pr "\n";
6161         *)
6162         pr "  if (!str) {\n";
6163         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6164         pr "    return -1;\n";
6165         pr "  }\n";
6166         pr "  if (!*str || c_isspace (*str)) {\n";
6167         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6168         pr "    return -1;\n";
6169         pr "  }\n";
6170         pr "  tok = str;\n";
6171         List.iter (
6172           fun (name, coltype) ->
6173             pr "  if (!tok) {\n";
6174             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6175             pr "    return -1;\n";
6176             pr "  }\n";
6177             pr "  p = strchrnul (tok, ',');\n";
6178             pr "  if (*p) next = p+1; else next = NULL;\n";
6179             pr "  *p = '\\0';\n";
6180             (match coltype with
6181              | FString ->
6182                  pr "  r->%s = strdup (tok);\n" name;
6183                  pr "  if (r->%s == NULL) {\n" name;
6184                  pr "    perror (\"strdup\");\n";
6185                  pr "    return -1;\n";
6186                  pr "  }\n"
6187              | FUUID ->
6188                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6189                  pr "    if (tok[j] == '\\0') {\n";
6190                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6191                  pr "      return -1;\n";
6192                  pr "    } else if (tok[j] != '-')\n";
6193                  pr "      r->%s[i++] = tok[j];\n" name;
6194                  pr "  }\n";
6195              | FBytes ->
6196                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6197                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6198                  pr "    return -1;\n";
6199                  pr "  }\n";
6200              | FInt64 ->
6201                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6202                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6203                  pr "    return -1;\n";
6204                  pr "  }\n";
6205              | FOptPercent ->
6206                  pr "  if (tok[0] == '\\0')\n";
6207                  pr "    r->%s = -1;\n" name;
6208                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6209                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6210                  pr "    return -1;\n";
6211                  pr "  }\n";
6212              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6213                  assert false (* can never be an LVM column *)
6214             );
6215             pr "  tok = next;\n";
6216         ) cols;
6217
6218         pr "  if (tok != NULL) {\n";
6219         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6220         pr "    return -1;\n";
6221         pr "  }\n";
6222         pr "  return 0;\n";
6223         pr "}\n";
6224         pr "\n";
6225
6226         pr "guestfs_int_lvm_%s_list *\n" typ;
6227         pr "parse_command_line_%ss (void)\n" typ;
6228         pr "{\n";
6229         pr "  char *out, *err;\n";
6230         pr "  char *p, *pend;\n";
6231         pr "  int r, i;\n";
6232         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6233         pr "  void *newp;\n";
6234         pr "\n";
6235         pr "  ret = malloc (sizeof *ret);\n";
6236         pr "  if (!ret) {\n";
6237         pr "    reply_with_perror (\"malloc\");\n";
6238         pr "    return NULL;\n";
6239         pr "  }\n";
6240         pr "\n";
6241         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6242         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6243         pr "\n";
6244         pr "  r = command (&out, &err,\n";
6245         pr "           \"lvm\", \"%ss\",\n" typ;
6246         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6247         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6248         pr "  if (r == -1) {\n";
6249         pr "    reply_with_error (\"%%s\", err);\n";
6250         pr "    free (out);\n";
6251         pr "    free (err);\n";
6252         pr "    free (ret);\n";
6253         pr "    return NULL;\n";
6254         pr "  }\n";
6255         pr "\n";
6256         pr "  free (err);\n";
6257         pr "\n";
6258         pr "  /* Tokenize each line of the output. */\n";
6259         pr "  p = out;\n";
6260         pr "  i = 0;\n";
6261         pr "  while (p) {\n";
6262         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6263         pr "    if (pend) {\n";
6264         pr "      *pend = '\\0';\n";
6265         pr "      pend++;\n";
6266         pr "    }\n";
6267         pr "\n";
6268         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6269         pr "      p++;\n";
6270         pr "\n";
6271         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6272         pr "      p = pend;\n";
6273         pr "      continue;\n";
6274         pr "    }\n";
6275         pr "\n";
6276         pr "    /* Allocate some space to store this next entry. */\n";
6277         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6278         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6279         pr "    if (newp == NULL) {\n";
6280         pr "      reply_with_perror (\"realloc\");\n";
6281         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6282         pr "      free (ret);\n";
6283         pr "      free (out);\n";
6284         pr "      return NULL;\n";
6285         pr "    }\n";
6286         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6287         pr "\n";
6288         pr "    /* Tokenize the next entry. */\n";
6289         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6290         pr "    if (r == -1) {\n";
6291         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6292         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6293         pr "      free (ret);\n";
6294         pr "      free (out);\n";
6295         pr "      return NULL;\n";
6296         pr "    }\n";
6297         pr "\n";
6298         pr "    ++i;\n";
6299         pr "    p = pend;\n";
6300         pr "  }\n";
6301         pr "\n";
6302         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6303         pr "\n";
6304         pr "  free (out);\n";
6305         pr "  return ret;\n";
6306         pr "}\n"
6307
6308   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6309
6310 (* Generate a list of function names, for debugging in the daemon.. *)
6311 and generate_daemon_names () =
6312   generate_header CStyle GPLv2plus;
6313
6314   pr "#include <config.h>\n";
6315   pr "\n";
6316   pr "#include \"daemon.h\"\n";
6317   pr "\n";
6318
6319   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6320   pr "const char *function_names[] = {\n";
6321   List.iter (
6322     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6323   ) daemon_functions;
6324   pr "};\n";
6325
6326 (* Generate the optional groups for the daemon to implement
6327  * guestfs_available.
6328  *)
6329 and generate_daemon_optgroups_c () =
6330   generate_header CStyle GPLv2plus;
6331
6332   pr "#include <config.h>\n";
6333   pr "\n";
6334   pr "#include \"daemon.h\"\n";
6335   pr "#include \"optgroups.h\"\n";
6336   pr "\n";
6337
6338   pr "struct optgroup optgroups[] = {\n";
6339   List.iter (
6340     fun (group, _) ->
6341       pr "  { \"%s\", optgroup_%s_available },\n" group group
6342   ) optgroups;
6343   pr "  { NULL, NULL }\n";
6344   pr "};\n"
6345
6346 and generate_daemon_optgroups_h () =
6347   generate_header CStyle GPLv2plus;
6348
6349   List.iter (
6350     fun (group, _) ->
6351       pr "extern int optgroup_%s_available (void);\n" group
6352   ) optgroups
6353
6354 (* Generate the tests. *)
6355 and generate_tests () =
6356   generate_header CStyle GPLv2plus;
6357
6358   pr "\
6359 #include <stdio.h>
6360 #include <stdlib.h>
6361 #include <string.h>
6362 #include <unistd.h>
6363 #include <sys/types.h>
6364 #include <fcntl.h>
6365
6366 #include \"guestfs.h\"
6367 #include \"guestfs-internal.h\"
6368
6369 static guestfs_h *g;
6370 static int suppress_error = 0;
6371
6372 static void print_error (guestfs_h *g, void *data, const char *msg)
6373 {
6374   if (!suppress_error)
6375     fprintf (stderr, \"%%s\\n\", msg);
6376 }
6377
6378 /* FIXME: nearly identical code appears in fish.c */
6379 static void print_strings (char *const *argv)
6380 {
6381   int argc;
6382
6383   for (argc = 0; argv[argc] != NULL; ++argc)
6384     printf (\"\\t%%s\\n\", argv[argc]);
6385 }
6386
6387 /*
6388 static void print_table (char const *const *argv)
6389 {
6390   int i;
6391
6392   for (i = 0; argv[i] != NULL; i += 2)
6393     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6394 }
6395 */
6396
6397 ";
6398
6399   (* Generate a list of commands which are not tested anywhere. *)
6400   pr "static void no_test_warnings (void)\n";
6401   pr "{\n";
6402
6403   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6404   List.iter (
6405     fun (_, _, _, _, tests, _, _) ->
6406       let tests = filter_map (
6407         function
6408         | (_, (Always|If _|Unless _), test) -> Some test
6409         | (_, Disabled, _) -> None
6410       ) tests in
6411       let seq = List.concat (List.map seq_of_test tests) in
6412       let cmds_tested = List.map List.hd seq in
6413       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6414   ) all_functions;
6415
6416   List.iter (
6417     fun (name, _, _, _, _, _, _) ->
6418       if not (Hashtbl.mem hash name) then
6419         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6420   ) all_functions;
6421
6422   pr "}\n";
6423   pr "\n";
6424
6425   (* Generate the actual tests.  Note that we generate the tests
6426    * in reverse order, deliberately, so that (in general) the
6427    * newest tests run first.  This makes it quicker and easier to
6428    * debug them.
6429    *)
6430   let test_names =
6431     List.map (
6432       fun (name, _, _, flags, tests, _, _) ->
6433         mapi (generate_one_test name flags) tests
6434     ) (List.rev all_functions) in
6435   let test_names = List.concat test_names in
6436   let nr_tests = List.length test_names in
6437
6438   pr "\
6439 int main (int argc, char *argv[])
6440 {
6441   char c = 0;
6442   unsigned long int n_failed = 0;
6443   const char *filename;
6444   int fd;
6445   int nr_tests, test_num = 0;
6446
6447   setbuf (stdout, NULL);
6448
6449   no_test_warnings ();
6450
6451   g = guestfs_create ();
6452   if (g == NULL) {
6453     printf (\"guestfs_create FAILED\\n\");
6454     exit (EXIT_FAILURE);
6455   }
6456
6457   guestfs_set_error_handler (g, print_error, NULL);
6458
6459   guestfs_set_path (g, \"../appliance\");
6460
6461   filename = \"test1.img\";
6462   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6463   if (fd == -1) {
6464     perror (filename);
6465     exit (EXIT_FAILURE);
6466   }
6467   if (lseek (fd, %d, SEEK_SET) == -1) {
6468     perror (\"lseek\");
6469     close (fd);
6470     unlink (filename);
6471     exit (EXIT_FAILURE);
6472   }
6473   if (write (fd, &c, 1) == -1) {
6474     perror (\"write\");
6475     close (fd);
6476     unlink (filename);
6477     exit (EXIT_FAILURE);
6478   }
6479   if (close (fd) == -1) {
6480     perror (filename);
6481     unlink (filename);
6482     exit (EXIT_FAILURE);
6483   }
6484   if (guestfs_add_drive (g, filename) == -1) {
6485     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6486     exit (EXIT_FAILURE);
6487   }
6488
6489   filename = \"test2.img\";
6490   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6491   if (fd == -1) {
6492     perror (filename);
6493     exit (EXIT_FAILURE);
6494   }
6495   if (lseek (fd, %d, SEEK_SET) == -1) {
6496     perror (\"lseek\");
6497     close (fd);
6498     unlink (filename);
6499     exit (EXIT_FAILURE);
6500   }
6501   if (write (fd, &c, 1) == -1) {
6502     perror (\"write\");
6503     close (fd);
6504     unlink (filename);
6505     exit (EXIT_FAILURE);
6506   }
6507   if (close (fd) == -1) {
6508     perror (filename);
6509     unlink (filename);
6510     exit (EXIT_FAILURE);
6511   }
6512   if (guestfs_add_drive (g, filename) == -1) {
6513     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6514     exit (EXIT_FAILURE);
6515   }
6516
6517   filename = \"test3.img\";
6518   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6519   if (fd == -1) {
6520     perror (filename);
6521     exit (EXIT_FAILURE);
6522   }
6523   if (lseek (fd, %d, SEEK_SET) == -1) {
6524     perror (\"lseek\");
6525     close (fd);
6526     unlink (filename);
6527     exit (EXIT_FAILURE);
6528   }
6529   if (write (fd, &c, 1) == -1) {
6530     perror (\"write\");
6531     close (fd);
6532     unlink (filename);
6533     exit (EXIT_FAILURE);
6534   }
6535   if (close (fd) == -1) {
6536     perror (filename);
6537     unlink (filename);
6538     exit (EXIT_FAILURE);
6539   }
6540   if (guestfs_add_drive (g, filename) == -1) {
6541     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6542     exit (EXIT_FAILURE);
6543   }
6544
6545   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6546     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6547     exit (EXIT_FAILURE);
6548   }
6549
6550   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6551   alarm (600);
6552
6553   if (guestfs_launch (g) == -1) {
6554     printf (\"guestfs_launch FAILED\\n\");
6555     exit (EXIT_FAILURE);
6556   }
6557
6558   /* Cancel previous alarm. */
6559   alarm (0);
6560
6561   nr_tests = %d;
6562
6563 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6564
6565   iteri (
6566     fun i test_name ->
6567       pr "  test_num++;\n";
6568       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6569       pr "  if (%s () == -1) {\n" test_name;
6570       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6571       pr "    n_failed++;\n";
6572       pr "  }\n";
6573   ) test_names;
6574   pr "\n";
6575
6576   pr "  guestfs_close (g);\n";
6577   pr "  unlink (\"test1.img\");\n";
6578   pr "  unlink (\"test2.img\");\n";
6579   pr "  unlink (\"test3.img\");\n";
6580   pr "\n";
6581
6582   pr "  if (n_failed > 0) {\n";
6583   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6584   pr "    exit (EXIT_FAILURE);\n";
6585   pr "  }\n";
6586   pr "\n";
6587
6588   pr "  exit (EXIT_SUCCESS);\n";
6589   pr "}\n"
6590
6591 and generate_one_test name flags i (init, prereq, test) =
6592   let test_name = sprintf "test_%s_%d" name i in
6593
6594   pr "\
6595 static int %s_skip (void)
6596 {
6597   const char *str;
6598
6599   str = getenv (\"TEST_ONLY\");
6600   if (str)
6601     return strstr (str, \"%s\") == NULL;
6602   str = getenv (\"SKIP_%s\");
6603   if (str && STREQ (str, \"1\")) return 1;
6604   str = getenv (\"SKIP_TEST_%s\");
6605   if (str && STREQ (str, \"1\")) return 1;
6606   return 0;
6607 }
6608
6609 " test_name name (String.uppercase test_name) (String.uppercase name);
6610
6611   (match prereq with
6612    | Disabled | Always -> ()
6613    | If code | Unless code ->
6614        pr "static int %s_prereq (void)\n" test_name;
6615        pr "{\n";
6616        pr "  %s\n" code;
6617        pr "}\n";
6618        pr "\n";
6619   );
6620
6621   pr "\
6622 static int %s (void)
6623 {
6624   if (%s_skip ()) {
6625     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6626     return 0;
6627   }
6628
6629 " test_name test_name test_name;
6630
6631   (* Optional functions should only be tested if the relevant
6632    * support is available in the daemon.
6633    *)
6634   List.iter (
6635     function
6636     | Optional group ->
6637         pr "  {\n";
6638         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6639         pr "    int r;\n";
6640         pr "    suppress_error = 1;\n";
6641         pr "    r = guestfs_available (g, (char **) groups);\n";
6642         pr "    suppress_error = 0;\n";
6643         pr "    if (r == -1) {\n";
6644         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6645         pr "      return 0;\n";
6646         pr "    }\n";
6647         pr "  }\n";
6648     | _ -> ()
6649   ) flags;
6650
6651   (match prereq with
6652    | Disabled ->
6653        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6654    | If _ ->
6655        pr "  if (! %s_prereq ()) {\n" test_name;
6656        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6657        pr "    return 0;\n";
6658        pr "  }\n";
6659        pr "\n";
6660        generate_one_test_body name i test_name init test;
6661    | Unless _ ->
6662        pr "  if (%s_prereq ()) {\n" test_name;
6663        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6664        pr "    return 0;\n";
6665        pr "  }\n";
6666        pr "\n";
6667        generate_one_test_body name i test_name init test;
6668    | Always ->
6669        generate_one_test_body name i test_name init test
6670   );
6671
6672   pr "  return 0;\n";
6673   pr "}\n";
6674   pr "\n";
6675   test_name
6676
6677 and generate_one_test_body name i test_name init test =
6678   (match init with
6679    | InitNone (* XXX at some point, InitNone and InitEmpty became
6680                * folded together as the same thing.  Really we should
6681                * make InitNone do nothing at all, but the tests may
6682                * need to be checked to make sure this is OK.
6683                *)
6684    | InitEmpty ->
6685        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6686        List.iter (generate_test_command_call test_name)
6687          [["blockdev_setrw"; "/dev/sda"];
6688           ["umount_all"];
6689           ["lvm_remove_all"]]
6690    | InitPartition ->
6691        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6692        List.iter (generate_test_command_call test_name)
6693          [["blockdev_setrw"; "/dev/sda"];
6694           ["umount_all"];
6695           ["lvm_remove_all"];
6696           ["part_disk"; "/dev/sda"; "mbr"]]
6697    | InitBasicFS ->
6698        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6699        List.iter (generate_test_command_call test_name)
6700          [["blockdev_setrw"; "/dev/sda"];
6701           ["umount_all"];
6702           ["lvm_remove_all"];
6703           ["part_disk"; "/dev/sda"; "mbr"];
6704           ["mkfs"; "ext2"; "/dev/sda1"];
6705           ["mount_options"; ""; "/dev/sda1"; "/"]]
6706    | InitBasicFSonLVM ->
6707        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6708          test_name;
6709        List.iter (generate_test_command_call test_name)
6710          [["blockdev_setrw"; "/dev/sda"];
6711           ["umount_all"];
6712           ["lvm_remove_all"];
6713           ["part_disk"; "/dev/sda"; "mbr"];
6714           ["pvcreate"; "/dev/sda1"];
6715           ["vgcreate"; "VG"; "/dev/sda1"];
6716           ["lvcreate"; "LV"; "VG"; "8"];
6717           ["mkfs"; "ext2"; "/dev/VG/LV"];
6718           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6719    | InitISOFS ->
6720        pr "  /* InitISOFS for %s */\n" test_name;
6721        List.iter (generate_test_command_call test_name)
6722          [["blockdev_setrw"; "/dev/sda"];
6723           ["umount_all"];
6724           ["lvm_remove_all"];
6725           ["mount_ro"; "/dev/sdd"; "/"]]
6726   );
6727
6728   let get_seq_last = function
6729     | [] ->
6730         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6731           test_name
6732     | seq ->
6733         let seq = List.rev seq in
6734         List.rev (List.tl seq), List.hd seq
6735   in
6736
6737   match test with
6738   | TestRun seq ->
6739       pr "  /* TestRun for %s (%d) */\n" name i;
6740       List.iter (generate_test_command_call test_name) seq
6741   | TestOutput (seq, expected) ->
6742       pr "  /* TestOutput for %s (%d) */\n" name i;
6743       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6744       let seq, last = get_seq_last seq in
6745       let test () =
6746         pr "    if (STRNEQ (r, expected)) {\n";
6747         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6748         pr "      return -1;\n";
6749         pr "    }\n"
6750       in
6751       List.iter (generate_test_command_call test_name) seq;
6752       generate_test_command_call ~test test_name last
6753   | TestOutputList (seq, expected) ->
6754       pr "  /* TestOutputList for %s (%d) */\n" name i;
6755       let seq, last = get_seq_last seq in
6756       let test () =
6757         iteri (
6758           fun i str ->
6759             pr "    if (!r[%d]) {\n" i;
6760             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6761             pr "      print_strings (r);\n";
6762             pr "      return -1;\n";
6763             pr "    }\n";
6764             pr "    {\n";
6765             pr "      const char *expected = \"%s\";\n" (c_quote str);
6766             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6767             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6768             pr "        return -1;\n";
6769             pr "      }\n";
6770             pr "    }\n"
6771         ) expected;
6772         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6773         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6774           test_name;
6775         pr "      print_strings (r);\n";
6776         pr "      return -1;\n";
6777         pr "    }\n"
6778       in
6779       List.iter (generate_test_command_call test_name) seq;
6780       generate_test_command_call ~test test_name last
6781   | TestOutputListOfDevices (seq, expected) ->
6782       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6783       let seq, last = get_seq_last seq in
6784       let test () =
6785         iteri (
6786           fun i str ->
6787             pr "    if (!r[%d]) {\n" i;
6788             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6789             pr "      print_strings (r);\n";
6790             pr "      return -1;\n";
6791             pr "    }\n";
6792             pr "    {\n";
6793             pr "      const char *expected = \"%s\";\n" (c_quote str);
6794             pr "      r[%d][5] = 's';\n" i;
6795             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6796             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6797             pr "        return -1;\n";
6798             pr "      }\n";
6799             pr "    }\n"
6800         ) expected;
6801         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6802         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6803           test_name;
6804         pr "      print_strings (r);\n";
6805         pr "      return -1;\n";
6806         pr "    }\n"
6807       in
6808       List.iter (generate_test_command_call test_name) seq;
6809       generate_test_command_call ~test test_name last
6810   | TestOutputInt (seq, expected) ->
6811       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6812       let seq, last = get_seq_last seq in
6813       let test () =
6814         pr "    if (r != %d) {\n" expected;
6815         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6816           test_name expected;
6817         pr "               (int) r);\n";
6818         pr "      return -1;\n";
6819         pr "    }\n"
6820       in
6821       List.iter (generate_test_command_call test_name) seq;
6822       generate_test_command_call ~test test_name last
6823   | TestOutputIntOp (seq, op, expected) ->
6824       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6825       let seq, last = get_seq_last seq in
6826       let test () =
6827         pr "    if (! (r %s %d)) {\n" op expected;
6828         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6829           test_name op expected;
6830         pr "               (int) r);\n";
6831         pr "      return -1;\n";
6832         pr "    }\n"
6833       in
6834       List.iter (generate_test_command_call test_name) seq;
6835       generate_test_command_call ~test test_name last
6836   | TestOutputTrue seq ->
6837       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6838       let seq, last = get_seq_last seq in
6839       let test () =
6840         pr "    if (!r) {\n";
6841         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6842           test_name;
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   | TestOutputFalse seq ->
6849       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6850       let seq, last = get_seq_last seq in
6851       let test () =
6852         pr "    if (r) {\n";
6853         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6854           test_name;
6855         pr "      return -1;\n";
6856         pr "    }\n"
6857       in
6858       List.iter (generate_test_command_call test_name) seq;
6859       generate_test_command_call ~test test_name last
6860   | TestOutputLength (seq, expected) ->
6861       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6862       let seq, last = get_seq_last seq in
6863       let test () =
6864         pr "    int j;\n";
6865         pr "    for (j = 0; j < %d; ++j)\n" expected;
6866         pr "      if (r[j] == NULL) {\n";
6867         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6868           test_name;
6869         pr "        print_strings (r);\n";
6870         pr "        return -1;\n";
6871         pr "      }\n";
6872         pr "    if (r[j] != NULL) {\n";
6873         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6874           test_name;
6875         pr "      print_strings (r);\n";
6876         pr "      return -1;\n";
6877         pr "    }\n"
6878       in
6879       List.iter (generate_test_command_call test_name) seq;
6880       generate_test_command_call ~test test_name last
6881   | TestOutputBuffer (seq, expected) ->
6882       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6883       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6884       let seq, last = get_seq_last seq in
6885       let len = String.length expected in
6886       let test () =
6887         pr "    if (size != %d) {\n" len;
6888         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6889         pr "      return -1;\n";
6890         pr "    }\n";
6891         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6892         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6893         pr "      return -1;\n";
6894         pr "    }\n"
6895       in
6896       List.iter (generate_test_command_call test_name) seq;
6897       generate_test_command_call ~test test_name last
6898   | TestOutputStruct (seq, checks) ->
6899       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6900       let seq, last = get_seq_last seq in
6901       let test () =
6902         List.iter (
6903           function
6904           | CompareWithInt (field, expected) ->
6905               pr "    if (r->%s != %d) {\n" field expected;
6906               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6907                 test_name field expected;
6908               pr "               (int) r->%s);\n" field;
6909               pr "      return -1;\n";
6910               pr "    }\n"
6911           | CompareWithIntOp (field, op, expected) ->
6912               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6913               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6914                 test_name field op expected;
6915               pr "               (int) r->%s);\n" field;
6916               pr "      return -1;\n";
6917               pr "    }\n"
6918           | CompareWithString (field, expected) ->
6919               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6920               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6921                 test_name field expected;
6922               pr "               r->%s);\n" field;
6923               pr "      return -1;\n";
6924               pr "    }\n"
6925           | CompareFieldsIntEq (field1, field2) ->
6926               pr "    if (r->%s != r->%s) {\n" field1 field2;
6927               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6928                 test_name field1 field2;
6929               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6930               pr "      return -1;\n";
6931               pr "    }\n"
6932           | CompareFieldsStrEq (field1, field2) ->
6933               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6934               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6935                 test_name field1 field2;
6936               pr "               r->%s, r->%s);\n" field1 field2;
6937               pr "      return -1;\n";
6938               pr "    }\n"
6939         ) checks
6940       in
6941       List.iter (generate_test_command_call test_name) seq;
6942       generate_test_command_call ~test test_name last
6943   | TestLastFail seq ->
6944       pr "  /* TestLastFail for %s (%d) */\n" name i;
6945       let seq, last = get_seq_last seq in
6946       List.iter (generate_test_command_call test_name) seq;
6947       generate_test_command_call test_name ~expect_error:true last
6948
6949 (* Generate the code to run a command, leaving the result in 'r'.
6950  * If you expect to get an error then you should set expect_error:true.
6951  *)
6952 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6953   match cmd with
6954   | [] -> assert false
6955   | name :: args ->
6956       (* Look up the command to find out what args/ret it has. *)
6957       let style =
6958         try
6959           let _, style, _, _, _, _, _ =
6960             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6961           style
6962         with Not_found ->
6963           failwithf "%s: in test, command %s was not found" test_name name in
6964
6965       if List.length (snd style) <> List.length args then
6966         failwithf "%s: in test, wrong number of args given to %s"
6967           test_name name;
6968
6969       pr "  {\n";
6970
6971       List.iter (
6972         function
6973         | OptString n, "NULL" -> ()
6974         | Pathname n, arg
6975         | Device n, arg
6976         | Dev_or_Path n, arg
6977         | String n, arg
6978         | OptString n, arg ->
6979             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6980         | Int _, _
6981         | Int64 _, _
6982         | Bool _, _
6983         | FileIn _, _ | FileOut _, _ -> ()
6984         | StringList n, "" | DeviceList n, "" ->
6985             pr "    const char *const %s[1] = { NULL };\n" n
6986         | StringList n, arg | DeviceList n, arg ->
6987             let strs = string_split " " arg in
6988             iteri (
6989               fun i str ->
6990                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6991             ) strs;
6992             pr "    const char *const %s[] = {\n" n;
6993             iteri (
6994               fun i _ -> pr "      %s_%d,\n" n i
6995             ) strs;
6996             pr "      NULL\n";
6997             pr "    };\n";
6998       ) (List.combine (snd style) args);
6999
7000       let error_code =
7001         match fst style with
7002         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7003         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7004         | RConstString _ | RConstOptString _ ->
7005             pr "    const char *r;\n"; "NULL"
7006         | RString _ -> pr "    char *r;\n"; "NULL"
7007         | RStringList _ | RHashtable _ ->
7008             pr "    char **r;\n";
7009             pr "    int i;\n";
7010             "NULL"
7011         | RStruct (_, typ) ->
7012             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7013         | RStructList (_, typ) ->
7014             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7015         | RBufferOut _ ->
7016             pr "    char *r;\n";
7017             pr "    size_t size;\n";
7018             "NULL" in
7019
7020       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7021       pr "    r = guestfs_%s (g" name;
7022
7023       (* Generate the parameters. *)
7024       List.iter (
7025         function
7026         | OptString _, "NULL" -> pr ", NULL"
7027         | Pathname n, _
7028         | Device n, _ | Dev_or_Path n, _
7029         | String n, _
7030         | OptString n, _ ->
7031             pr ", %s" n
7032         | FileIn _, arg | FileOut _, arg ->
7033             pr ", \"%s\"" (c_quote arg)
7034         | StringList n, _ | DeviceList n, _ ->
7035             pr ", (char **) %s" n
7036         | Int _, arg ->
7037             let i =
7038               try int_of_string arg
7039               with Failure "int_of_string" ->
7040                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7041             pr ", %d" i
7042         | Int64 _, arg ->
7043             let i =
7044               try Int64.of_string arg
7045               with Failure "int_of_string" ->
7046                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7047             pr ", %Ld" i
7048         | Bool _, arg ->
7049             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7050       ) (List.combine (snd style) args);
7051
7052       (match fst style with
7053        | RBufferOut _ -> pr ", &size"
7054        | _ -> ()
7055       );
7056
7057       pr ");\n";
7058
7059       if not expect_error then
7060         pr "    if (r == %s)\n" error_code
7061       else
7062         pr "    if (r != %s)\n" error_code;
7063       pr "      return -1;\n";
7064
7065       (* Insert the test code. *)
7066       (match test with
7067        | None -> ()
7068        | Some f -> f ()
7069       );
7070
7071       (match fst style with
7072        | RErr | RInt _ | RInt64 _ | RBool _
7073        | RConstString _ | RConstOptString _ -> ()
7074        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7075        | RStringList _ | RHashtable _ ->
7076            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7077            pr "      free (r[i]);\n";
7078            pr "    free (r);\n"
7079        | RStruct (_, typ) ->
7080            pr "    guestfs_free_%s (r);\n" typ
7081        | RStructList (_, typ) ->
7082            pr "    guestfs_free_%s_list (r);\n" typ
7083       );
7084
7085       pr "  }\n"
7086
7087 and c_quote str =
7088   let str = replace_str str "\r" "\\r" in
7089   let str = replace_str str "\n" "\\n" in
7090   let str = replace_str str "\t" "\\t" in
7091   let str = replace_str str "\000" "\\0" in
7092   str
7093
7094 (* Generate a lot of different functions for guestfish. *)
7095 and generate_fish_cmds () =
7096   generate_header CStyle GPLv2plus;
7097
7098   let all_functions =
7099     List.filter (
7100       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7101     ) all_functions in
7102   let all_functions_sorted =
7103     List.filter (
7104       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7105     ) all_functions_sorted in
7106
7107   pr "#include <config.h>\n";
7108   pr "\n";
7109   pr "#include <stdio.h>\n";
7110   pr "#include <stdlib.h>\n";
7111   pr "#include <string.h>\n";
7112   pr "#include <inttypes.h>\n";
7113   pr "\n";
7114   pr "#include <guestfs.h>\n";
7115   pr "#include \"c-ctype.h\"\n";
7116   pr "#include \"full-write.h\"\n";
7117   pr "#include \"xstrtol.h\"\n";
7118   pr "#include \"fish.h\"\n";
7119   pr "\n";
7120
7121   (* list_commands function, which implements guestfish -h *)
7122   pr "void list_commands (void)\n";
7123   pr "{\n";
7124   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7125   pr "  list_builtin_commands ();\n";
7126   List.iter (
7127     fun (name, _, _, flags, _, shortdesc, _) ->
7128       let name = replace_char name '_' '-' in
7129       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7130         name shortdesc
7131   ) all_functions_sorted;
7132   pr "  printf (\"    %%s\\n\",";
7133   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7134   pr "}\n";
7135   pr "\n";
7136
7137   (* display_command function, which implements guestfish -h cmd *)
7138   pr "void display_command (const char *cmd)\n";
7139   pr "{\n";
7140   List.iter (
7141     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7142       let name2 = replace_char name '_' '-' in
7143       let alias =
7144         try find_map (function FishAlias n -> Some n | _ -> None) flags
7145         with Not_found -> name in
7146       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7147       let synopsis =
7148         match snd style with
7149         | [] -> name2
7150         | args ->
7151             sprintf "%s %s"
7152               name2 (String.concat " " (List.map name_of_argt args)) in
7153
7154       let warnings =
7155         if List.mem ProtocolLimitWarning flags then
7156           ("\n\n" ^ protocol_limit_warning)
7157         else "" in
7158
7159       (* For DangerWillRobinson commands, we should probably have
7160        * guestfish prompt before allowing you to use them (especially
7161        * in interactive mode). XXX
7162        *)
7163       let warnings =
7164         warnings ^
7165           if List.mem DangerWillRobinson flags then
7166             ("\n\n" ^ danger_will_robinson)
7167           else "" in
7168
7169       let warnings =
7170         warnings ^
7171           match deprecation_notice flags with
7172           | None -> ""
7173           | Some txt -> "\n\n" ^ txt in
7174
7175       let describe_alias =
7176         if name <> alias then
7177           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7178         else "" in
7179
7180       pr "  if (";
7181       pr "STRCASEEQ (cmd, \"%s\")" name;
7182       if name <> name2 then
7183         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7184       if name <> alias then
7185         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7186       pr ")\n";
7187       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7188         name2 shortdesc
7189         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7190          "=head1 DESCRIPTION\n\n" ^
7191          longdesc ^ warnings ^ describe_alias);
7192       pr "  else\n"
7193   ) all_functions;
7194   pr "    display_builtin_command (cmd);\n";
7195   pr "}\n";
7196   pr "\n";
7197
7198   let emit_print_list_function typ =
7199     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7200       typ typ typ;
7201     pr "{\n";
7202     pr "  unsigned int i;\n";
7203     pr "\n";
7204     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7205     pr "    printf (\"[%%d] = {\\n\", i);\n";
7206     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7207     pr "    printf (\"}\\n\");\n";
7208     pr "  }\n";
7209     pr "}\n";
7210     pr "\n";
7211   in
7212
7213   (* print_* functions *)
7214   List.iter (
7215     fun (typ, cols) ->
7216       let needs_i =
7217         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7218
7219       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7220       pr "{\n";
7221       if needs_i then (
7222         pr "  unsigned int i;\n";
7223         pr "\n"
7224       );
7225       List.iter (
7226         function
7227         | name, FString ->
7228             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7229         | name, FUUID ->
7230             pr "  printf (\"%%s%s: \", indent);\n" name;
7231             pr "  for (i = 0; i < 32; ++i)\n";
7232             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7233             pr "  printf (\"\\n\");\n"
7234         | name, FBuffer ->
7235             pr "  printf (\"%%s%s: \", indent);\n" name;
7236             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7237             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7238             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7239             pr "    else\n";
7240             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7241             pr "  printf (\"\\n\");\n"
7242         | name, (FUInt64|FBytes) ->
7243             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7244               name typ name
7245         | name, FInt64 ->
7246             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7247               name typ name
7248         | name, FUInt32 ->
7249             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7250               name typ name
7251         | name, FInt32 ->
7252             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7253               name typ name
7254         | name, FChar ->
7255             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7256               name typ name
7257         | name, FOptPercent ->
7258             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7259               typ name name typ name;
7260             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7261       ) cols;
7262       pr "}\n";
7263       pr "\n";
7264   ) structs;
7265
7266   (* Emit a print_TYPE_list function definition only if that function is used. *)
7267   List.iter (
7268     function
7269     | typ, (RStructListOnly | RStructAndList) ->
7270         (* generate the function for typ *)
7271         emit_print_list_function typ
7272     | typ, _ -> () (* empty *)
7273   ) (rstructs_used_by all_functions);
7274
7275   (* Emit a print_TYPE function definition only if that function is used. *)
7276   List.iter (
7277     function
7278     | typ, (RStructOnly | RStructAndList) ->
7279         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7280         pr "{\n";
7281         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7282         pr "}\n";
7283         pr "\n";
7284     | typ, _ -> () (* empty *)
7285   ) (rstructs_used_by all_functions);
7286
7287   (* run_<action> actions *)
7288   List.iter (
7289     fun (name, style, _, flags, _, _, _) ->
7290       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7291       pr "{\n";
7292       (match fst style with
7293        | RErr
7294        | RInt _
7295        | RBool _ -> pr "  int r;\n"
7296        | RInt64 _ -> pr "  int64_t r;\n"
7297        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7298        | RString _ -> pr "  char *r;\n"
7299        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7300        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7301        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7302        | RBufferOut _ ->
7303            pr "  char *r;\n";
7304            pr "  size_t size;\n";
7305       );
7306       List.iter (
7307         function
7308         | Device n
7309         | String n
7310         | OptString n
7311         | FileIn n
7312         | FileOut n -> pr "  const char *%s;\n" n
7313         | Pathname n
7314         | Dev_or_Path n -> pr "  char *%s;\n" n
7315         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7316         | Bool n -> pr "  int %s;\n" n
7317         | Int n -> pr "  int %s;\n" n
7318         | Int64 n -> pr "  int64_t %s;\n" n
7319       ) (snd style);
7320
7321       (* Check and convert parameters. *)
7322       let argc_expected = List.length (snd style) in
7323       pr "  if (argc != %d) {\n" argc_expected;
7324       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7325         argc_expected;
7326       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7327       pr "    return -1;\n";
7328       pr "  }\n";
7329
7330       let parse_integer fn fntyp rtyp range name i =
7331         pr "  {\n";
7332         pr "    strtol_error xerr;\n";
7333         pr "    %s r;\n" fntyp;
7334         pr "\n";
7335         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7336         pr "    if (xerr != LONGINT_OK) {\n";
7337         pr "      fprintf (stderr,\n";
7338         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7339         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7340         pr "      return -1;\n";
7341         pr "    }\n";
7342         (match range with
7343          | None -> ()
7344          | Some (min, max, comment) ->
7345              pr "    /* %s */\n" comment;
7346              pr "    if (r < %s || r > %s) {\n" min max;
7347              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7348                name;
7349              pr "      return -1;\n";
7350              pr "    }\n";
7351              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7352         );
7353         pr "    %s = r;\n" name;
7354         pr "  }\n";
7355       in
7356
7357       iteri (
7358         fun i ->
7359           function
7360           | Device name
7361           | String name ->
7362               pr "  %s = argv[%d];\n" name i
7363           | Pathname name
7364           | Dev_or_Path name ->
7365               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7366               pr "  if (%s == NULL) return -1;\n" name
7367           | OptString name ->
7368               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7369                 name i i
7370           | FileIn name ->
7371               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7372                 name i i
7373           | FileOut name ->
7374               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7375                 name i i
7376           | StringList name | DeviceList name ->
7377               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7378               pr "  if (%s == NULL) return -1;\n" name;
7379           | Bool name ->
7380               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7381           | Int name ->
7382               let range =
7383                 let min = "(-(2LL<<30))"
7384                 and max = "((2LL<<30)-1)"
7385                 and comment =
7386                   "The Int type in the generator is a signed 31 bit int." in
7387                 Some (min, max, comment) in
7388               parse_integer "xstrtoll" "long long" "int" range name i
7389           | Int64 name ->
7390               parse_integer "xstrtoll" "long long" "int64_t" None name i
7391       ) (snd style);
7392
7393       (* Call C API function. *)
7394       let fn =
7395         try find_map (function FishAction n -> Some n | _ -> None) flags
7396         with Not_found -> sprintf "guestfs_%s" name in
7397       pr "  r = %s " fn;
7398       generate_c_call_args ~handle:"g" style;
7399       pr ";\n";
7400
7401       List.iter (
7402         function
7403         | Device name | String name
7404         | OptString name | FileIn name | FileOut name | Bool name
7405         | Int name | Int64 name -> ()
7406         | Pathname name | Dev_or_Path name ->
7407             pr "  free (%s);\n" name
7408         | StringList name | DeviceList name ->
7409             pr "  free_strings (%s);\n" name
7410       ) (snd style);
7411
7412       (* Check return value for errors and display command results. *)
7413       (match fst style with
7414        | RErr -> pr "  return r;\n"
7415        | RInt _ ->
7416            pr "  if (r == -1) return -1;\n";
7417            pr "  printf (\"%%d\\n\", r);\n";
7418            pr "  return 0;\n"
7419        | RInt64 _ ->
7420            pr "  if (r == -1) return -1;\n";
7421            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7422            pr "  return 0;\n"
7423        | RBool _ ->
7424            pr "  if (r == -1) return -1;\n";
7425            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7426            pr "  return 0;\n"
7427        | RConstString _ ->
7428            pr "  if (r == NULL) return -1;\n";
7429            pr "  printf (\"%%s\\n\", r);\n";
7430            pr "  return 0;\n"
7431        | RConstOptString _ ->
7432            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7433            pr "  return 0;\n"
7434        | RString _ ->
7435            pr "  if (r == NULL) return -1;\n";
7436            pr "  printf (\"%%s\\n\", r);\n";
7437            pr "  free (r);\n";
7438            pr "  return 0;\n"
7439        | RStringList _ ->
7440            pr "  if (r == NULL) return -1;\n";
7441            pr "  print_strings (r);\n";
7442            pr "  free_strings (r);\n";
7443            pr "  return 0;\n"
7444        | RStruct (_, typ) ->
7445            pr "  if (r == NULL) return -1;\n";
7446            pr "  print_%s (r);\n" typ;
7447            pr "  guestfs_free_%s (r);\n" typ;
7448            pr "  return 0;\n"
7449        | RStructList (_, typ) ->
7450            pr "  if (r == NULL) return -1;\n";
7451            pr "  print_%s_list (r);\n" typ;
7452            pr "  guestfs_free_%s_list (r);\n" typ;
7453            pr "  return 0;\n"
7454        | RHashtable _ ->
7455            pr "  if (r == NULL) return -1;\n";
7456            pr "  print_table (r);\n";
7457            pr "  free_strings (r);\n";
7458            pr "  return 0;\n"
7459        | RBufferOut _ ->
7460            pr "  if (r == NULL) return -1;\n";
7461            pr "  if (full_write (1, r, size) != size) {\n";
7462            pr "    perror (\"write\");\n";
7463            pr "    free (r);\n";
7464            pr "    return -1;\n";
7465            pr "  }\n";
7466            pr "  free (r);\n";
7467            pr "  return 0;\n"
7468       );
7469       pr "}\n";
7470       pr "\n"
7471   ) all_functions;
7472
7473   (* run_action function *)
7474   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7475   pr "{\n";
7476   List.iter (
7477     fun (name, _, _, flags, _, _, _) ->
7478       let name2 = replace_char name '_' '-' in
7479       let alias =
7480         try find_map (function FishAlias n -> Some n | _ -> None) flags
7481         with Not_found -> name in
7482       pr "  if (";
7483       pr "STRCASEEQ (cmd, \"%s\")" name;
7484       if name <> name2 then
7485         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7486       if name <> alias then
7487         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7488       pr ")\n";
7489       pr "    return run_%s (cmd, argc, argv);\n" name;
7490       pr "  else\n";
7491   ) all_functions;
7492   pr "    {\n";
7493   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7494   pr "      if (command_num == 1)\n";
7495   pr "        extended_help_message ();\n";
7496   pr "      return -1;\n";
7497   pr "    }\n";
7498   pr "  return 0;\n";
7499   pr "}\n";
7500   pr "\n"
7501
7502 (* Readline completion for guestfish. *)
7503 and generate_fish_completion () =
7504   generate_header CStyle GPLv2plus;
7505
7506   let all_functions =
7507     List.filter (
7508       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7509     ) all_functions in
7510
7511   pr "\
7512 #include <config.h>
7513
7514 #include <stdio.h>
7515 #include <stdlib.h>
7516 #include <string.h>
7517
7518 #ifdef HAVE_LIBREADLINE
7519 #include <readline/readline.h>
7520 #endif
7521
7522 #include \"fish.h\"
7523
7524 #ifdef HAVE_LIBREADLINE
7525
7526 static const char *const commands[] = {
7527   BUILTIN_COMMANDS_FOR_COMPLETION,
7528 ";
7529
7530   (* Get the commands, including the aliases.  They don't need to be
7531    * sorted - the generator() function just does a dumb linear search.
7532    *)
7533   let commands =
7534     List.map (
7535       fun (name, _, _, flags, _, _, _) ->
7536         let name2 = replace_char name '_' '-' in
7537         let alias =
7538           try find_map (function FishAlias n -> Some n | _ -> None) flags
7539           with Not_found -> name in
7540
7541         if name <> alias then [name2; alias] else [name2]
7542     ) all_functions in
7543   let commands = List.flatten commands in
7544
7545   List.iter (pr "  \"%s\",\n") commands;
7546
7547   pr "  NULL
7548 };
7549
7550 static char *
7551 generator (const char *text, int state)
7552 {
7553   static int index, len;
7554   const char *name;
7555
7556   if (!state) {
7557     index = 0;
7558     len = strlen (text);
7559   }
7560
7561   rl_attempted_completion_over = 1;
7562
7563   while ((name = commands[index]) != NULL) {
7564     index++;
7565     if (STRCASEEQLEN (name, text, len))
7566       return strdup (name);
7567   }
7568
7569   return NULL;
7570 }
7571
7572 #endif /* HAVE_LIBREADLINE */
7573
7574 #ifdef HAVE_RL_COMPLETION_MATCHES
7575 #define RL_COMPLETION_MATCHES rl_completion_matches
7576 #else
7577 #ifdef HAVE_COMPLETION_MATCHES
7578 #define RL_COMPLETION_MATCHES completion_matches
7579 #endif
7580 #endif /* else just fail if we don't have either symbol */
7581
7582 char **
7583 do_completion (const char *text, int start, int end)
7584 {
7585   char **matches = NULL;
7586
7587 #ifdef HAVE_LIBREADLINE
7588   rl_completion_append_character = ' ';
7589
7590   if (start == 0)
7591     matches = RL_COMPLETION_MATCHES (text, generator);
7592   else if (complete_dest_paths)
7593     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7594 #endif
7595
7596   return matches;
7597 }
7598 ";
7599
7600 (* Generate the POD documentation for guestfish. *)
7601 and generate_fish_actions_pod () =
7602   let all_functions_sorted =
7603     List.filter (
7604       fun (_, _, _, flags, _, _, _) ->
7605         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7606     ) all_functions_sorted in
7607
7608   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7609
7610   List.iter (
7611     fun (name, style, _, flags, _, _, longdesc) ->
7612       let longdesc =
7613         Str.global_substitute rex (
7614           fun s ->
7615             let sub =
7616               try Str.matched_group 1 s
7617               with Not_found ->
7618                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7619             "C<" ^ replace_char sub '_' '-' ^ ">"
7620         ) longdesc in
7621       let name = replace_char name '_' '-' in
7622       let alias =
7623         try find_map (function FishAlias n -> Some n | _ -> None) flags
7624         with Not_found -> name in
7625
7626       pr "=head2 %s" name;
7627       if name <> alias then
7628         pr " | %s" alias;
7629       pr "\n";
7630       pr "\n";
7631       pr " %s" name;
7632       List.iter (
7633         function
7634         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7635         | OptString n -> pr " %s" n
7636         | StringList n | DeviceList n -> pr " '%s ...'" n
7637         | Bool _ -> pr " true|false"
7638         | Int n -> pr " %s" n
7639         | Int64 n -> pr " %s" n
7640         | FileIn n | FileOut n -> pr " (%s|-)" n
7641       ) (snd style);
7642       pr "\n";
7643       pr "\n";
7644       pr "%s\n\n" longdesc;
7645
7646       if List.exists (function FileIn _ | FileOut _ -> true
7647                       | _ -> false) (snd style) then
7648         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7649
7650       if List.mem ProtocolLimitWarning flags then
7651         pr "%s\n\n" protocol_limit_warning;
7652
7653       if List.mem DangerWillRobinson flags then
7654         pr "%s\n\n" danger_will_robinson;
7655
7656       match deprecation_notice flags with
7657       | None -> ()
7658       | Some txt -> pr "%s\n\n" txt
7659   ) all_functions_sorted
7660
7661 (* Generate a C function prototype. *)
7662 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7663     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7664     ?(prefix = "")
7665     ?handle name style =
7666   if extern then pr "extern ";
7667   if static then pr "static ";
7668   (match fst style with
7669    | RErr -> pr "int "
7670    | RInt _ -> pr "int "
7671    | RInt64 _ -> pr "int64_t "
7672    | RBool _ -> pr "int "
7673    | RConstString _ | RConstOptString _ -> pr "const char *"
7674    | RString _ | RBufferOut _ -> pr "char *"
7675    | RStringList _ | RHashtable _ -> pr "char **"
7676    | RStruct (_, typ) ->
7677        if not in_daemon then pr "struct guestfs_%s *" typ
7678        else pr "guestfs_int_%s *" typ
7679    | RStructList (_, typ) ->
7680        if not in_daemon then pr "struct guestfs_%s_list *" typ
7681        else pr "guestfs_int_%s_list *" typ
7682   );
7683   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7684   pr "%s%s (" prefix name;
7685   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7686     pr "void"
7687   else (
7688     let comma = ref false in
7689     (match handle with
7690      | None -> ()
7691      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7692     );
7693     let next () =
7694       if !comma then (
7695         if single_line then pr ", " else pr ",\n\t\t"
7696       );
7697       comma := true
7698     in
7699     List.iter (
7700       function
7701       | Pathname n
7702       | Device n | Dev_or_Path n
7703       | String n
7704       | OptString n ->
7705           next ();
7706           pr "const char *%s" n
7707       | StringList n | DeviceList n ->
7708           next ();
7709           pr "char *const *%s" n
7710       | Bool n -> next (); pr "int %s" n
7711       | Int n -> next (); pr "int %s" n
7712       | Int64 n -> next (); pr "int64_t %s" n
7713       | FileIn n
7714       | FileOut n ->
7715           if not in_daemon then (next (); pr "const char *%s" n)
7716     ) (snd style);
7717     if is_RBufferOut then (next (); pr "size_t *size_r");
7718   );
7719   pr ")";
7720   if semicolon then pr ";";
7721   if newline then pr "\n"
7722
7723 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7724 and generate_c_call_args ?handle ?(decl = false) style =
7725   pr "(";
7726   let comma = ref false in
7727   let next () =
7728     if !comma then pr ", ";
7729     comma := true
7730   in
7731   (match handle with
7732    | None -> ()
7733    | Some handle -> pr "%s" handle; comma := true
7734   );
7735   List.iter (
7736     fun arg ->
7737       next ();
7738       pr "%s" (name_of_argt arg)
7739   ) (snd style);
7740   (* For RBufferOut calls, add implicit &size parameter. *)
7741   if not decl then (
7742     match fst style with
7743     | RBufferOut _ ->
7744         next ();
7745         pr "&size"
7746     | _ -> ()
7747   );
7748   pr ")"
7749
7750 (* Generate the OCaml bindings interface. *)
7751 and generate_ocaml_mli () =
7752   generate_header OCamlStyle LGPLv2plus;
7753
7754   pr "\
7755 (** For API documentation you should refer to the C API
7756     in the guestfs(3) manual page.  The OCaml API uses almost
7757     exactly the same calls. *)
7758
7759 type t
7760 (** A [guestfs_h] handle. *)
7761
7762 exception Error of string
7763 (** This exception is raised when there is an error. *)
7764
7765 exception Handle_closed of string
7766 (** This exception is raised if you use a {!Guestfs.t} handle
7767     after calling {!close} on it.  The string is the name of
7768     the function. *)
7769
7770 val create : unit -> t
7771 (** Create a {!Guestfs.t} handle. *)
7772
7773 val close : t -> unit
7774 (** Close the {!Guestfs.t} handle and free up all resources used
7775     by it immediately.
7776
7777     Handles are closed by the garbage collector when they become
7778     unreferenced, but callers can call this in order to provide
7779     predictable cleanup. *)
7780
7781 ";
7782   generate_ocaml_structure_decls ();
7783
7784   (* The actions. *)
7785   List.iter (
7786     fun (name, style, _, _, _, shortdesc, _) ->
7787       generate_ocaml_prototype name style;
7788       pr "(** %s *)\n" shortdesc;
7789       pr "\n"
7790   ) all_functions_sorted
7791
7792 (* Generate the OCaml bindings implementation. *)
7793 and generate_ocaml_ml () =
7794   generate_header OCamlStyle LGPLv2plus;
7795
7796   pr "\
7797 type t
7798
7799 exception Error of string
7800 exception Handle_closed of string
7801
7802 external create : unit -> t = \"ocaml_guestfs_create\"
7803 external close : t -> unit = \"ocaml_guestfs_close\"
7804
7805 (* Give the exceptions names, so they can be raised from the C code. *)
7806 let () =
7807   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7808   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7809
7810 ";
7811
7812   generate_ocaml_structure_decls ();
7813
7814   (* The actions. *)
7815   List.iter (
7816     fun (name, style, _, _, _, shortdesc, _) ->
7817       generate_ocaml_prototype ~is_external:true name style;
7818   ) all_functions_sorted
7819
7820 (* Generate the OCaml bindings C implementation. *)
7821 and generate_ocaml_c () =
7822   generate_header CStyle LGPLv2plus;
7823
7824   pr "\
7825 #include <stdio.h>
7826 #include <stdlib.h>
7827 #include <string.h>
7828
7829 #include <caml/config.h>
7830 #include <caml/alloc.h>
7831 #include <caml/callback.h>
7832 #include <caml/fail.h>
7833 #include <caml/memory.h>
7834 #include <caml/mlvalues.h>
7835 #include <caml/signals.h>
7836
7837 #include <guestfs.h>
7838
7839 #include \"guestfs_c.h\"
7840
7841 /* Copy a hashtable of string pairs into an assoc-list.  We return
7842  * the list in reverse order, but hashtables aren't supposed to be
7843  * ordered anyway.
7844  */
7845 static CAMLprim value
7846 copy_table (char * const * argv)
7847 {
7848   CAMLparam0 ();
7849   CAMLlocal5 (rv, pairv, kv, vv, cons);
7850   int i;
7851
7852   rv = Val_int (0);
7853   for (i = 0; argv[i] != NULL; i += 2) {
7854     kv = caml_copy_string (argv[i]);
7855     vv = caml_copy_string (argv[i+1]);
7856     pairv = caml_alloc (2, 0);
7857     Store_field (pairv, 0, kv);
7858     Store_field (pairv, 1, vv);
7859     cons = caml_alloc (2, 0);
7860     Store_field (cons, 1, rv);
7861     rv = cons;
7862     Store_field (cons, 0, pairv);
7863   }
7864
7865   CAMLreturn (rv);
7866 }
7867
7868 ";
7869
7870   (* Struct copy functions. *)
7871
7872   let emit_ocaml_copy_list_function typ =
7873     pr "static CAMLprim value\n";
7874     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7875     pr "{\n";
7876     pr "  CAMLparam0 ();\n";
7877     pr "  CAMLlocal2 (rv, v);\n";
7878     pr "  unsigned int i;\n";
7879     pr "\n";
7880     pr "  if (%ss->len == 0)\n" typ;
7881     pr "    CAMLreturn (Atom (0));\n";
7882     pr "  else {\n";
7883     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7884     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7885     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7886     pr "      caml_modify (&Field (rv, i), v);\n";
7887     pr "    }\n";
7888     pr "    CAMLreturn (rv);\n";
7889     pr "  }\n";
7890     pr "}\n";
7891     pr "\n";
7892   in
7893
7894   List.iter (
7895     fun (typ, cols) ->
7896       let has_optpercent_col =
7897         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7898
7899       pr "static CAMLprim value\n";
7900       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7901       pr "{\n";
7902       pr "  CAMLparam0 ();\n";
7903       if has_optpercent_col then
7904         pr "  CAMLlocal3 (rv, v, v2);\n"
7905       else
7906         pr "  CAMLlocal2 (rv, v);\n";
7907       pr "\n";
7908       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7909       iteri (
7910         fun i col ->
7911           (match col with
7912            | name, FString ->
7913                pr "  v = caml_copy_string (%s->%s);\n" typ name
7914            | name, FBuffer ->
7915                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7916                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7917                  typ name typ name
7918            | name, FUUID ->
7919                pr "  v = caml_alloc_string (32);\n";
7920                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7921            | name, (FBytes|FInt64|FUInt64) ->
7922                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7923            | name, (FInt32|FUInt32) ->
7924                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7925            | name, FOptPercent ->
7926                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7927                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7928                pr "    v = caml_alloc (1, 0);\n";
7929                pr "    Store_field (v, 0, v2);\n";
7930                pr "  } else /* None */\n";
7931                pr "    v = Val_int (0);\n";
7932            | name, FChar ->
7933                pr "  v = Val_int (%s->%s);\n" typ name
7934           );
7935           pr "  Store_field (rv, %d, v);\n" i
7936       ) cols;
7937       pr "  CAMLreturn (rv);\n";
7938       pr "}\n";
7939       pr "\n";
7940   ) structs;
7941
7942   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7943   List.iter (
7944     function
7945     | typ, (RStructListOnly | RStructAndList) ->
7946         (* generate the function for typ *)
7947         emit_ocaml_copy_list_function typ
7948     | typ, _ -> () (* empty *)
7949   ) (rstructs_used_by all_functions);
7950
7951   (* The wrappers. *)
7952   List.iter (
7953     fun (name, style, _, _, _, _, _) ->
7954       pr "/* Automatically generated wrapper for function\n";
7955       pr " * ";
7956       generate_ocaml_prototype name style;
7957       pr " */\n";
7958       pr "\n";
7959
7960       let params =
7961         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7962
7963       let needs_extra_vs =
7964         match fst style with RConstOptString _ -> true | _ -> false in
7965
7966       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7967       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7968       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7969       pr "\n";
7970
7971       pr "CAMLprim value\n";
7972       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7973       List.iter (pr ", value %s") (List.tl params);
7974       pr ")\n";
7975       pr "{\n";
7976
7977       (match params with
7978        | [p1; p2; p3; p4; p5] ->
7979            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7980        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7981            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7982            pr "  CAMLxparam%d (%s);\n"
7983              (List.length rest) (String.concat ", " rest)
7984        | ps ->
7985            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7986       );
7987       if not needs_extra_vs then
7988         pr "  CAMLlocal1 (rv);\n"
7989       else
7990         pr "  CAMLlocal3 (rv, v, v2);\n";
7991       pr "\n";
7992
7993       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7994       pr "  if (g == NULL)\n";
7995       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7996       pr "\n";
7997
7998       List.iter (
7999         function
8000         | Pathname n
8001         | Device n | Dev_or_Path n
8002         | String n
8003         | FileIn n
8004         | FileOut n ->
8005             pr "  const char *%s = String_val (%sv);\n" n n
8006         | OptString n ->
8007             pr "  const char *%s =\n" n;
8008             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8009               n n
8010         | StringList n | DeviceList n ->
8011             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8012         | Bool n ->
8013             pr "  int %s = Bool_val (%sv);\n" n n
8014         | Int n ->
8015             pr "  int %s = Int_val (%sv);\n" n n
8016         | Int64 n ->
8017             pr "  int64_t %s = Int64_val (%sv);\n" n n
8018       ) (snd style);
8019       let error_code =
8020         match fst style with
8021         | RErr -> pr "  int r;\n"; "-1"
8022         | RInt _ -> pr "  int r;\n"; "-1"
8023         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8024         | RBool _ -> pr "  int r;\n"; "-1"
8025         | RConstString _ | RConstOptString _ ->
8026             pr "  const char *r;\n"; "NULL"
8027         | RString _ -> pr "  char *r;\n"; "NULL"
8028         | RStringList _ ->
8029             pr "  int i;\n";
8030             pr "  char **r;\n";
8031             "NULL"
8032         | RStruct (_, typ) ->
8033             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8034         | RStructList (_, typ) ->
8035             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8036         | RHashtable _ ->
8037             pr "  int i;\n";
8038             pr "  char **r;\n";
8039             "NULL"
8040         | RBufferOut _ ->
8041             pr "  char *r;\n";
8042             pr "  size_t size;\n";
8043             "NULL" in
8044       pr "\n";
8045
8046       pr "  caml_enter_blocking_section ();\n";
8047       pr "  r = guestfs_%s " name;
8048       generate_c_call_args ~handle:"g" style;
8049       pr ";\n";
8050       pr "  caml_leave_blocking_section ();\n";
8051
8052       List.iter (
8053         function
8054         | StringList n | DeviceList n ->
8055             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8056         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8057         | Bool _ | Int _ | Int64 _
8058         | FileIn _ | FileOut _ -> ()
8059       ) (snd style);
8060
8061       pr "  if (r == %s)\n" error_code;
8062       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8063       pr "\n";
8064
8065       (match fst style with
8066        | RErr -> pr "  rv = Val_unit;\n"
8067        | RInt _ -> pr "  rv = Val_int (r);\n"
8068        | RInt64 _ ->
8069            pr "  rv = caml_copy_int64 (r);\n"
8070        | RBool _ -> pr "  rv = Val_bool (r);\n"
8071        | RConstString _ ->
8072            pr "  rv = caml_copy_string (r);\n"
8073        | RConstOptString _ ->
8074            pr "  if (r) { /* Some string */\n";
8075            pr "    v = caml_alloc (1, 0);\n";
8076            pr "    v2 = caml_copy_string (r);\n";
8077            pr "    Store_field (v, 0, v2);\n";
8078            pr "  } else /* None */\n";
8079            pr "    v = Val_int (0);\n";
8080        | RString _ ->
8081            pr "  rv = caml_copy_string (r);\n";
8082            pr "  free (r);\n"
8083        | RStringList _ ->
8084            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8085            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8086            pr "  free (r);\n"
8087        | RStruct (_, typ) ->
8088            pr "  rv = copy_%s (r);\n" typ;
8089            pr "  guestfs_free_%s (r);\n" typ;
8090        | RStructList (_, typ) ->
8091            pr "  rv = copy_%s_list (r);\n" typ;
8092            pr "  guestfs_free_%s_list (r);\n" typ;
8093        | RHashtable _ ->
8094            pr "  rv = copy_table (r);\n";
8095            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8096            pr "  free (r);\n";
8097        | RBufferOut _ ->
8098            pr "  rv = caml_alloc_string (size);\n";
8099            pr "  memcpy (String_val (rv), r, size);\n";
8100       );
8101
8102       pr "  CAMLreturn (rv);\n";
8103       pr "}\n";
8104       pr "\n";
8105
8106       if List.length params > 5 then (
8107         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8108         pr "CAMLprim value ";
8109         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8110         pr "CAMLprim value\n";
8111         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8112         pr "{\n";
8113         pr "  return ocaml_guestfs_%s (argv[0]" name;
8114         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8115         pr ");\n";
8116         pr "}\n";
8117         pr "\n"
8118       )
8119   ) all_functions_sorted
8120
8121 and generate_ocaml_structure_decls () =
8122   List.iter (
8123     fun (typ, cols) ->
8124       pr "type %s = {\n" typ;
8125       List.iter (
8126         function
8127         | name, FString -> pr "  %s : string;\n" name
8128         | name, FBuffer -> pr "  %s : string;\n" name
8129         | name, FUUID -> pr "  %s : string;\n" name
8130         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8131         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8132         | name, FChar -> pr "  %s : char;\n" name
8133         | name, FOptPercent -> pr "  %s : float option;\n" name
8134       ) cols;
8135       pr "}\n";
8136       pr "\n"
8137   ) structs
8138
8139 and generate_ocaml_prototype ?(is_external = false) name style =
8140   if is_external then pr "external " else pr "val ";
8141   pr "%s : t -> " name;
8142   List.iter (
8143     function
8144     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8145     | OptString _ -> pr "string option -> "
8146     | StringList _ | DeviceList _ -> pr "string array -> "
8147     | Bool _ -> pr "bool -> "
8148     | Int _ -> pr "int -> "
8149     | Int64 _ -> pr "int64 -> "
8150   ) (snd style);
8151   (match fst style with
8152    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8153    | RInt _ -> pr "int"
8154    | RInt64 _ -> pr "int64"
8155    | RBool _ -> pr "bool"
8156    | RConstString _ -> pr "string"
8157    | RConstOptString _ -> pr "string option"
8158    | RString _ | RBufferOut _ -> pr "string"
8159    | RStringList _ -> pr "string array"
8160    | RStruct (_, typ) -> pr "%s" typ
8161    | RStructList (_, typ) -> pr "%s array" typ
8162    | RHashtable _ -> pr "(string * string) list"
8163   );
8164   if is_external then (
8165     pr " = ";
8166     if List.length (snd style) + 1 > 5 then
8167       pr "\"ocaml_guestfs_%s_byte\" " name;
8168     pr "\"ocaml_guestfs_%s\"" name
8169   );
8170   pr "\n"
8171
8172 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8173 and generate_perl_xs () =
8174   generate_header CStyle LGPLv2plus;
8175
8176   pr "\
8177 #include \"EXTERN.h\"
8178 #include \"perl.h\"
8179 #include \"XSUB.h\"
8180
8181 #include <guestfs.h>
8182
8183 #ifndef PRId64
8184 #define PRId64 \"lld\"
8185 #endif
8186
8187 static SV *
8188 my_newSVll(long long val) {
8189 #ifdef USE_64_BIT_ALL
8190   return newSViv(val);
8191 #else
8192   char buf[100];
8193   int len;
8194   len = snprintf(buf, 100, \"%%\" PRId64, val);
8195   return newSVpv(buf, len);
8196 #endif
8197 }
8198
8199 #ifndef PRIu64
8200 #define PRIu64 \"llu\"
8201 #endif
8202
8203 static SV *
8204 my_newSVull(unsigned long long val) {
8205 #ifdef USE_64_BIT_ALL
8206   return newSVuv(val);
8207 #else
8208   char buf[100];
8209   int len;
8210   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8211   return newSVpv(buf, len);
8212 #endif
8213 }
8214
8215 /* http://www.perlmonks.org/?node_id=680842 */
8216 static char **
8217 XS_unpack_charPtrPtr (SV *arg) {
8218   char **ret;
8219   AV *av;
8220   I32 i;
8221
8222   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8223     croak (\"array reference expected\");
8224
8225   av = (AV *)SvRV (arg);
8226   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8227   if (!ret)
8228     croak (\"malloc failed\");
8229
8230   for (i = 0; i <= av_len (av); i++) {
8231     SV **elem = av_fetch (av, i, 0);
8232
8233     if (!elem || !*elem)
8234       croak (\"missing element in list\");
8235
8236     ret[i] = SvPV_nolen (*elem);
8237   }
8238
8239   ret[i] = NULL;
8240
8241   return ret;
8242 }
8243
8244 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8245
8246 PROTOTYPES: ENABLE
8247
8248 guestfs_h *
8249 _create ()
8250    CODE:
8251       RETVAL = guestfs_create ();
8252       if (!RETVAL)
8253         croak (\"could not create guestfs handle\");
8254       guestfs_set_error_handler (RETVAL, NULL, NULL);
8255  OUTPUT:
8256       RETVAL
8257
8258 void
8259 DESTROY (g)
8260       guestfs_h *g;
8261  PPCODE:
8262       guestfs_close (g);
8263
8264 ";
8265
8266   List.iter (
8267     fun (name, style, _, _, _, _, _) ->
8268       (match fst style with
8269        | RErr -> pr "void\n"
8270        | RInt _ -> pr "SV *\n"
8271        | RInt64 _ -> pr "SV *\n"
8272        | RBool _ -> pr "SV *\n"
8273        | RConstString _ -> pr "SV *\n"
8274        | RConstOptString _ -> pr "SV *\n"
8275        | RString _ -> pr "SV *\n"
8276        | RBufferOut _ -> pr "SV *\n"
8277        | RStringList _
8278        | RStruct _ | RStructList _
8279        | RHashtable _ ->
8280            pr "void\n" (* all lists returned implictly on the stack *)
8281       );
8282       (* Call and arguments. *)
8283       pr "%s " name;
8284       generate_c_call_args ~handle:"g" ~decl:true style;
8285       pr "\n";
8286       pr "      guestfs_h *g;\n";
8287       iteri (
8288         fun i ->
8289           function
8290           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8291               pr "      char *%s;\n" n
8292           | OptString n ->
8293               (* http://www.perlmonks.org/?node_id=554277
8294                * Note that the implicit handle argument means we have
8295                * to add 1 to the ST(x) operator.
8296                *)
8297               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8298           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8299           | Bool n -> pr "      int %s;\n" n
8300           | Int n -> pr "      int %s;\n" n
8301           | Int64 n -> pr "      int64_t %s;\n" n
8302       ) (snd style);
8303
8304       let do_cleanups () =
8305         List.iter (
8306           function
8307           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8308           | Bool _ | Int _ | Int64 _
8309           | FileIn _ | FileOut _ -> ()
8310           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8311         ) (snd style)
8312       in
8313
8314       (* Code. *)
8315       (match fst style with
8316        | RErr ->
8317            pr "PREINIT:\n";
8318            pr "      int r;\n";
8319            pr " PPCODE:\n";
8320            pr "      r = guestfs_%s " name;
8321            generate_c_call_args ~handle:"g" style;
8322            pr ";\n";
8323            do_cleanups ();
8324            pr "      if (r == -1)\n";
8325            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8326        | RInt n
8327        | RBool n ->
8328            pr "PREINIT:\n";
8329            pr "      int %s;\n" n;
8330            pr "   CODE:\n";
8331            pr "      %s = guestfs_%s " n name;
8332            generate_c_call_args ~handle:"g" style;
8333            pr ";\n";
8334            do_cleanups ();
8335            pr "      if (%s == -1)\n" n;
8336            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8337            pr "      RETVAL = newSViv (%s);\n" n;
8338            pr " OUTPUT:\n";
8339            pr "      RETVAL\n"
8340        | RInt64 n ->
8341            pr "PREINIT:\n";
8342            pr "      int64_t %s;\n" n;
8343            pr "   CODE:\n";
8344            pr "      %s = guestfs_%s " n name;
8345            generate_c_call_args ~handle:"g" style;
8346            pr ";\n";
8347            do_cleanups ();
8348            pr "      if (%s == -1)\n" n;
8349            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8350            pr "      RETVAL = my_newSVll (%s);\n" n;
8351            pr " OUTPUT:\n";
8352            pr "      RETVAL\n"
8353        | RConstString n ->
8354            pr "PREINIT:\n";
8355            pr "      const char *%s;\n" n;
8356            pr "   CODE:\n";
8357            pr "      %s = guestfs_%s " n name;
8358            generate_c_call_args ~handle:"g" style;
8359            pr ";\n";
8360            do_cleanups ();
8361            pr "      if (%s == NULL)\n" n;
8362            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8363            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8364            pr " OUTPUT:\n";
8365            pr "      RETVAL\n"
8366        | RConstOptString n ->
8367            pr "PREINIT:\n";
8368            pr "      const char *%s;\n" n;
8369            pr "   CODE:\n";
8370            pr "      %s = guestfs_%s " n name;
8371            generate_c_call_args ~handle:"g" style;
8372            pr ";\n";
8373            do_cleanups ();
8374            pr "      if (%s == NULL)\n" n;
8375            pr "        RETVAL = &PL_sv_undef;\n";
8376            pr "      else\n";
8377            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8378            pr " OUTPUT:\n";
8379            pr "      RETVAL\n"
8380        | RString n ->
8381            pr "PREINIT:\n";
8382            pr "      char *%s;\n" n;
8383            pr "   CODE:\n";
8384            pr "      %s = guestfs_%s " n name;
8385            generate_c_call_args ~handle:"g" style;
8386            pr ";\n";
8387            do_cleanups ();
8388            pr "      if (%s == NULL)\n" n;
8389            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8390            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8391            pr "      free (%s);\n" n;
8392            pr " OUTPUT:\n";
8393            pr "      RETVAL\n"
8394        | RStringList n | RHashtable n ->
8395            pr "PREINIT:\n";
8396            pr "      char **%s;\n" n;
8397            pr "      int i, n;\n";
8398            pr " PPCODE:\n";
8399            pr "      %s = guestfs_%s " n name;
8400            generate_c_call_args ~handle:"g" style;
8401            pr ";\n";
8402            do_cleanups ();
8403            pr "      if (%s == NULL)\n" n;
8404            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8405            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8406            pr "      EXTEND (SP, n);\n";
8407            pr "      for (i = 0; i < n; ++i) {\n";
8408            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8409            pr "        free (%s[i]);\n" n;
8410            pr "      }\n";
8411            pr "      free (%s);\n" n;
8412        | RStruct (n, typ) ->
8413            let cols = cols_of_struct typ in
8414            generate_perl_struct_code typ cols name style n do_cleanups
8415        | RStructList (n, typ) ->
8416            let cols = cols_of_struct typ in
8417            generate_perl_struct_list_code typ cols name style n do_cleanups
8418        | RBufferOut n ->
8419            pr "PREINIT:\n";
8420            pr "      char *%s;\n" n;
8421            pr "      size_t size;\n";
8422            pr "   CODE:\n";
8423            pr "      %s = guestfs_%s " n name;
8424            generate_c_call_args ~handle:"g" style;
8425            pr ";\n";
8426            do_cleanups ();
8427            pr "      if (%s == NULL)\n" n;
8428            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8429            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8430            pr "      free (%s);\n" n;
8431            pr " OUTPUT:\n";
8432            pr "      RETVAL\n"
8433       );
8434
8435       pr "\n"
8436   ) all_functions
8437
8438 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8439   pr "PREINIT:\n";
8440   pr "      struct guestfs_%s_list *%s;\n" typ n;
8441   pr "      int i;\n";
8442   pr "      HV *hv;\n";
8443   pr " PPCODE:\n";
8444   pr "      %s = guestfs_%s " n name;
8445   generate_c_call_args ~handle:"g" style;
8446   pr ";\n";
8447   do_cleanups ();
8448   pr "      if (%s == NULL)\n" n;
8449   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8450   pr "      EXTEND (SP, %s->len);\n" n;
8451   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8452   pr "        hv = newHV ();\n";
8453   List.iter (
8454     function
8455     | name, FString ->
8456         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8457           name (String.length name) n name
8458     | name, FUUID ->
8459         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8460           name (String.length name) n name
8461     | name, FBuffer ->
8462         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8463           name (String.length name) n name n name
8464     | name, (FBytes|FUInt64) ->
8465         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8466           name (String.length name) n name
8467     | name, FInt64 ->
8468         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8469           name (String.length name) n name
8470     | name, (FInt32|FUInt32) ->
8471         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8472           name (String.length name) n name
8473     | name, FChar ->
8474         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8475           name (String.length name) n name
8476     | name, FOptPercent ->
8477         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8478           name (String.length name) n name
8479   ) cols;
8480   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8481   pr "      }\n";
8482   pr "      guestfs_free_%s_list (%s);\n" typ n
8483
8484 and generate_perl_struct_code typ cols name style n do_cleanups =
8485   pr "PREINIT:\n";
8486   pr "      struct guestfs_%s *%s;\n" typ n;
8487   pr " PPCODE:\n";
8488   pr "      %s = guestfs_%s " n name;
8489   generate_c_call_args ~handle:"g" style;
8490   pr ";\n";
8491   do_cleanups ();
8492   pr "      if (%s == NULL)\n" n;
8493   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8494   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8495   List.iter (
8496     fun ((name, _) as col) ->
8497       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8498
8499       match col with
8500       | name, FString ->
8501           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8502             n name
8503       | name, FBuffer ->
8504           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8505             n name n name
8506       | name, FUUID ->
8507           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8508             n name
8509       | name, (FBytes|FUInt64) ->
8510           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8511             n name
8512       | name, FInt64 ->
8513           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8514             n name
8515       | name, (FInt32|FUInt32) ->
8516           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8517             n name
8518       | name, FChar ->
8519           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8520             n name
8521       | name, FOptPercent ->
8522           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8523             n name
8524   ) cols;
8525   pr "      free (%s);\n" n
8526
8527 (* Generate Sys/Guestfs.pm. *)
8528 and generate_perl_pm () =
8529   generate_header HashStyle LGPLv2plus;
8530
8531   pr "\
8532 =pod
8533
8534 =head1 NAME
8535
8536 Sys::Guestfs - Perl bindings for libguestfs
8537
8538 =head1 SYNOPSIS
8539
8540  use Sys::Guestfs;
8541
8542  my $h = Sys::Guestfs->new ();
8543  $h->add_drive ('guest.img');
8544  $h->launch ();
8545  $h->mount ('/dev/sda1', '/');
8546  $h->touch ('/hello');
8547  $h->sync ();
8548
8549 =head1 DESCRIPTION
8550
8551 The C<Sys::Guestfs> module provides a Perl XS binding to the
8552 libguestfs API for examining and modifying virtual machine
8553 disk images.
8554
8555 Amongst the things this is good for: making batch configuration
8556 changes to guests, getting disk used/free statistics (see also:
8557 virt-df), migrating between virtualization systems (see also:
8558 virt-p2v), performing partial backups, performing partial guest
8559 clones, cloning guests and changing registry/UUID/hostname info, and
8560 much else besides.
8561
8562 Libguestfs uses Linux kernel and qemu code, and can access any type of
8563 guest filesystem that Linux and qemu can, including but not limited
8564 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8565 schemes, qcow, qcow2, vmdk.
8566
8567 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8568 LVs, what filesystem is in each LV, etc.).  It can also run commands
8569 in the context of the guest.  Also you can access filesystems over
8570 FUSE.
8571
8572 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8573 functions for using libguestfs from Perl, including integration
8574 with libvirt.
8575
8576 =head1 ERRORS
8577
8578 All errors turn into calls to C<croak> (see L<Carp(3)>).
8579
8580 =head1 METHODS
8581
8582 =over 4
8583
8584 =cut
8585
8586 package Sys::Guestfs;
8587
8588 use strict;
8589 use warnings;
8590
8591 require XSLoader;
8592 XSLoader::load ('Sys::Guestfs');
8593
8594 =item $h = Sys::Guestfs->new ();
8595
8596 Create a new guestfs handle.
8597
8598 =cut
8599
8600 sub new {
8601   my $proto = shift;
8602   my $class = ref ($proto) || $proto;
8603
8604   my $self = Sys::Guestfs::_create ();
8605   bless $self, $class;
8606   return $self;
8607 }
8608
8609 ";
8610
8611   (* Actions.  We only need to print documentation for these as
8612    * they are pulled in from the XS code automatically.
8613    *)
8614   List.iter (
8615     fun (name, style, _, flags, _, _, longdesc) ->
8616       if not (List.mem NotInDocs flags) then (
8617         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8618         pr "=item ";
8619         generate_perl_prototype name style;
8620         pr "\n\n";
8621         pr "%s\n\n" longdesc;
8622         if List.mem ProtocolLimitWarning flags then
8623           pr "%s\n\n" protocol_limit_warning;
8624         if List.mem DangerWillRobinson flags then
8625           pr "%s\n\n" danger_will_robinson;
8626         match deprecation_notice flags with
8627         | None -> ()
8628         | Some txt -> pr "%s\n\n" txt
8629       )
8630   ) all_functions_sorted;
8631
8632   (* End of file. *)
8633   pr "\
8634 =cut
8635
8636 1;
8637
8638 =back
8639
8640 =head1 COPYRIGHT
8641
8642 Copyright (C) %s Red Hat Inc.
8643
8644 =head1 LICENSE
8645
8646 Please see the file COPYING.LIB for the full license.
8647
8648 =head1 SEE ALSO
8649
8650 L<guestfs(3)>,
8651 L<guestfish(1)>,
8652 L<http://libguestfs.org>,
8653 L<Sys::Guestfs::Lib(3)>.
8654
8655 =cut
8656 " copyright_years
8657
8658 and generate_perl_prototype name style =
8659   (match fst style with
8660    | RErr -> ()
8661    | RBool n
8662    | RInt n
8663    | RInt64 n
8664    | RConstString n
8665    | RConstOptString n
8666    | RString n
8667    | RBufferOut n -> pr "$%s = " n
8668    | RStruct (n,_)
8669    | RHashtable n -> pr "%%%s = " n
8670    | RStringList n
8671    | RStructList (n,_) -> pr "@%s = " n
8672   );
8673   pr "$h->%s (" name;
8674   let comma = ref false in
8675   List.iter (
8676     fun arg ->
8677       if !comma then pr ", ";
8678       comma := true;
8679       match arg with
8680       | Pathname n | Device n | Dev_or_Path n | String n
8681       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8682           pr "$%s" n
8683       | StringList n | DeviceList n ->
8684           pr "\\@%s" n
8685   ) (snd style);
8686   pr ");"
8687
8688 (* Generate Python C module. *)
8689 and generate_python_c () =
8690   generate_header CStyle LGPLv2plus;
8691
8692   pr "\
8693 #include <Python.h>
8694
8695 #include <stdio.h>
8696 #include <stdlib.h>
8697 #include <assert.h>
8698
8699 #include \"guestfs.h\"
8700
8701 typedef struct {
8702   PyObject_HEAD
8703   guestfs_h *g;
8704 } Pyguestfs_Object;
8705
8706 static guestfs_h *
8707 get_handle (PyObject *obj)
8708 {
8709   assert (obj);
8710   assert (obj != Py_None);
8711   return ((Pyguestfs_Object *) obj)->g;
8712 }
8713
8714 static PyObject *
8715 put_handle (guestfs_h *g)
8716 {
8717   assert (g);
8718   return
8719     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8720 }
8721
8722 /* This list should be freed (but not the strings) after use. */
8723 static char **
8724 get_string_list (PyObject *obj)
8725 {
8726   int i, len;
8727   char **r;
8728
8729   assert (obj);
8730
8731   if (!PyList_Check (obj)) {
8732     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8733     return NULL;
8734   }
8735
8736   len = PyList_Size (obj);
8737   r = malloc (sizeof (char *) * (len+1));
8738   if (r == NULL) {
8739     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8740     return NULL;
8741   }
8742
8743   for (i = 0; i < len; ++i)
8744     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8745   r[len] = NULL;
8746
8747   return r;
8748 }
8749
8750 static PyObject *
8751 put_string_list (char * const * const argv)
8752 {
8753   PyObject *list;
8754   int argc, i;
8755
8756   for (argc = 0; argv[argc] != NULL; ++argc)
8757     ;
8758
8759   list = PyList_New (argc);
8760   for (i = 0; i < argc; ++i)
8761     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8762
8763   return list;
8764 }
8765
8766 static PyObject *
8767 put_table (char * const * const argv)
8768 {
8769   PyObject *list, *item;
8770   int argc, i;
8771
8772   for (argc = 0; argv[argc] != NULL; ++argc)
8773     ;
8774
8775   list = PyList_New (argc >> 1);
8776   for (i = 0; i < argc; i += 2) {
8777     item = PyTuple_New (2);
8778     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8779     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8780     PyList_SetItem (list, i >> 1, item);
8781   }
8782
8783   return list;
8784 }
8785
8786 static void
8787 free_strings (char **argv)
8788 {
8789   int argc;
8790
8791   for (argc = 0; argv[argc] != NULL; ++argc)
8792     free (argv[argc]);
8793   free (argv);
8794 }
8795
8796 static PyObject *
8797 py_guestfs_create (PyObject *self, PyObject *args)
8798 {
8799   guestfs_h *g;
8800
8801   g = guestfs_create ();
8802   if (g == NULL) {
8803     PyErr_SetString (PyExc_RuntimeError,
8804                      \"guestfs.create: failed to allocate handle\");
8805     return NULL;
8806   }
8807   guestfs_set_error_handler (g, NULL, NULL);
8808   return put_handle (g);
8809 }
8810
8811 static PyObject *
8812 py_guestfs_close (PyObject *self, PyObject *args)
8813 {
8814   PyObject *py_g;
8815   guestfs_h *g;
8816
8817   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8818     return NULL;
8819   g = get_handle (py_g);
8820
8821   guestfs_close (g);
8822
8823   Py_INCREF (Py_None);
8824   return Py_None;
8825 }
8826
8827 ";
8828
8829   let emit_put_list_function typ =
8830     pr "static PyObject *\n";
8831     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8832     pr "{\n";
8833     pr "  PyObject *list;\n";
8834     pr "  int i;\n";
8835     pr "\n";
8836     pr "  list = PyList_New (%ss->len);\n" typ;
8837     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8838     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8839     pr "  return list;\n";
8840     pr "};\n";
8841     pr "\n"
8842   in
8843
8844   (* Structures, turned into Python dictionaries. *)
8845   List.iter (
8846     fun (typ, cols) ->
8847       pr "static PyObject *\n";
8848       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8849       pr "{\n";
8850       pr "  PyObject *dict;\n";
8851       pr "\n";
8852       pr "  dict = PyDict_New ();\n";
8853       List.iter (
8854         function
8855         | name, FString ->
8856             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8857             pr "                        PyString_FromString (%s->%s));\n"
8858               typ name
8859         | name, FBuffer ->
8860             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8861             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8862               typ name typ name
8863         | name, FUUID ->
8864             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8865             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8866               typ name
8867         | name, (FBytes|FUInt64) ->
8868             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8869             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8870               typ name
8871         | name, FInt64 ->
8872             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8873             pr "                        PyLong_FromLongLong (%s->%s));\n"
8874               typ name
8875         | name, FUInt32 ->
8876             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8877             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8878               typ name
8879         | name, FInt32 ->
8880             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8881             pr "                        PyLong_FromLong (%s->%s));\n"
8882               typ name
8883         | name, FOptPercent ->
8884             pr "  if (%s->%s >= 0)\n" typ name;
8885             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8886             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8887               typ name;
8888             pr "  else {\n";
8889             pr "    Py_INCREF (Py_None);\n";
8890             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8891             pr "  }\n"
8892         | name, FChar ->
8893             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8894             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8895       ) cols;
8896       pr "  return dict;\n";
8897       pr "};\n";
8898       pr "\n";
8899
8900   ) structs;
8901
8902   (* Emit a put_TYPE_list function definition only if that function is used. *)
8903   List.iter (
8904     function
8905     | typ, (RStructListOnly | RStructAndList) ->
8906         (* generate the function for typ *)
8907         emit_put_list_function typ
8908     | typ, _ -> () (* empty *)
8909   ) (rstructs_used_by all_functions);
8910
8911   (* Python wrapper functions. *)
8912   List.iter (
8913     fun (name, style, _, _, _, _, _) ->
8914       pr "static PyObject *\n";
8915       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8916       pr "{\n";
8917
8918       pr "  PyObject *py_g;\n";
8919       pr "  guestfs_h *g;\n";
8920       pr "  PyObject *py_r;\n";
8921
8922       let error_code =
8923         match fst style with
8924         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8925         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8926         | RConstString _ | RConstOptString _ ->
8927             pr "  const char *r;\n"; "NULL"
8928         | RString _ -> pr "  char *r;\n"; "NULL"
8929         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8930         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8931         | RStructList (_, typ) ->
8932             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8933         | RBufferOut _ ->
8934             pr "  char *r;\n";
8935             pr "  size_t size;\n";
8936             "NULL" in
8937
8938       List.iter (
8939         function
8940         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8941             pr "  const char *%s;\n" n
8942         | OptString n -> pr "  const char *%s;\n" n
8943         | StringList n | DeviceList n ->
8944             pr "  PyObject *py_%s;\n" n;
8945             pr "  char **%s;\n" n
8946         | Bool n -> pr "  int %s;\n" n
8947         | Int n -> pr "  int %s;\n" n
8948         | Int64 n -> pr "  long long %s;\n" n
8949       ) (snd style);
8950
8951       pr "\n";
8952
8953       (* Convert the parameters. *)
8954       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8955       List.iter (
8956         function
8957         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8958         | OptString _ -> pr "z"
8959         | StringList _ | DeviceList _ -> pr "O"
8960         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8961         | Int _ -> pr "i"
8962         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8963                              * emulate C's int/long/long long in Python?
8964                              *)
8965       ) (snd style);
8966       pr ":guestfs_%s\",\n" name;
8967       pr "                         &py_g";
8968       List.iter (
8969         function
8970         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8971         | OptString n -> pr ", &%s" n
8972         | StringList n | DeviceList n -> pr ", &py_%s" n
8973         | Bool n -> pr ", &%s" n
8974         | Int n -> pr ", &%s" n
8975         | Int64 n -> pr ", &%s" n
8976       ) (snd style);
8977
8978       pr "))\n";
8979       pr "    return NULL;\n";
8980
8981       pr "  g = get_handle (py_g);\n";
8982       List.iter (
8983         function
8984         | Pathname _ | Device _ | Dev_or_Path _ | String _
8985         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8986         | StringList n | DeviceList n ->
8987             pr "  %s = get_string_list (py_%s);\n" n n;
8988             pr "  if (!%s) return NULL;\n" n
8989       ) (snd style);
8990
8991       pr "\n";
8992
8993       pr "  r = guestfs_%s " name;
8994       generate_c_call_args ~handle:"g" style;
8995       pr ";\n";
8996
8997       List.iter (
8998         function
8999         | Pathname _ | Device _ | Dev_or_Path _ | String _
9000         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9001         | StringList n | DeviceList n ->
9002             pr "  free (%s);\n" n
9003       ) (snd style);
9004
9005       pr "  if (r == %s) {\n" error_code;
9006       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9007       pr "    return NULL;\n";
9008       pr "  }\n";
9009       pr "\n";
9010
9011       (match fst style with
9012        | RErr ->
9013            pr "  Py_INCREF (Py_None);\n";
9014            pr "  py_r = Py_None;\n"
9015        | RInt _
9016        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9017        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9018        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9019        | RConstOptString _ ->
9020            pr "  if (r)\n";
9021            pr "    py_r = PyString_FromString (r);\n";
9022            pr "  else {\n";
9023            pr "    Py_INCREF (Py_None);\n";
9024            pr "    py_r = Py_None;\n";
9025            pr "  }\n"
9026        | RString _ ->
9027            pr "  py_r = PyString_FromString (r);\n";
9028            pr "  free (r);\n"
9029        | RStringList _ ->
9030            pr "  py_r = put_string_list (r);\n";
9031            pr "  free_strings (r);\n"
9032        | RStruct (_, typ) ->
9033            pr "  py_r = put_%s (r);\n" typ;
9034            pr "  guestfs_free_%s (r);\n" typ
9035        | RStructList (_, typ) ->
9036            pr "  py_r = put_%s_list (r);\n" typ;
9037            pr "  guestfs_free_%s_list (r);\n" typ
9038        | RHashtable n ->
9039            pr "  py_r = put_table (r);\n";
9040            pr "  free_strings (r);\n"
9041        | RBufferOut _ ->
9042            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9043            pr "  free (r);\n"
9044       );
9045
9046       pr "  return py_r;\n";
9047       pr "}\n";
9048       pr "\n"
9049   ) all_functions;
9050
9051   (* Table of functions. *)
9052   pr "static PyMethodDef methods[] = {\n";
9053   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9054   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9055   List.iter (
9056     fun (name, _, _, _, _, _, _) ->
9057       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9058         name name
9059   ) all_functions;
9060   pr "  { NULL, NULL, 0, NULL }\n";
9061   pr "};\n";
9062   pr "\n";
9063
9064   (* Init function. *)
9065   pr "\
9066 void
9067 initlibguestfsmod (void)
9068 {
9069   static int initialized = 0;
9070
9071   if (initialized) return;
9072   Py_InitModule ((char *) \"libguestfsmod\", methods);
9073   initialized = 1;
9074 }
9075 "
9076
9077 (* Generate Python module. *)
9078 and generate_python_py () =
9079   generate_header HashStyle LGPLv2plus;
9080
9081   pr "\
9082 u\"\"\"Python bindings for libguestfs
9083
9084 import guestfs
9085 g = guestfs.GuestFS ()
9086 g.add_drive (\"guest.img\")
9087 g.launch ()
9088 parts = g.list_partitions ()
9089
9090 The guestfs module provides a Python binding to the libguestfs API
9091 for examining and modifying virtual machine disk images.
9092
9093 Amongst the things this is good for: making batch configuration
9094 changes to guests, getting disk used/free statistics (see also:
9095 virt-df), migrating between virtualization systems (see also:
9096 virt-p2v), performing partial backups, performing partial guest
9097 clones, cloning guests and changing registry/UUID/hostname info, and
9098 much else besides.
9099
9100 Libguestfs uses Linux kernel and qemu code, and can access any type of
9101 guest filesystem that Linux and qemu can, including but not limited
9102 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9103 schemes, qcow, qcow2, vmdk.
9104
9105 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9106 LVs, what filesystem is in each LV, etc.).  It can also run commands
9107 in the context of the guest.  Also you can access filesystems over
9108 FUSE.
9109
9110 Errors which happen while using the API are turned into Python
9111 RuntimeError exceptions.
9112
9113 To create a guestfs handle you usually have to perform the following
9114 sequence of calls:
9115
9116 # Create the handle, call add_drive at least once, and possibly
9117 # several times if the guest has multiple block devices:
9118 g = guestfs.GuestFS ()
9119 g.add_drive (\"guest.img\")
9120
9121 # Launch the qemu subprocess and wait for it to become ready:
9122 g.launch ()
9123
9124 # Now you can issue commands, for example:
9125 logvols = g.lvs ()
9126
9127 \"\"\"
9128
9129 import libguestfsmod
9130
9131 class GuestFS:
9132     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9133
9134     def __init__ (self):
9135         \"\"\"Create a new libguestfs handle.\"\"\"
9136         self._o = libguestfsmod.create ()
9137
9138     def __del__ (self):
9139         libguestfsmod.close (self._o)
9140
9141 ";
9142
9143   List.iter (
9144     fun (name, style, _, flags, _, _, longdesc) ->
9145       pr "    def %s " name;
9146       generate_py_call_args ~handle:"self" (snd style);
9147       pr ":\n";
9148
9149       if not (List.mem NotInDocs flags) then (
9150         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9151         let doc =
9152           match fst style with
9153           | RErr | RInt _ | RInt64 _ | RBool _
9154           | RConstOptString _ | RConstString _
9155           | RString _ | RBufferOut _ -> doc
9156           | RStringList _ ->
9157               doc ^ "\n\nThis function returns a list of strings."
9158           | RStruct (_, typ) ->
9159               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9160           | RStructList (_, typ) ->
9161               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9162           | RHashtable _ ->
9163               doc ^ "\n\nThis function returns a dictionary." in
9164         let doc =
9165           if List.mem ProtocolLimitWarning flags then
9166             doc ^ "\n\n" ^ protocol_limit_warning
9167           else doc in
9168         let doc =
9169           if List.mem DangerWillRobinson flags then
9170             doc ^ "\n\n" ^ danger_will_robinson
9171           else doc in
9172         let doc =
9173           match deprecation_notice flags with
9174           | None -> doc
9175           | Some txt -> doc ^ "\n\n" ^ txt in
9176         let doc = pod2text ~width:60 name doc in
9177         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9178         let doc = String.concat "\n        " doc in
9179         pr "        u\"\"\"%s\"\"\"\n" doc;
9180       );
9181       pr "        return libguestfsmod.%s " name;
9182       generate_py_call_args ~handle:"self._o" (snd style);
9183       pr "\n";
9184       pr "\n";
9185   ) all_functions
9186
9187 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9188 and generate_py_call_args ~handle args =
9189   pr "(%s" handle;
9190   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9191   pr ")"
9192
9193 (* Useful if you need the longdesc POD text as plain text.  Returns a
9194  * list of lines.
9195  *
9196  * Because this is very slow (the slowest part of autogeneration),
9197  * we memoize the results.
9198  *)
9199 and pod2text ~width name longdesc =
9200   let key = width, name, longdesc in
9201   try Hashtbl.find pod2text_memo key
9202   with Not_found ->
9203     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9204     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9205     close_out chan;
9206     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9207     let chan = open_process_in cmd in
9208     let lines = ref [] in
9209     let rec loop i =
9210       let line = input_line chan in
9211       if i = 1 then             (* discard the first line of output *)
9212         loop (i+1)
9213       else (
9214         let line = triml line in
9215         lines := line :: !lines;
9216         loop (i+1)
9217       ) in
9218     let lines = try loop 1 with End_of_file -> List.rev !lines in
9219     unlink filename;
9220     (match close_process_in chan with
9221      | WEXITED 0 -> ()
9222      | WEXITED i ->
9223          failwithf "pod2text: process exited with non-zero status (%d)" i
9224      | WSIGNALED i | WSTOPPED i ->
9225          failwithf "pod2text: process signalled or stopped by signal %d" i
9226     );
9227     Hashtbl.add pod2text_memo key lines;
9228     pod2text_memo_updated ();
9229     lines
9230
9231 (* Generate ruby bindings. *)
9232 and generate_ruby_c () =
9233   generate_header CStyle LGPLv2plus;
9234
9235   pr "\
9236 #include <stdio.h>
9237 #include <stdlib.h>
9238
9239 #include <ruby.h>
9240
9241 #include \"guestfs.h\"
9242
9243 #include \"extconf.h\"
9244
9245 /* For Ruby < 1.9 */
9246 #ifndef RARRAY_LEN
9247 #define RARRAY_LEN(r) (RARRAY((r))->len)
9248 #endif
9249
9250 static VALUE m_guestfs;                 /* guestfs module */
9251 static VALUE c_guestfs;                 /* guestfs_h handle */
9252 static VALUE e_Error;                   /* used for all errors */
9253
9254 static void ruby_guestfs_free (void *p)
9255 {
9256   if (!p) return;
9257   guestfs_close ((guestfs_h *) p);
9258 }
9259
9260 static VALUE ruby_guestfs_create (VALUE m)
9261 {
9262   guestfs_h *g;
9263
9264   g = guestfs_create ();
9265   if (!g)
9266     rb_raise (e_Error, \"failed to create guestfs handle\");
9267
9268   /* Don't print error messages to stderr by default. */
9269   guestfs_set_error_handler (g, NULL, NULL);
9270
9271   /* Wrap it, and make sure the close function is called when the
9272    * handle goes away.
9273    */
9274   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9275 }
9276
9277 static VALUE ruby_guestfs_close (VALUE gv)
9278 {
9279   guestfs_h *g;
9280   Data_Get_Struct (gv, guestfs_h, g);
9281
9282   ruby_guestfs_free (g);
9283   DATA_PTR (gv) = NULL;
9284
9285   return Qnil;
9286 }
9287
9288 ";
9289
9290   List.iter (
9291     fun (name, style, _, _, _, _, _) ->
9292       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9293       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9294       pr ")\n";
9295       pr "{\n";
9296       pr "  guestfs_h *g;\n";
9297       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9298       pr "  if (!g)\n";
9299       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9300         name;
9301       pr "\n";
9302
9303       List.iter (
9304         function
9305         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9306             pr "  Check_Type (%sv, T_STRING);\n" n;
9307             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9308             pr "  if (!%s)\n" n;
9309             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9310             pr "              \"%s\", \"%s\");\n" n name
9311         | OptString n ->
9312             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9313         | StringList n | DeviceList n ->
9314             pr "  char **%s;\n" n;
9315             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9316             pr "  {\n";
9317             pr "    int i, len;\n";
9318             pr "    len = RARRAY_LEN (%sv);\n" n;
9319             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9320               n;
9321             pr "    for (i = 0; i < len; ++i) {\n";
9322             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9323             pr "      %s[i] = StringValueCStr (v);\n" n;
9324             pr "    }\n";
9325             pr "    %s[len] = NULL;\n" n;
9326             pr "  }\n";
9327         | Bool n ->
9328             pr "  int %s = RTEST (%sv);\n" n n
9329         | Int n ->
9330             pr "  int %s = NUM2INT (%sv);\n" n n
9331         | Int64 n ->
9332             pr "  long long %s = NUM2LL (%sv);\n" n n
9333       ) (snd style);
9334       pr "\n";
9335
9336       let error_code =
9337         match fst style with
9338         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9339         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9340         | RConstString _ | RConstOptString _ ->
9341             pr "  const char *r;\n"; "NULL"
9342         | RString _ -> pr "  char *r;\n"; "NULL"
9343         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9344         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9345         | RStructList (_, typ) ->
9346             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9347         | RBufferOut _ ->
9348             pr "  char *r;\n";
9349             pr "  size_t size;\n";
9350             "NULL" in
9351       pr "\n";
9352
9353       pr "  r = guestfs_%s " name;
9354       generate_c_call_args ~handle:"g" style;
9355       pr ";\n";
9356
9357       List.iter (
9358         function
9359         | Pathname _ | Device _ | Dev_or_Path _ | String _
9360         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9361         | StringList n | DeviceList n ->
9362             pr "  free (%s);\n" n
9363       ) (snd style);
9364
9365       pr "  if (r == %s)\n" error_code;
9366       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9367       pr "\n";
9368
9369       (match fst style with
9370        | RErr ->
9371            pr "  return Qnil;\n"
9372        | RInt _ | RBool _ ->
9373            pr "  return INT2NUM (r);\n"
9374        | RInt64 _ ->
9375            pr "  return ULL2NUM (r);\n"
9376        | RConstString _ ->
9377            pr "  return rb_str_new2 (r);\n";
9378        | RConstOptString _ ->
9379            pr "  if (r)\n";
9380            pr "    return rb_str_new2 (r);\n";
9381            pr "  else\n";
9382            pr "    return Qnil;\n";
9383        | RString _ ->
9384            pr "  VALUE rv = rb_str_new2 (r);\n";
9385            pr "  free (r);\n";
9386            pr "  return rv;\n";
9387        | RStringList _ ->
9388            pr "  int i, len = 0;\n";
9389            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9390            pr "  VALUE rv = rb_ary_new2 (len);\n";
9391            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9392            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9393            pr "    free (r[i]);\n";
9394            pr "  }\n";
9395            pr "  free (r);\n";
9396            pr "  return rv;\n"
9397        | RStruct (_, typ) ->
9398            let cols = cols_of_struct typ in
9399            generate_ruby_struct_code typ cols
9400        | RStructList (_, typ) ->
9401            let cols = cols_of_struct typ in
9402            generate_ruby_struct_list_code typ cols
9403        | RHashtable _ ->
9404            pr "  VALUE rv = rb_hash_new ();\n";
9405            pr "  int i;\n";
9406            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9407            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9408            pr "    free (r[i]);\n";
9409            pr "    free (r[i+1]);\n";
9410            pr "  }\n";
9411            pr "  free (r);\n";
9412            pr "  return rv;\n"
9413        | RBufferOut _ ->
9414            pr "  VALUE rv = rb_str_new (r, size);\n";
9415            pr "  free (r);\n";
9416            pr "  return rv;\n";
9417       );
9418
9419       pr "}\n";
9420       pr "\n"
9421   ) all_functions;
9422
9423   pr "\
9424 /* Initialize the module. */
9425 void Init__guestfs ()
9426 {
9427   m_guestfs = rb_define_module (\"Guestfs\");
9428   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9429   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9430
9431   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9432   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9433
9434 ";
9435   (* Define the rest of the methods. *)
9436   List.iter (
9437     fun (name, style, _, _, _, _, _) ->
9438       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9439       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9440   ) all_functions;
9441
9442   pr "}\n"
9443
9444 (* Ruby code to return a struct. *)
9445 and generate_ruby_struct_code typ cols =
9446   pr "  VALUE rv = rb_hash_new ();\n";
9447   List.iter (
9448     function
9449     | name, FString ->
9450         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9451     | name, FBuffer ->
9452         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9453     | name, FUUID ->
9454         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9455     | name, (FBytes|FUInt64) ->
9456         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9457     | name, FInt64 ->
9458         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9459     | name, FUInt32 ->
9460         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9461     | name, FInt32 ->
9462         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9463     | name, FOptPercent ->
9464         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9465     | name, FChar -> (* XXX wrong? *)
9466         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9467   ) cols;
9468   pr "  guestfs_free_%s (r);\n" typ;
9469   pr "  return rv;\n"
9470
9471 (* Ruby code to return a struct list. *)
9472 and generate_ruby_struct_list_code typ cols =
9473   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9474   pr "  int i;\n";
9475   pr "  for (i = 0; i < r->len; ++i) {\n";
9476   pr "    VALUE hv = rb_hash_new ();\n";
9477   List.iter (
9478     function
9479     | name, FString ->
9480         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9481     | name, FBuffer ->
9482         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
9483     | name, FUUID ->
9484         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9485     | name, (FBytes|FUInt64) ->
9486         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9487     | name, FInt64 ->
9488         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9489     | name, FUInt32 ->
9490         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9491     | name, FInt32 ->
9492         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9493     | name, FOptPercent ->
9494         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9495     | name, FChar -> (* XXX wrong? *)
9496         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9497   ) cols;
9498   pr "    rb_ary_push (rv, hv);\n";
9499   pr "  }\n";
9500   pr "  guestfs_free_%s_list (r);\n" typ;
9501   pr "  return rv;\n"
9502
9503 (* Generate Java bindings GuestFS.java file. *)
9504 and generate_java_java () =
9505   generate_header CStyle LGPLv2plus;
9506
9507   pr "\
9508 package com.redhat.et.libguestfs;
9509
9510 import java.util.HashMap;
9511 import com.redhat.et.libguestfs.LibGuestFSException;
9512 import com.redhat.et.libguestfs.PV;
9513 import com.redhat.et.libguestfs.VG;
9514 import com.redhat.et.libguestfs.LV;
9515 import com.redhat.et.libguestfs.Stat;
9516 import com.redhat.et.libguestfs.StatVFS;
9517 import com.redhat.et.libguestfs.IntBool;
9518 import com.redhat.et.libguestfs.Dirent;
9519
9520 /**
9521  * The GuestFS object is a libguestfs handle.
9522  *
9523  * @author rjones
9524  */
9525 public class GuestFS {
9526   // Load the native code.
9527   static {
9528     System.loadLibrary (\"guestfs_jni\");
9529   }
9530
9531   /**
9532    * The native guestfs_h pointer.
9533    */
9534   long g;
9535
9536   /**
9537    * Create a libguestfs handle.
9538    *
9539    * @throws LibGuestFSException
9540    */
9541   public GuestFS () throws LibGuestFSException
9542   {
9543     g = _create ();
9544   }
9545   private native long _create () throws LibGuestFSException;
9546
9547   /**
9548    * Close a libguestfs handle.
9549    *
9550    * You can also leave handles to be collected by the garbage
9551    * collector, but this method ensures that the resources used
9552    * by the handle are freed up immediately.  If you call any
9553    * other methods after closing the handle, you will get an
9554    * exception.
9555    *
9556    * @throws LibGuestFSException
9557    */
9558   public void close () throws LibGuestFSException
9559   {
9560     if (g != 0)
9561       _close (g);
9562     g = 0;
9563   }
9564   private native void _close (long g) throws LibGuestFSException;
9565
9566   public void finalize () throws LibGuestFSException
9567   {
9568     close ();
9569   }
9570
9571 ";
9572
9573   List.iter (
9574     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9575       if not (List.mem NotInDocs flags); then (
9576         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9577         let doc =
9578           if List.mem ProtocolLimitWarning flags then
9579             doc ^ "\n\n" ^ protocol_limit_warning
9580           else doc in
9581         let doc =
9582           if List.mem DangerWillRobinson flags then
9583             doc ^ "\n\n" ^ danger_will_robinson
9584           else doc in
9585         let doc =
9586           match deprecation_notice flags with
9587           | None -> doc
9588           | Some txt -> doc ^ "\n\n" ^ txt in
9589         let doc = pod2text ~width:60 name doc in
9590         let doc = List.map (            (* RHBZ#501883 *)
9591           function
9592           | "" -> "<p>"
9593           | nonempty -> nonempty
9594         ) doc in
9595         let doc = String.concat "\n   * " doc in
9596
9597         pr "  /**\n";
9598         pr "   * %s\n" shortdesc;
9599         pr "   * <p>\n";
9600         pr "   * %s\n" doc;
9601         pr "   * @throws LibGuestFSException\n";
9602         pr "   */\n";
9603         pr "  ";
9604       );
9605       generate_java_prototype ~public:true ~semicolon:false name style;
9606       pr "\n";
9607       pr "  {\n";
9608       pr "    if (g == 0)\n";
9609       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9610         name;
9611       pr "    ";
9612       if fst style <> RErr then pr "return ";
9613       pr "_%s " name;
9614       generate_java_call_args ~handle:"g" (snd style);
9615       pr ";\n";
9616       pr "  }\n";
9617       pr "  ";
9618       generate_java_prototype ~privat:true ~native:true name style;
9619       pr "\n";
9620       pr "\n";
9621   ) all_functions;
9622
9623   pr "}\n"
9624
9625 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9626 and generate_java_call_args ~handle args =
9627   pr "(%s" handle;
9628   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9629   pr ")"
9630
9631 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9632     ?(semicolon=true) name style =
9633   if privat then pr "private ";
9634   if public then pr "public ";
9635   if native then pr "native ";
9636
9637   (* return type *)
9638   (match fst style with
9639    | RErr -> pr "void ";
9640    | RInt _ -> pr "int ";
9641    | RInt64 _ -> pr "long ";
9642    | RBool _ -> pr "boolean ";
9643    | RConstString _ | RConstOptString _ | RString _
9644    | RBufferOut _ -> pr "String ";
9645    | RStringList _ -> pr "String[] ";
9646    | RStruct (_, typ) ->
9647        let name = java_name_of_struct typ in
9648        pr "%s " name;
9649    | RStructList (_, typ) ->
9650        let name = java_name_of_struct typ in
9651        pr "%s[] " name;
9652    | RHashtable _ -> pr "HashMap<String,String> ";
9653   );
9654
9655   if native then pr "_%s " name else pr "%s " name;
9656   pr "(";
9657   let needs_comma = ref false in
9658   if native then (
9659     pr "long g";
9660     needs_comma := true
9661   );
9662
9663   (* args *)
9664   List.iter (
9665     fun arg ->
9666       if !needs_comma then pr ", ";
9667       needs_comma := true;
9668
9669       match arg with
9670       | Pathname n
9671       | Device n | Dev_or_Path n
9672       | String n
9673       | OptString n
9674       | FileIn n
9675       | FileOut n ->
9676           pr "String %s" n
9677       | StringList n | DeviceList n ->
9678           pr "String[] %s" n
9679       | Bool n ->
9680           pr "boolean %s" n
9681       | Int n ->
9682           pr "int %s" n
9683       | Int64 n ->
9684           pr "long %s" n
9685   ) (snd style);
9686
9687   pr ")\n";
9688   pr "    throws LibGuestFSException";
9689   if semicolon then pr ";"
9690
9691 and generate_java_struct jtyp cols () =
9692   generate_header CStyle LGPLv2plus;
9693
9694   pr "\
9695 package com.redhat.et.libguestfs;
9696
9697 /**
9698  * Libguestfs %s structure.
9699  *
9700  * @author rjones
9701  * @see GuestFS
9702  */
9703 public class %s {
9704 " jtyp jtyp;
9705
9706   List.iter (
9707     function
9708     | name, FString
9709     | name, FUUID
9710     | name, FBuffer -> pr "  public String %s;\n" name
9711     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9712     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9713     | name, FChar -> pr "  public char %s;\n" name
9714     | name, FOptPercent ->
9715         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9716         pr "  public float %s;\n" name
9717   ) cols;
9718
9719   pr "}\n"
9720
9721 and generate_java_c () =
9722   generate_header CStyle LGPLv2plus;
9723
9724   pr "\
9725 #include <stdio.h>
9726 #include <stdlib.h>
9727 #include <string.h>
9728
9729 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9730 #include \"guestfs.h\"
9731
9732 /* Note that this function returns.  The exception is not thrown
9733  * until after the wrapper function returns.
9734  */
9735 static void
9736 throw_exception (JNIEnv *env, const char *msg)
9737 {
9738   jclass cl;
9739   cl = (*env)->FindClass (env,
9740                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9741   (*env)->ThrowNew (env, cl, msg);
9742 }
9743
9744 JNIEXPORT jlong JNICALL
9745 Java_com_redhat_et_libguestfs_GuestFS__1create
9746   (JNIEnv *env, jobject obj)
9747 {
9748   guestfs_h *g;
9749
9750   g = guestfs_create ();
9751   if (g == NULL) {
9752     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9753     return 0;
9754   }
9755   guestfs_set_error_handler (g, NULL, NULL);
9756   return (jlong) (long) g;
9757 }
9758
9759 JNIEXPORT void JNICALL
9760 Java_com_redhat_et_libguestfs_GuestFS__1close
9761   (JNIEnv *env, jobject obj, jlong jg)
9762 {
9763   guestfs_h *g = (guestfs_h *) (long) jg;
9764   guestfs_close (g);
9765 }
9766
9767 ";
9768
9769   List.iter (
9770     fun (name, style, _, _, _, _, _) ->
9771       pr "JNIEXPORT ";
9772       (match fst style with
9773        | RErr -> pr "void ";
9774        | RInt _ -> pr "jint ";
9775        | RInt64 _ -> pr "jlong ";
9776        | RBool _ -> pr "jboolean ";
9777        | RConstString _ | RConstOptString _ | RString _
9778        | RBufferOut _ -> pr "jstring ";
9779        | RStruct _ | RHashtable _ ->
9780            pr "jobject ";
9781        | RStringList _ | RStructList _ ->
9782            pr "jobjectArray ";
9783       );
9784       pr "JNICALL\n";
9785       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9786       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9787       pr "\n";
9788       pr "  (JNIEnv *env, jobject obj, jlong jg";
9789       List.iter (
9790         function
9791         | Pathname n
9792         | Device n | Dev_or_Path n
9793         | String n
9794         | OptString n
9795         | FileIn n
9796         | FileOut n ->
9797             pr ", jstring j%s" n
9798         | StringList n | DeviceList n ->
9799             pr ", jobjectArray j%s" n
9800         | Bool n ->
9801             pr ", jboolean j%s" n
9802         | Int n ->
9803             pr ", jint j%s" n
9804         | Int64 n ->
9805             pr ", jlong j%s" n
9806       ) (snd style);
9807       pr ")\n";
9808       pr "{\n";
9809       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9810       let error_code, no_ret =
9811         match fst style with
9812         | RErr -> pr "  int r;\n"; "-1", ""
9813         | RBool _
9814         | RInt _ -> pr "  int r;\n"; "-1", "0"
9815         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9816         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9817         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9818         | RString _ ->
9819             pr "  jstring jr;\n";
9820             pr "  char *r;\n"; "NULL", "NULL"
9821         | RStringList _ ->
9822             pr "  jobjectArray jr;\n";
9823             pr "  int r_len;\n";
9824             pr "  jclass cl;\n";
9825             pr "  jstring jstr;\n";
9826             pr "  char **r;\n"; "NULL", "NULL"
9827         | RStruct (_, typ) ->
9828             pr "  jobject jr;\n";
9829             pr "  jclass cl;\n";
9830             pr "  jfieldID fl;\n";
9831             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9832         | RStructList (_, typ) ->
9833             pr "  jobjectArray jr;\n";
9834             pr "  jclass cl;\n";
9835             pr "  jfieldID fl;\n";
9836             pr "  jobject jfl;\n";
9837             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9838         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9839         | RBufferOut _ ->
9840             pr "  jstring jr;\n";
9841             pr "  char *r;\n";
9842             pr "  size_t size;\n";
9843             "NULL", "NULL" in
9844       List.iter (
9845         function
9846         | Pathname n
9847         | Device n | Dev_or_Path n
9848         | String n
9849         | OptString n
9850         | FileIn n
9851         | FileOut n ->
9852             pr "  const char *%s;\n" n
9853         | StringList n | DeviceList n ->
9854             pr "  int %s_len;\n" n;
9855             pr "  const char **%s;\n" n
9856         | Bool n
9857         | Int n ->
9858             pr "  int %s;\n" n
9859         | Int64 n ->
9860             pr "  int64_t %s;\n" n
9861       ) (snd style);
9862
9863       let needs_i =
9864         (match fst style with
9865          | RStringList _ | RStructList _ -> true
9866          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9867          | RConstOptString _
9868          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9869           List.exists (function
9870                        | StringList _ -> true
9871                        | DeviceList _ -> true
9872                        | _ -> false) (snd style) in
9873       if needs_i then
9874         pr "  int i;\n";
9875
9876       pr "\n";
9877
9878       (* Get the parameters. *)
9879       List.iter (
9880         function
9881         | Pathname n
9882         | Device n | Dev_or_Path n
9883         | String n
9884         | FileIn n
9885         | FileOut n ->
9886             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9887         | OptString n ->
9888             (* This is completely undocumented, but Java null becomes
9889              * a NULL parameter.
9890              *)
9891             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9892         | StringList n | DeviceList n ->
9893             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9894             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9895             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9896             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9897               n;
9898             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9899             pr "  }\n";
9900             pr "  %s[%s_len] = NULL;\n" n n;
9901         | Bool n
9902         | Int n
9903         | Int64 n ->
9904             pr "  %s = j%s;\n" n n
9905       ) (snd style);
9906
9907       (* Make the call. *)
9908       pr "  r = guestfs_%s " name;
9909       generate_c_call_args ~handle:"g" style;
9910       pr ";\n";
9911
9912       (* Release the parameters. *)
9913       List.iter (
9914         function
9915         | Pathname n
9916         | Device n | Dev_or_Path n
9917         | String n
9918         | FileIn n
9919         | FileOut n ->
9920             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9921         | OptString n ->
9922             pr "  if (j%s)\n" n;
9923             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9924         | StringList n | DeviceList n ->
9925             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9926             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9927               n;
9928             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9929             pr "  }\n";
9930             pr "  free (%s);\n" n
9931         | Bool n
9932         | Int n
9933         | Int64 n -> ()
9934       ) (snd style);
9935
9936       (* Check for errors. *)
9937       pr "  if (r == %s) {\n" error_code;
9938       pr "    throw_exception (env, guestfs_last_error (g));\n";
9939       pr "    return %s;\n" no_ret;
9940       pr "  }\n";
9941
9942       (* Return value. *)
9943       (match fst style with
9944        | RErr -> ()
9945        | RInt _ -> pr "  return (jint) r;\n"
9946        | RBool _ -> pr "  return (jboolean) r;\n"
9947        | RInt64 _ -> pr "  return (jlong) r;\n"
9948        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9949        | RConstOptString _ ->
9950            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9951        | RString _ ->
9952            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9953            pr "  free (r);\n";
9954            pr "  return jr;\n"
9955        | RStringList _ ->
9956            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9957            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9958            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9959            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9960            pr "  for (i = 0; i < r_len; ++i) {\n";
9961            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9962            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9963            pr "    free (r[i]);\n";
9964            pr "  }\n";
9965            pr "  free (r);\n";
9966            pr "  return jr;\n"
9967        | RStruct (_, typ) ->
9968            let jtyp = java_name_of_struct typ in
9969            let cols = cols_of_struct typ in
9970            generate_java_struct_return typ jtyp cols
9971        | RStructList (_, typ) ->
9972            let jtyp = java_name_of_struct typ in
9973            let cols = cols_of_struct typ in
9974            generate_java_struct_list_return typ jtyp cols
9975        | RHashtable _ ->
9976            (* XXX *)
9977            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9978            pr "  return NULL;\n"
9979        | RBufferOut _ ->
9980            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9981            pr "  free (r);\n";
9982            pr "  return jr;\n"
9983       );
9984
9985       pr "}\n";
9986       pr "\n"
9987   ) all_functions
9988
9989 and generate_java_struct_return typ jtyp cols =
9990   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9991   pr "  jr = (*env)->AllocObject (env, cl);\n";
9992   List.iter (
9993     function
9994     | name, FString ->
9995         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9996         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9997     | name, FUUID ->
9998         pr "  {\n";
9999         pr "    char s[33];\n";
10000         pr "    memcpy (s, r->%s, 32);\n" name;
10001         pr "    s[32] = 0;\n";
10002         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10003         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10004         pr "  }\n";
10005     | name, FBuffer ->
10006         pr "  {\n";
10007         pr "    int len = r->%s_len;\n" name;
10008         pr "    char s[len+1];\n";
10009         pr "    memcpy (s, r->%s, len);\n" name;
10010         pr "    s[len] = 0;\n";
10011         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10012         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10013         pr "  }\n";
10014     | name, (FBytes|FUInt64|FInt64) ->
10015         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10016         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10017     | name, (FUInt32|FInt32) ->
10018         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10019         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10020     | name, FOptPercent ->
10021         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10022         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10023     | name, FChar ->
10024         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10025         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10026   ) cols;
10027   pr "  free (r);\n";
10028   pr "  return jr;\n"
10029
10030 and generate_java_struct_list_return typ jtyp cols =
10031   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10032   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10033   pr "  for (i = 0; i < r->len; ++i) {\n";
10034   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10035   List.iter (
10036     function
10037     | name, FString ->
10038         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10039         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10040     | name, FUUID ->
10041         pr "    {\n";
10042         pr "      char s[33];\n";
10043         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10044         pr "      s[32] = 0;\n";
10045         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10046         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10047         pr "    }\n";
10048     | name, FBuffer ->
10049         pr "    {\n";
10050         pr "      int len = r->val[i].%s_len;\n" name;
10051         pr "      char s[len+1];\n";
10052         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10053         pr "      s[len] = 0;\n";
10054         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10055         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10056         pr "    }\n";
10057     | name, (FBytes|FUInt64|FInt64) ->
10058         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10059         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10060     | name, (FUInt32|FInt32) ->
10061         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10062         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10063     | name, FOptPercent ->
10064         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10065         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10066     | name, FChar ->
10067         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10068         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10069   ) cols;
10070   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10071   pr "  }\n";
10072   pr "  guestfs_free_%s_list (r);\n" typ;
10073   pr "  return jr;\n"
10074
10075 and generate_java_makefile_inc () =
10076   generate_header HashStyle GPLv2plus;
10077
10078   pr "java_built_sources = \\\n";
10079   List.iter (
10080     fun (typ, jtyp) ->
10081         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10082   ) java_structs;
10083   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10084
10085 and generate_haskell_hs () =
10086   generate_header HaskellStyle LGPLv2plus;
10087
10088   (* XXX We only know how to generate partial FFI for Haskell
10089    * at the moment.  Please help out!
10090    *)
10091   let can_generate style =
10092     match style with
10093     | RErr, _
10094     | RInt _, _
10095     | RInt64 _, _ -> true
10096     | RBool _, _
10097     | RConstString _, _
10098     | RConstOptString _, _
10099     | RString _, _
10100     | RStringList _, _
10101     | RStruct _, _
10102     | RStructList _, _
10103     | RHashtable _, _
10104     | RBufferOut _, _ -> false in
10105
10106   pr "\
10107 {-# INCLUDE <guestfs.h> #-}
10108 {-# LANGUAGE ForeignFunctionInterface #-}
10109
10110 module Guestfs (
10111   create";
10112
10113   (* List out the names of the actions we want to export. *)
10114   List.iter (
10115     fun (name, style, _, _, _, _, _) ->
10116       if can_generate style then pr ",\n  %s" name
10117   ) all_functions;
10118
10119   pr "
10120   ) where
10121
10122 -- Unfortunately some symbols duplicate ones already present
10123 -- in Prelude.  We don't know which, so we hard-code a list
10124 -- here.
10125 import Prelude hiding (truncate)
10126
10127 import Foreign
10128 import Foreign.C
10129 import Foreign.C.Types
10130 import IO
10131 import Control.Exception
10132 import Data.Typeable
10133
10134 data GuestfsS = GuestfsS            -- represents the opaque C struct
10135 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10136 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10137
10138 -- XXX define properly later XXX
10139 data PV = PV
10140 data VG = VG
10141 data LV = LV
10142 data IntBool = IntBool
10143 data Stat = Stat
10144 data StatVFS = StatVFS
10145 data Hashtable = Hashtable
10146
10147 foreign import ccall unsafe \"guestfs_create\" c_create
10148   :: IO GuestfsP
10149 foreign import ccall unsafe \"&guestfs_close\" c_close
10150   :: FunPtr (GuestfsP -> IO ())
10151 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10152   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10153
10154 create :: IO GuestfsH
10155 create = do
10156   p <- c_create
10157   c_set_error_handler p nullPtr nullPtr
10158   h <- newForeignPtr c_close p
10159   return h
10160
10161 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10162   :: GuestfsP -> IO CString
10163
10164 -- last_error :: GuestfsH -> IO (Maybe String)
10165 -- last_error h = do
10166 --   str <- withForeignPtr h (\\p -> c_last_error p)
10167 --   maybePeek peekCString str
10168
10169 last_error :: GuestfsH -> IO (String)
10170 last_error h = do
10171   str <- withForeignPtr h (\\p -> c_last_error p)
10172   if (str == nullPtr)
10173     then return \"no error\"
10174     else peekCString str
10175
10176 ";
10177
10178   (* Generate wrappers for each foreign function. *)
10179   List.iter (
10180     fun (name, style, _, _, _, _, _) ->
10181       if can_generate style then (
10182         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10183         pr "  :: ";
10184         generate_haskell_prototype ~handle:"GuestfsP" style;
10185         pr "\n";
10186         pr "\n";
10187         pr "%s :: " name;
10188         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10189         pr "\n";
10190         pr "%s %s = do\n" name
10191           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10192         pr "  r <- ";
10193         (* Convert pointer arguments using with* functions. *)
10194         List.iter (
10195           function
10196           | FileIn n
10197           | FileOut n
10198           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10199           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10200           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10201           | Bool _ | Int _ | Int64 _ -> ()
10202         ) (snd style);
10203         (* Convert integer arguments. *)
10204         let args =
10205           List.map (
10206             function
10207             | Bool n -> sprintf "(fromBool %s)" n
10208             | Int n -> sprintf "(fromIntegral %s)" n
10209             | Int64 n -> sprintf "(fromIntegral %s)" n
10210             | FileIn n | FileOut n
10211             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10212           ) (snd style) in
10213         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10214           (String.concat " " ("p" :: args));
10215         (match fst style with
10216          | RErr | RInt _ | RInt64 _ | RBool _ ->
10217              pr "  if (r == -1)\n";
10218              pr "    then do\n";
10219              pr "      err <- last_error h\n";
10220              pr "      fail err\n";
10221          | RConstString _ | RConstOptString _ | RString _
10222          | RStringList _ | RStruct _
10223          | RStructList _ | RHashtable _ | RBufferOut _ ->
10224              pr "  if (r == nullPtr)\n";
10225              pr "    then do\n";
10226              pr "      err <- last_error h\n";
10227              pr "      fail err\n";
10228         );
10229         (match fst style with
10230          | RErr ->
10231              pr "    else return ()\n"
10232          | RInt _ ->
10233              pr "    else return (fromIntegral r)\n"
10234          | RInt64 _ ->
10235              pr "    else return (fromIntegral r)\n"
10236          | RBool _ ->
10237              pr "    else return (toBool r)\n"
10238          | RConstString _
10239          | RConstOptString _
10240          | RString _
10241          | RStringList _
10242          | RStruct _
10243          | RStructList _
10244          | RHashtable _
10245          | RBufferOut _ ->
10246              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10247         );
10248         pr "\n";
10249       )
10250   ) all_functions
10251
10252 and generate_haskell_prototype ~handle ?(hs = false) style =
10253   pr "%s -> " handle;
10254   let string = if hs then "String" else "CString" in
10255   let int = if hs then "Int" else "CInt" in
10256   let bool = if hs then "Bool" else "CInt" in
10257   let int64 = if hs then "Integer" else "Int64" in
10258   List.iter (
10259     fun arg ->
10260       (match arg with
10261        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10262        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10263        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10264        | Bool _ -> pr "%s" bool
10265        | Int _ -> pr "%s" int
10266        | Int64 _ -> pr "%s" int
10267        | FileIn _ -> pr "%s" string
10268        | FileOut _ -> pr "%s" string
10269       );
10270       pr " -> ";
10271   ) (snd style);
10272   pr "IO (";
10273   (match fst style with
10274    | RErr -> if not hs then pr "CInt"
10275    | RInt _ -> pr "%s" int
10276    | RInt64 _ -> pr "%s" int64
10277    | RBool _ -> pr "%s" bool
10278    | RConstString _ -> pr "%s" string
10279    | RConstOptString _ -> pr "Maybe %s" string
10280    | RString _ -> pr "%s" string
10281    | RStringList _ -> pr "[%s]" string
10282    | RStruct (_, typ) ->
10283        let name = java_name_of_struct typ in
10284        pr "%s" name
10285    | RStructList (_, typ) ->
10286        let name = java_name_of_struct typ in
10287        pr "[%s]" name
10288    | RHashtable _ -> pr "Hashtable"
10289    | RBufferOut _ -> pr "%s" string
10290   );
10291   pr ")"
10292
10293 and generate_csharp () =
10294   generate_header CPlusPlusStyle LGPLv2plus;
10295
10296   (* XXX Make this configurable by the C# assembly users. *)
10297   let library = "libguestfs.so.0" in
10298
10299   pr "\
10300 // These C# bindings are highly experimental at present.
10301 //
10302 // Firstly they only work on Linux (ie. Mono).  In order to get them
10303 // to work on Windows (ie. .Net) you would need to port the library
10304 // itself to Windows first.
10305 //
10306 // The second issue is that some calls are known to be incorrect and
10307 // can cause Mono to segfault.  Particularly: calls which pass or
10308 // return string[], or return any structure value.  This is because
10309 // we haven't worked out the correct way to do this from C#.
10310 //
10311 // The third issue is that when compiling you get a lot of warnings.
10312 // We are not sure whether the warnings are important or not.
10313 //
10314 // Fourthly we do not routinely build or test these bindings as part
10315 // of the make && make check cycle, which means that regressions might
10316 // go unnoticed.
10317 //
10318 // Suggestions and patches are welcome.
10319
10320 // To compile:
10321 //
10322 // gmcs Libguestfs.cs
10323 // mono Libguestfs.exe
10324 //
10325 // (You'll probably want to add a Test class / static main function
10326 // otherwise this won't do anything useful).
10327
10328 using System;
10329 using System.IO;
10330 using System.Runtime.InteropServices;
10331 using System.Runtime.Serialization;
10332 using System.Collections;
10333
10334 namespace Guestfs
10335 {
10336   class Error : System.ApplicationException
10337   {
10338     public Error (string message) : base (message) {}
10339     protected Error (SerializationInfo info, StreamingContext context) {}
10340   }
10341
10342   class Guestfs
10343   {
10344     IntPtr _handle;
10345
10346     [DllImport (\"%s\")]
10347     static extern IntPtr guestfs_create ();
10348
10349     public Guestfs ()
10350     {
10351       _handle = guestfs_create ();
10352       if (_handle == IntPtr.Zero)
10353         throw new Error (\"could not create guestfs handle\");
10354     }
10355
10356     [DllImport (\"%s\")]
10357     static extern void guestfs_close (IntPtr h);
10358
10359     ~Guestfs ()
10360     {
10361       guestfs_close (_handle);
10362     }
10363
10364     [DllImport (\"%s\")]
10365     static extern string guestfs_last_error (IntPtr h);
10366
10367 " library library library;
10368
10369   (* Generate C# structure bindings.  We prefix struct names with
10370    * underscore because C# cannot have conflicting struct names and
10371    * method names (eg. "class stat" and "stat").
10372    *)
10373   List.iter (
10374     fun (typ, cols) ->
10375       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10376       pr "    public class _%s {\n" typ;
10377       List.iter (
10378         function
10379         | name, FChar -> pr "      char %s;\n" name
10380         | name, FString -> pr "      string %s;\n" name
10381         | name, FBuffer ->
10382             pr "      uint %s_len;\n" name;
10383             pr "      string %s;\n" name
10384         | name, FUUID ->
10385             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10386             pr "      string %s;\n" name
10387         | name, FUInt32 -> pr "      uint %s;\n" name
10388         | name, FInt32 -> pr "      int %s;\n" name
10389         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10390         | name, FInt64 -> pr "      long %s;\n" name
10391         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10392       ) cols;
10393       pr "    }\n";
10394       pr "\n"
10395   ) structs;
10396
10397   (* Generate C# function bindings. *)
10398   List.iter (
10399     fun (name, style, _, _, _, shortdesc, _) ->
10400       let rec csharp_return_type () =
10401         match fst style with
10402         | RErr -> "void"
10403         | RBool n -> "bool"
10404         | RInt n -> "int"
10405         | RInt64 n -> "long"
10406         | RConstString n
10407         | RConstOptString n
10408         | RString n
10409         | RBufferOut n -> "string"
10410         | RStruct (_,n) -> "_" ^ n
10411         | RHashtable n -> "Hashtable"
10412         | RStringList n -> "string[]"
10413         | RStructList (_,n) -> sprintf "_%s[]" n
10414
10415       and c_return_type () =
10416         match fst style with
10417         | RErr
10418         | RBool _
10419         | RInt _ -> "int"
10420         | RInt64 _ -> "long"
10421         | RConstString _
10422         | RConstOptString _
10423         | RString _
10424         | RBufferOut _ -> "string"
10425         | RStruct (_,n) -> "_" ^ n
10426         | RHashtable _
10427         | RStringList _ -> "string[]"
10428         | RStructList (_,n) -> sprintf "_%s[]" n
10429
10430       and c_error_comparison () =
10431         match fst style with
10432         | RErr
10433         | RBool _
10434         | RInt _
10435         | RInt64 _ -> "== -1"
10436         | RConstString _
10437         | RConstOptString _
10438         | RString _
10439         | RBufferOut _
10440         | RStruct (_,_)
10441         | RHashtable _
10442         | RStringList _
10443         | RStructList (_,_) -> "== null"
10444
10445       and generate_extern_prototype () =
10446         pr "    static extern %s guestfs_%s (IntPtr h"
10447           (c_return_type ()) name;
10448         List.iter (
10449           function
10450           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10451           | FileIn n | FileOut n ->
10452               pr ", [In] string %s" n
10453           | StringList n | DeviceList n ->
10454               pr ", [In] string[] %s" n
10455           | Bool n ->
10456               pr ", bool %s" n
10457           | Int n ->
10458               pr ", int %s" n
10459           | Int64 n ->
10460               pr ", long %s" n
10461         ) (snd style);
10462         pr ");\n"
10463
10464       and generate_public_prototype () =
10465         pr "    public %s %s (" (csharp_return_type ()) name;
10466         let comma = ref false in
10467         let next () =
10468           if !comma then pr ", ";
10469           comma := true
10470         in
10471         List.iter (
10472           function
10473           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10474           | FileIn n | FileOut n ->
10475               next (); pr "string %s" n
10476           | StringList n | DeviceList n ->
10477               next (); pr "string[] %s" n
10478           | Bool n ->
10479               next (); pr "bool %s" n
10480           | Int n ->
10481               next (); pr "int %s" n
10482           | Int64 n ->
10483               next (); pr "long %s" n
10484         ) (snd style);
10485         pr ")\n"
10486
10487       and generate_call () =
10488         pr "guestfs_%s (_handle" name;
10489         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10490         pr ");\n";
10491       in
10492
10493       pr "    [DllImport (\"%s\")]\n" library;
10494       generate_extern_prototype ();
10495       pr "\n";
10496       pr "    /// <summary>\n";
10497       pr "    /// %s\n" shortdesc;
10498       pr "    /// </summary>\n";
10499       generate_public_prototype ();
10500       pr "    {\n";
10501       pr "      %s r;\n" (c_return_type ());
10502       pr "      r = ";
10503       generate_call ();
10504       pr "      if (r %s)\n" (c_error_comparison ());
10505       pr "        throw new Error (guestfs_last_error (_handle));\n";
10506       (match fst style with
10507        | RErr -> ()
10508        | RBool _ ->
10509            pr "      return r != 0 ? true : false;\n"
10510        | RHashtable _ ->
10511            pr "      Hashtable rr = new Hashtable ();\n";
10512            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10513            pr "        rr.Add (r[i], r[i+1]);\n";
10514            pr "      return rr;\n"
10515        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10516        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10517        | RStructList _ ->
10518            pr "      return r;\n"
10519       );
10520       pr "    }\n";
10521       pr "\n";
10522   ) all_functions_sorted;
10523
10524   pr "  }
10525 }
10526 "
10527
10528 and generate_bindtests () =
10529   generate_header CStyle LGPLv2plus;
10530
10531   pr "\
10532 #include <stdio.h>
10533 #include <stdlib.h>
10534 #include <inttypes.h>
10535 #include <string.h>
10536
10537 #include \"guestfs.h\"
10538 #include \"guestfs-internal.h\"
10539 #include \"guestfs-internal-actions.h\"
10540 #include \"guestfs_protocol.h\"
10541
10542 #define error guestfs_error
10543 #define safe_calloc guestfs_safe_calloc
10544 #define safe_malloc guestfs_safe_malloc
10545
10546 static void
10547 print_strings (char *const *argv)
10548 {
10549   int argc;
10550
10551   printf (\"[\");
10552   for (argc = 0; argv[argc] != NULL; ++argc) {
10553     if (argc > 0) printf (\", \");
10554     printf (\"\\\"%%s\\\"\", argv[argc]);
10555   }
10556   printf (\"]\\n\");
10557 }
10558
10559 /* The test0 function prints its parameters to stdout. */
10560 ";
10561
10562   let test0, tests =
10563     match test_functions with
10564     | [] -> assert false
10565     | test0 :: tests -> test0, tests in
10566
10567   let () =
10568     let (name, style, _, _, _, _, _) = test0 in
10569     generate_prototype ~extern:false ~semicolon:false ~newline:true
10570       ~handle:"g" ~prefix:"guestfs__" name style;
10571     pr "{\n";
10572     List.iter (
10573       function
10574       | Pathname n
10575       | Device n | Dev_or_Path n
10576       | String n
10577       | FileIn n
10578       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10579       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10580       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10581       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10582       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10583       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10584     ) (snd style);
10585     pr "  /* Java changes stdout line buffering so we need this: */\n";
10586     pr "  fflush (stdout);\n";
10587     pr "  return 0;\n";
10588     pr "}\n";
10589     pr "\n" in
10590
10591   List.iter (
10592     fun (name, style, _, _, _, _, _) ->
10593       if String.sub name (String.length name - 3) 3 <> "err" then (
10594         pr "/* Test normal return. */\n";
10595         generate_prototype ~extern:false ~semicolon:false ~newline:true
10596           ~handle:"g" ~prefix:"guestfs__" name style;
10597         pr "{\n";
10598         (match fst style with
10599          | RErr ->
10600              pr "  return 0;\n"
10601          | RInt _ ->
10602              pr "  int r;\n";
10603              pr "  sscanf (val, \"%%d\", &r);\n";
10604              pr "  return r;\n"
10605          | RInt64 _ ->
10606              pr "  int64_t r;\n";
10607              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10608              pr "  return r;\n"
10609          | RBool _ ->
10610              pr "  return STREQ (val, \"true\");\n"
10611          | RConstString _
10612          | RConstOptString _ ->
10613              (* Can't return the input string here.  Return a static
10614               * string so we ensure we get a segfault if the caller
10615               * tries to free it.
10616               *)
10617              pr "  return \"static string\";\n"
10618          | RString _ ->
10619              pr "  return strdup (val);\n"
10620          | RStringList _ ->
10621              pr "  char **strs;\n";
10622              pr "  int n, i;\n";
10623              pr "  sscanf (val, \"%%d\", &n);\n";
10624              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10625              pr "  for (i = 0; i < n; ++i) {\n";
10626              pr "    strs[i] = safe_malloc (g, 16);\n";
10627              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10628              pr "  }\n";
10629              pr "  strs[n] = NULL;\n";
10630              pr "  return strs;\n"
10631          | RStruct (_, typ) ->
10632              pr "  struct guestfs_%s *r;\n" typ;
10633              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10634              pr "  return r;\n"
10635          | RStructList (_, typ) ->
10636              pr "  struct guestfs_%s_list *r;\n" typ;
10637              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10638              pr "  sscanf (val, \"%%d\", &r->len);\n";
10639              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10640              pr "  return r;\n"
10641          | RHashtable _ ->
10642              pr "  char **strs;\n";
10643              pr "  int n, i;\n";
10644              pr "  sscanf (val, \"%%d\", &n);\n";
10645              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10646              pr "  for (i = 0; i < n; ++i) {\n";
10647              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10648              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10649              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10650              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10651              pr "  }\n";
10652              pr "  strs[n*2] = NULL;\n";
10653              pr "  return strs;\n"
10654          | RBufferOut _ ->
10655              pr "  return strdup (val);\n"
10656         );
10657         pr "}\n";
10658         pr "\n"
10659       ) else (
10660         pr "/* Test error return. */\n";
10661         generate_prototype ~extern:false ~semicolon:false ~newline:true
10662           ~handle:"g" ~prefix:"guestfs__" name style;
10663         pr "{\n";
10664         pr "  error (g, \"error\");\n";
10665         (match fst style with
10666          | RErr | RInt _ | RInt64 _ | RBool _ ->
10667              pr "  return -1;\n"
10668          | RConstString _ | RConstOptString _
10669          | RString _ | RStringList _ | RStruct _
10670          | RStructList _
10671          | RHashtable _
10672          | RBufferOut _ ->
10673              pr "  return NULL;\n"
10674         );
10675         pr "}\n";
10676         pr "\n"
10677       )
10678   ) tests
10679
10680 and generate_ocaml_bindtests () =
10681   generate_header OCamlStyle GPLv2plus;
10682
10683   pr "\
10684 let () =
10685   let g = Guestfs.create () in
10686 ";
10687
10688   let mkargs args =
10689     String.concat " " (
10690       List.map (
10691         function
10692         | CallString s -> "\"" ^ s ^ "\""
10693         | CallOptString None -> "None"
10694         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10695         | CallStringList xs ->
10696             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10697         | CallInt i when i >= 0 -> string_of_int i
10698         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10699         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10700         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10701         | CallBool b -> string_of_bool b
10702       ) args
10703     )
10704   in
10705
10706   generate_lang_bindtests (
10707     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10708   );
10709
10710   pr "print_endline \"EOF\"\n"
10711
10712 and generate_perl_bindtests () =
10713   pr "#!/usr/bin/perl -w\n";
10714   generate_header HashStyle GPLv2plus;
10715
10716   pr "\
10717 use strict;
10718
10719 use Sys::Guestfs;
10720
10721 my $g = Sys::Guestfs->new ();
10722 ";
10723
10724   let mkargs args =
10725     String.concat ", " (
10726       List.map (
10727         function
10728         | CallString s -> "\"" ^ s ^ "\""
10729         | CallOptString None -> "undef"
10730         | CallOptString (Some s) -> sprintf "\"%s\"" s
10731         | CallStringList xs ->
10732             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10733         | CallInt i -> string_of_int i
10734         | CallInt64 i -> Int64.to_string i
10735         | CallBool b -> if b then "1" else "0"
10736       ) args
10737     )
10738   in
10739
10740   generate_lang_bindtests (
10741     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10742   );
10743
10744   pr "print \"EOF\\n\"\n"
10745
10746 and generate_python_bindtests () =
10747   generate_header HashStyle GPLv2plus;
10748
10749   pr "\
10750 import guestfs
10751
10752 g = guestfs.GuestFS ()
10753 ";
10754
10755   let mkargs args =
10756     String.concat ", " (
10757       List.map (
10758         function
10759         | CallString s -> "\"" ^ s ^ "\""
10760         | CallOptString None -> "None"
10761         | CallOptString (Some s) -> sprintf "\"%s\"" s
10762         | CallStringList xs ->
10763             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10764         | CallInt i -> string_of_int i
10765         | CallInt64 i -> Int64.to_string i
10766         | CallBool b -> if b then "1" else "0"
10767       ) args
10768     )
10769   in
10770
10771   generate_lang_bindtests (
10772     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10773   );
10774
10775   pr "print \"EOF\"\n"
10776
10777 and generate_ruby_bindtests () =
10778   generate_header HashStyle GPLv2plus;
10779
10780   pr "\
10781 require 'guestfs'
10782
10783 g = Guestfs::create()
10784 ";
10785
10786   let mkargs args =
10787     String.concat ", " (
10788       List.map (
10789         function
10790         | CallString s -> "\"" ^ s ^ "\""
10791         | CallOptString None -> "nil"
10792         | CallOptString (Some s) -> sprintf "\"%s\"" s
10793         | CallStringList xs ->
10794             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10795         | CallInt i -> string_of_int i
10796         | CallInt64 i -> Int64.to_string i
10797         | CallBool b -> string_of_bool b
10798       ) args
10799     )
10800   in
10801
10802   generate_lang_bindtests (
10803     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10804   );
10805
10806   pr "print \"EOF\\n\"\n"
10807
10808 and generate_java_bindtests () =
10809   generate_header CStyle GPLv2plus;
10810
10811   pr "\
10812 import com.redhat.et.libguestfs.*;
10813
10814 public class Bindtests {
10815     public static void main (String[] argv)
10816     {
10817         try {
10818             GuestFS g = new GuestFS ();
10819 ";
10820
10821   let mkargs args =
10822     String.concat ", " (
10823       List.map (
10824         function
10825         | CallString s -> "\"" ^ s ^ "\""
10826         | CallOptString None -> "null"
10827         | CallOptString (Some s) -> sprintf "\"%s\"" s
10828         | CallStringList xs ->
10829             "new String[]{" ^
10830               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10831         | CallInt i -> string_of_int i
10832         | CallInt64 i -> Int64.to_string i
10833         | CallBool b -> string_of_bool b
10834       ) args
10835     )
10836   in
10837
10838   generate_lang_bindtests (
10839     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10840   );
10841
10842   pr "
10843             System.out.println (\"EOF\");
10844         }
10845         catch (Exception exn) {
10846             System.err.println (exn);
10847             System.exit (1);
10848         }
10849     }
10850 }
10851 "
10852
10853 and generate_haskell_bindtests () =
10854   generate_header HaskellStyle GPLv2plus;
10855
10856   pr "\
10857 module Bindtests where
10858 import qualified Guestfs
10859
10860 main = do
10861   g <- Guestfs.create
10862 ";
10863
10864   let mkargs args =
10865     String.concat " " (
10866       List.map (
10867         function
10868         | CallString s -> "\"" ^ s ^ "\""
10869         | CallOptString None -> "Nothing"
10870         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10871         | CallStringList xs ->
10872             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10873         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10874         | CallInt i -> string_of_int i
10875         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10876         | CallInt64 i -> Int64.to_string i
10877         | CallBool true -> "True"
10878         | CallBool false -> "False"
10879       ) args
10880     )
10881   in
10882
10883   generate_lang_bindtests (
10884     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10885   );
10886
10887   pr "  putStrLn \"EOF\"\n"
10888
10889 (* Language-independent bindings tests - we do it this way to
10890  * ensure there is parity in testing bindings across all languages.
10891  *)
10892 and generate_lang_bindtests call =
10893   call "test0" [CallString "abc"; CallOptString (Some "def");
10894                 CallStringList []; CallBool false;
10895                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10896   call "test0" [CallString "abc"; CallOptString None;
10897                 CallStringList []; CallBool false;
10898                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10899   call "test0" [CallString ""; CallOptString (Some "def");
10900                 CallStringList []; CallBool false;
10901                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10902   call "test0" [CallString ""; CallOptString (Some "");
10903                 CallStringList []; CallBool false;
10904                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10905   call "test0" [CallString "abc"; CallOptString (Some "def");
10906                 CallStringList ["1"]; CallBool false;
10907                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10908   call "test0" [CallString "abc"; CallOptString (Some "def");
10909                 CallStringList ["1"; "2"]; CallBool false;
10910                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10911   call "test0" [CallString "abc"; CallOptString (Some "def");
10912                 CallStringList ["1"]; CallBool true;
10913                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10914   call "test0" [CallString "abc"; CallOptString (Some "def");
10915                 CallStringList ["1"]; CallBool false;
10916                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10917   call "test0" [CallString "abc"; CallOptString (Some "def");
10918                 CallStringList ["1"]; CallBool false;
10919                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10920   call "test0" [CallString "abc"; CallOptString (Some "def");
10921                 CallStringList ["1"]; CallBool false;
10922                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10923   call "test0" [CallString "abc"; CallOptString (Some "def");
10924                 CallStringList ["1"]; CallBool false;
10925                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10926   call "test0" [CallString "abc"; CallOptString (Some "def");
10927                 CallStringList ["1"]; CallBool false;
10928                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10929   call "test0" [CallString "abc"; CallOptString (Some "def");
10930                 CallStringList ["1"]; CallBool false;
10931                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10932
10933 (* XXX Add here tests of the return and error functions. *)
10934
10935 (* Code to generator bindings for virt-inspector.  Currently only
10936  * implemented for OCaml code (for virt-p2v 2.0).
10937  *)
10938 let rng_input = "inspector/virt-inspector.rng"
10939
10940 (* Read the input file and parse it into internal structures.  This is
10941  * by no means a complete RELAX NG parser, but is just enough to be
10942  * able to parse the specific input file.
10943  *)
10944 type rng =
10945   | Element of string * rng list        (* <element name=name/> *)
10946   | Attribute of string * rng list        (* <attribute name=name/> *)
10947   | Interleave of rng list                (* <interleave/> *)
10948   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10949   | OneOrMore of rng                        (* <oneOrMore/> *)
10950   | Optional of rng                        (* <optional/> *)
10951   | Choice of string list                (* <choice><value/>*</choice> *)
10952   | Value of string                        (* <value>str</value> *)
10953   | Text                                (* <text/> *)
10954
10955 let rec string_of_rng = function
10956   | Element (name, xs) ->
10957       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10958   | Attribute (name, xs) ->
10959       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10960   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10961   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10962   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10963   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10964   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10965   | Value value -> "Value \"" ^ value ^ "\""
10966   | Text -> "Text"
10967
10968 and string_of_rng_list xs =
10969   String.concat ", " (List.map string_of_rng xs)
10970
10971 let rec parse_rng ?defines context = function
10972   | [] -> []
10973   | Xml.Element ("element", ["name", name], children) :: rest ->
10974       Element (name, parse_rng ?defines context children)
10975       :: parse_rng ?defines context rest
10976   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10977       Attribute (name, parse_rng ?defines context children)
10978       :: parse_rng ?defines context rest
10979   | Xml.Element ("interleave", [], children) :: rest ->
10980       Interleave (parse_rng ?defines context children)
10981       :: parse_rng ?defines context rest
10982   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10983       let rng = parse_rng ?defines context [child] in
10984       (match rng with
10985        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10986        | _ ->
10987            failwithf "%s: <zeroOrMore> contains more than one child element"
10988              context
10989       )
10990   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10991       let rng = parse_rng ?defines context [child] in
10992       (match rng with
10993        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10994        | _ ->
10995            failwithf "%s: <oneOrMore> contains more than one child element"
10996              context
10997       )
10998   | Xml.Element ("optional", [], [child]) :: rest ->
10999       let rng = parse_rng ?defines context [child] in
11000       (match rng with
11001        | [child] -> Optional child :: parse_rng ?defines context rest
11002        | _ ->
11003            failwithf "%s: <optional> contains more than one child element"
11004              context
11005       )
11006   | Xml.Element ("choice", [], children) :: rest ->
11007       let values = List.map (
11008         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11009         | _ ->
11010             failwithf "%s: can't handle anything except <value> in <choice>"
11011               context
11012       ) children in
11013       Choice values
11014       :: parse_rng ?defines context rest
11015   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11016       Value value :: parse_rng ?defines context rest
11017   | Xml.Element ("text", [], []) :: rest ->
11018       Text :: parse_rng ?defines context rest
11019   | Xml.Element ("ref", ["name", name], []) :: rest ->
11020       (* Look up the reference.  Because of limitations in this parser,
11021        * we can't handle arbitrarily nested <ref> yet.  You can only
11022        * use <ref> from inside <start>.
11023        *)
11024       (match defines with
11025        | None ->
11026            failwithf "%s: contains <ref>, but no refs are defined yet" context
11027        | Some map ->
11028            let rng = StringMap.find name map in
11029            rng @ parse_rng ?defines context rest
11030       )
11031   | x :: _ ->
11032       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11033
11034 let grammar =
11035   let xml = Xml.parse_file rng_input in
11036   match xml with
11037   | Xml.Element ("grammar", _,
11038                  Xml.Element ("start", _, gram) :: defines) ->
11039       (* The <define/> elements are referenced in the <start> section,
11040        * so build a map of those first.
11041        *)
11042       let defines = List.fold_left (
11043         fun map ->
11044           function Xml.Element ("define", ["name", name], defn) ->
11045             StringMap.add name defn map
11046           | _ ->
11047               failwithf "%s: expected <define name=name/>" rng_input
11048       ) StringMap.empty defines in
11049       let defines = StringMap.mapi parse_rng defines in
11050
11051       (* Parse the <start> clause, passing the defines. *)
11052       parse_rng ~defines "<start>" gram
11053   | _ ->
11054       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11055         rng_input
11056
11057 let name_of_field = function
11058   | Element (name, _) | Attribute (name, _)
11059   | ZeroOrMore (Element (name, _))
11060   | OneOrMore (Element (name, _))
11061   | Optional (Element (name, _)) -> name
11062   | Optional (Attribute (name, _)) -> name
11063   | Text -> (* an unnamed field in an element *)
11064       "data"
11065   | rng ->
11066       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11067
11068 (* At the moment this function only generates OCaml types.  However we
11069  * should parameterize it later so it can generate types/structs in a
11070  * variety of languages.
11071  *)
11072 let generate_types xs =
11073   (* A simple type is one that can be printed out directly, eg.
11074    * "string option".  A complex type is one which has a name and has
11075    * to be defined via another toplevel definition, eg. a struct.
11076    *
11077    * generate_type generates code for either simple or complex types.
11078    * In the simple case, it returns the string ("string option").  In
11079    * the complex case, it returns the name ("mountpoint").  In the
11080    * complex case it has to print out the definition before returning,
11081    * so it should only be called when we are at the beginning of a
11082    * new line (BOL context).
11083    *)
11084   let rec generate_type = function
11085     | Text ->                                (* string *)
11086         "string", true
11087     | Choice values ->                        (* [`val1|`val2|...] *)
11088         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11089     | ZeroOrMore rng ->                        (* <rng> list *)
11090         let t, is_simple = generate_type rng in
11091         t ^ " list (* 0 or more *)", is_simple
11092     | OneOrMore rng ->                        (* <rng> list *)
11093         let t, is_simple = generate_type rng in
11094         t ^ " list (* 1 or more *)", is_simple
11095                                         (* virt-inspector hack: bool *)
11096     | Optional (Attribute (name, [Value "1"])) ->
11097         "bool", true
11098     | Optional rng ->                        (* <rng> list *)
11099         let t, is_simple = generate_type rng in
11100         t ^ " option", is_simple
11101                                         (* type name = { fields ... } *)
11102     | Element (name, fields) when is_attrs_interleave fields ->
11103         generate_type_struct name (get_attrs_interleave fields)
11104     | Element (name, [field])                (* type name = field *)
11105     | Attribute (name, [field]) ->
11106         let t, is_simple = generate_type field in
11107         if is_simple then (t, true)
11108         else (
11109           pr "type %s = %s\n" name t;
11110           name, false
11111         )
11112     | Element (name, fields) ->              (* type name = { fields ... } *)
11113         generate_type_struct name fields
11114     | rng ->
11115         failwithf "generate_type failed at: %s" (string_of_rng rng)
11116
11117   and is_attrs_interleave = function
11118     | [Interleave _] -> true
11119     | Attribute _ :: fields -> is_attrs_interleave fields
11120     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11121     | _ -> false
11122
11123   and get_attrs_interleave = function
11124     | [Interleave fields] -> fields
11125     | ((Attribute _) as field) :: fields
11126     | ((Optional (Attribute _)) as field) :: fields ->
11127         field :: get_attrs_interleave fields
11128     | _ -> assert false
11129
11130   and generate_types xs =
11131     List.iter (fun x -> ignore (generate_type x)) xs
11132
11133   and generate_type_struct name fields =
11134     (* Calculate the types of the fields first.  We have to do this
11135      * before printing anything so we are still in BOL context.
11136      *)
11137     let types = List.map fst (List.map generate_type fields) in
11138
11139     (* Special case of a struct containing just a string and another
11140      * field.  Turn it into an assoc list.
11141      *)
11142     match types with
11143     | ["string"; other] ->
11144         let fname1, fname2 =
11145           match fields with
11146           | [f1; f2] -> name_of_field f1, name_of_field f2
11147           | _ -> assert false in
11148         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11149         name, false
11150
11151     | types ->
11152         pr "type %s = {\n" name;
11153         List.iter (
11154           fun (field, ftype) ->
11155             let fname = name_of_field field in
11156             pr "  %s_%s : %s;\n" name fname ftype
11157         ) (List.combine fields types);
11158         pr "}\n";
11159         (* Return the name of this type, and
11160          * false because it's not a simple type.
11161          *)
11162         name, false
11163   in
11164
11165   generate_types xs
11166
11167 let generate_parsers xs =
11168   (* As for generate_type above, generate_parser makes a parser for
11169    * some type, and returns the name of the parser it has generated.
11170    * Because it (may) need to print something, it should always be
11171    * called in BOL context.
11172    *)
11173   let rec generate_parser = function
11174     | Text ->                                (* string *)
11175         "string_child_or_empty"
11176     | Choice values ->                        (* [`val1|`val2|...] *)
11177         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11178           (String.concat "|"
11179              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11180     | ZeroOrMore rng ->                        (* <rng> list *)
11181         let pa = generate_parser rng in
11182         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11183     | OneOrMore rng ->                        (* <rng> list *)
11184         let pa = generate_parser rng in
11185         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11186                                         (* virt-inspector hack: bool *)
11187     | Optional (Attribute (name, [Value "1"])) ->
11188         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11189     | Optional rng ->                        (* <rng> list *)
11190         let pa = generate_parser rng in
11191         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11192                                         (* type name = { fields ... } *)
11193     | Element (name, fields) when is_attrs_interleave fields ->
11194         generate_parser_struct name (get_attrs_interleave fields)
11195     | Element (name, [field]) ->        (* type name = field *)
11196         let pa = generate_parser field in
11197         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11198         pr "let %s =\n" parser_name;
11199         pr "  %s\n" pa;
11200         pr "let parse_%s = %s\n" name parser_name;
11201         parser_name
11202     | Attribute (name, [field]) ->
11203         let pa = generate_parser field in
11204         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11205         pr "let %s =\n" parser_name;
11206         pr "  %s\n" pa;
11207         pr "let parse_%s = %s\n" name parser_name;
11208         parser_name
11209     | Element (name, fields) ->              (* type name = { fields ... } *)
11210         generate_parser_struct name ([], fields)
11211     | rng ->
11212         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11213
11214   and is_attrs_interleave = function
11215     | [Interleave _] -> true
11216     | Attribute _ :: fields -> is_attrs_interleave fields
11217     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11218     | _ -> false
11219
11220   and get_attrs_interleave = function
11221     | [Interleave fields] -> [], fields
11222     | ((Attribute _) as field) :: fields
11223     | ((Optional (Attribute _)) as field) :: fields ->
11224         let attrs, interleaves = get_attrs_interleave fields in
11225         (field :: attrs), interleaves
11226     | _ -> assert false
11227
11228   and generate_parsers xs =
11229     List.iter (fun x -> ignore (generate_parser x)) xs
11230
11231   and generate_parser_struct name (attrs, interleaves) =
11232     (* Generate parsers for the fields first.  We have to do this
11233      * before printing anything so we are still in BOL context.
11234      *)
11235     let fields = attrs @ interleaves in
11236     let pas = List.map generate_parser fields in
11237
11238     (* Generate an intermediate tuple from all the fields first.
11239      * If the type is just a string + another field, then we will
11240      * return this directly, otherwise it is turned into a record.
11241      *
11242      * RELAX NG note: This code treats <interleave> and plain lists of
11243      * fields the same.  In other words, it doesn't bother enforcing
11244      * any ordering of fields in the XML.
11245      *)
11246     pr "let parse_%s x =\n" name;
11247     pr "  let t = (\n    ";
11248     let comma = ref false in
11249     List.iter (
11250       fun x ->
11251         if !comma then pr ",\n    ";
11252         comma := true;
11253         match x with
11254         | Optional (Attribute (fname, [field])), pa ->
11255             pr "%s x" pa
11256         | Optional (Element (fname, [field])), pa ->
11257             pr "%s (optional_child %S x)" pa fname
11258         | Attribute (fname, [Text]), _ ->
11259             pr "attribute %S x" fname
11260         | (ZeroOrMore _ | OneOrMore _), pa ->
11261             pr "%s x" pa
11262         | Text, pa ->
11263             pr "%s x" pa
11264         | (field, pa) ->
11265             let fname = name_of_field field in
11266             pr "%s (child %S x)" pa fname
11267     ) (List.combine fields pas);
11268     pr "\n  ) in\n";
11269
11270     (match fields with
11271      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11272          pr "  t\n"
11273
11274      | _ ->
11275          pr "  (Obj.magic t : %s)\n" name
11276 (*
11277          List.iter (
11278            function
11279            | (Optional (Attribute (fname, [field])), pa) ->
11280                pr "  %s_%s =\n" name fname;
11281                pr "    %s x;\n" pa
11282            | (Optional (Element (fname, [field])), pa) ->
11283                pr "  %s_%s =\n" name fname;
11284                pr "    (let x = optional_child %S x in\n" fname;
11285                pr "     %s x);\n" pa
11286            | (field, pa) ->
11287                let fname = name_of_field field in
11288                pr "  %s_%s =\n" name fname;
11289                pr "    (let x = child %S x in\n" fname;
11290                pr "     %s x);\n" pa
11291          ) (List.combine fields pas);
11292          pr "}\n"
11293 *)
11294     );
11295     sprintf "parse_%s" name
11296   in
11297
11298   generate_parsers xs
11299
11300 (* Generate ocaml/guestfs_inspector.mli. *)
11301 let generate_ocaml_inspector_mli () =
11302   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11303
11304   pr "\
11305 (** This is an OCaml language binding to the external [virt-inspector]
11306     program.
11307
11308     For more information, please read the man page [virt-inspector(1)].
11309 *)
11310
11311 ";
11312
11313   generate_types grammar;
11314   pr "(** The nested information returned from the {!inspect} function. *)\n";
11315   pr "\n";
11316
11317   pr "\
11318 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11319 (** To inspect a libvirt domain called [name], pass a singleton
11320     list: [inspect [name]].  When using libvirt only, you may
11321     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11322
11323     To inspect a disk image or images, pass a list of the filenames
11324     of the disk images: [inspect filenames]
11325
11326     This function inspects the given guest or disk images and
11327     returns a list of operating system(s) found and a large amount
11328     of information about them.  In the vast majority of cases,
11329     a virtual machine only contains a single operating system.
11330
11331     If the optional [~xml] parameter is given, then this function
11332     skips running the external virt-inspector program and just
11333     parses the given XML directly (which is expected to be XML
11334     produced from a previous run of virt-inspector).  The list of
11335     names and connect URI are ignored in this case.
11336
11337     This function can throw a wide variety of exceptions, for example
11338     if the external virt-inspector program cannot be found, or if
11339     it doesn't generate valid XML.
11340 *)
11341 "
11342
11343 (* Generate ocaml/guestfs_inspector.ml. *)
11344 let generate_ocaml_inspector_ml () =
11345   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11346
11347   pr "open Unix\n";
11348   pr "\n";
11349
11350   generate_types grammar;
11351   pr "\n";
11352
11353   pr "\
11354 (* Misc functions which are used by the parser code below. *)
11355 let first_child = function
11356   | Xml.Element (_, _, c::_) -> c
11357   | Xml.Element (name, _, []) ->
11358       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11359   | Xml.PCData str ->
11360       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11361
11362 let string_child_or_empty = function
11363   | Xml.Element (_, _, [Xml.PCData s]) -> s
11364   | Xml.Element (_, _, []) -> \"\"
11365   | Xml.Element (x, _, _) ->
11366       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11367                 x ^ \" instead\")
11368   | Xml.PCData str ->
11369       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11370
11371 let optional_child name xml =
11372   let children = Xml.children xml in
11373   try
11374     Some (List.find (function
11375                      | Xml.Element (n, _, _) when n = name -> true
11376                      | _ -> false) children)
11377   with
11378     Not_found -> None
11379
11380 let child name xml =
11381   match optional_child name xml with
11382   | Some c -> c
11383   | None ->
11384       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11385
11386 let attribute name xml =
11387   try Xml.attrib xml name
11388   with Xml.No_attribute _ ->
11389     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11390
11391 ";
11392
11393   generate_parsers grammar;
11394   pr "\n";
11395
11396   pr "\
11397 (* Run external virt-inspector, then use parser to parse the XML. *)
11398 let inspect ?connect ?xml names =
11399   let xml =
11400     match xml with
11401     | None ->
11402         if names = [] then invalid_arg \"inspect: no names given\";
11403         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11404           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11405           names in
11406         let cmd = List.map Filename.quote cmd in
11407         let cmd = String.concat \" \" cmd in
11408         let chan = open_process_in cmd in
11409         let xml = Xml.parse_in chan in
11410         (match close_process_in chan with
11411          | WEXITED 0 -> ()
11412          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11413          | WSIGNALED i | WSTOPPED i ->
11414              failwith (\"external virt-inspector command died or stopped on sig \" ^
11415                        string_of_int i)
11416         );
11417         xml
11418     | Some doc ->
11419         Xml.parse_string doc in
11420   parse_operatingsystems xml
11421 "
11422
11423 (* This is used to generate the src/MAX_PROC_NR file which
11424  * contains the maximum procedure number, a surrogate for the
11425  * ABI version number.  See src/Makefile.am for the details.
11426  *)
11427 and generate_max_proc_nr () =
11428   let proc_nrs = List.map (
11429     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11430   ) daemon_functions in
11431
11432   let max_proc_nr = List.fold_left max 0 proc_nrs in
11433
11434   pr "%d\n" max_proc_nr
11435
11436 let output_to filename k =
11437   let filename_new = filename ^ ".new" in
11438   chan := open_out filename_new;
11439   k ();
11440   close_out !chan;
11441   chan := Pervasives.stdout;
11442
11443   (* Is the new file different from the current file? *)
11444   if Sys.file_exists filename && files_equal filename filename_new then
11445     unlink filename_new                 (* same, so skip it *)
11446   else (
11447     (* different, overwrite old one *)
11448     (try chmod filename 0o644 with Unix_error _ -> ());
11449     rename filename_new filename;
11450     chmod filename 0o444;
11451     printf "written %s\n%!" filename;
11452   )
11453
11454 let perror msg = function
11455   | Unix_error (err, _, _) ->
11456       eprintf "%s: %s\n" msg (error_message err)
11457   | exn ->
11458       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11459
11460 (* Main program. *)
11461 let () =
11462   let lock_fd =
11463     try openfile "HACKING" [O_RDWR] 0
11464     with
11465     | Unix_error (ENOENT, _, _) ->
11466         eprintf "\
11467 You are probably running this from the wrong directory.
11468 Run it from the top source directory using the command
11469   src/generator.ml
11470 ";
11471         exit 1
11472     | exn ->
11473         perror "open: HACKING" exn;
11474         exit 1 in
11475
11476   (* Acquire a lock so parallel builds won't try to run the generator
11477    * twice at the same time.  Subsequent builds will wait for the first
11478    * one to finish.  Note the lock is released implicitly when the
11479    * program exits.
11480    *)
11481   (try lockf lock_fd F_LOCK 1
11482    with exn ->
11483      perror "lock: HACKING" exn;
11484      exit 1);
11485
11486   check_functions ();
11487
11488   output_to "src/guestfs_protocol.x" generate_xdr;
11489   output_to "src/guestfs-structs.h" generate_structs_h;
11490   output_to "src/guestfs-actions.h" generate_actions_h;
11491   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11492   output_to "src/guestfs-actions.c" generate_client_actions;
11493   output_to "src/guestfs-bindtests.c" generate_bindtests;
11494   output_to "src/guestfs-structs.pod" generate_structs_pod;
11495   output_to "src/guestfs-actions.pod" generate_actions_pod;
11496   output_to "src/guestfs-availability.pod" generate_availability_pod;
11497   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11498   output_to "src/libguestfs.syms" generate_linker_script;
11499   output_to "daemon/actions.h" generate_daemon_actions_h;
11500   output_to "daemon/stubs.c" generate_daemon_actions;
11501   output_to "daemon/names.c" generate_daemon_names;
11502   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11503   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11504   output_to "capitests/tests.c" generate_tests;
11505   output_to "fish/cmds.c" generate_fish_cmds;
11506   output_to "fish/completion.c" generate_fish_completion;
11507   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11508   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11509   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11510   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11511   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11512   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11513   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11514   output_to "perl/Guestfs.xs" generate_perl_xs;
11515   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11516   output_to "perl/bindtests.pl" generate_perl_bindtests;
11517   output_to "python/guestfs-py.c" generate_python_c;
11518   output_to "python/guestfs.py" generate_python_py;
11519   output_to "python/bindtests.py" generate_python_bindtests;
11520   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11521   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11522   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11523
11524   List.iter (
11525     fun (typ, jtyp) ->
11526       let cols = cols_of_struct typ in
11527       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11528       output_to filename (generate_java_struct jtyp cols);
11529   ) java_structs;
11530
11531   output_to "java/Makefile.inc" generate_java_makefile_inc;
11532   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11533   output_to "java/Bindtests.java" generate_java_bindtests;
11534   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11535   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11536   output_to "csharp/Libguestfs.cs" generate_csharp;
11537
11538   (* Always generate this file last, and unconditionally.  It's used
11539    * by the Makefile to know when we must re-run the generator.
11540    *)
11541   let chan = open_out "src/stamp-generator" in
11542   fprintf chan "1\n";
11543   close_out chan;
11544
11545   printf "generated %d lines of code\n" !lines