New API: checksum-device for checksumming devices.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1384
1385   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM volume group",
1477    "\
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>
2029 or C<guestfs_txz_in>.");
2030
2031   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2032    [],
2033    "pack directory into tarfile",
2034    "\
2035 This command packs the contents of C<directory> and downloads
2036 it to local file C<tarfile>.
2037
2038 To download a compressed tarball, use C<guestfs_tgz_out>
2039 or C<guestfs_txz_out>.");
2040
2041   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042    [InitBasicFS, Always, TestOutput (
2043       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044        ["cat"; "/hello"]], "hello\n")],
2045    "unpack compressed tarball to directory",
2046    "\
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2049
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2051
2052   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2053    [],
2054    "pack directory into compressed tarball",
2055    "\
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2058
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2060
2061   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062    [InitBasicFS, Always, TestLastFail (
2063       [["umount"; "/"];
2064        ["mount_ro"; "/dev/sda1"; "/"];
2065        ["touch"; "/new"]]);
2066     InitBasicFS, Always, TestOutput (
2067       [["write_file"; "/new"; "data"; "0"];
2068        ["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["cat"; "/new"]], "data")],
2071    "mount a guest disk, read-only",
2072    "\
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2075
2076   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2077    [],
2078    "mount a guest disk with mount options",
2079    "\
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2083
2084   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2085    [],
2086    "mount a guest disk with mount options and vfstype",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2091
2092   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2093    [],
2094    "debugging and internals",
2095    "\
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2098 qemu subprocess.
2099
2100 There is no comprehensive help for this command.  You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2103
2104   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105    [InitEmpty, Always, TestOutputList (
2106       [["part_disk"; "/dev/sda"; "mbr"];
2107        ["pvcreate"; "/dev/sda1"];
2108        ["vgcreate"; "VG"; "/dev/sda1"];
2109        ["lvcreate"; "LV1"; "VG"; "50"];
2110        ["lvcreate"; "LV2"; "VG"; "50"];
2111        ["lvremove"; "/dev/VG/LV1"];
2112        ["lvs"]], ["/dev/VG/LV2"]);
2113     InitEmpty, Always, TestOutputList (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["lvremove"; "/dev/VG"];
2120        ["lvs"]], []);
2121     InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG"];
2128        ["vgs"]], ["VG"])],
2129    "remove an LVM logical volume",
2130    "\
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2133
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2136
2137   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["vgremove"; "VG"];
2145        ["lvs"]], []);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["vgremove"; "VG"];
2153        ["vgs"]], [])],
2154    "remove an LVM volume group",
2155    "\
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2157
2158 This also forcibly removes all logical volumes in the volume
2159 group (if any).");
2160
2161   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162    [InitEmpty, Always, TestOutputListOfDevices (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["pvremove"; "/dev/sda1"];
2170        ["lvs"]], []);
2171     InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["vgs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["pvs"]], [])],
2189    "remove an LVM physical volume",
2190    "\
2191 This wipes a physical volume C<device> so that LVM will no longer
2192 recognise it.
2193
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2197
2198   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199    [InitBasicFS, Always, TestOutput (
2200       [["set_e2label"; "/dev/sda1"; "testlabel"];
2201        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202    "set the ext2/3/4 filesystem label",
2203    "\
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>.  Filesystem labels are limited to
2206 16 characters.
2207
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2210
2211   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2212    [],
2213    "get the ext2/3/4 filesystem label",
2214    "\
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2216 C<device>.");
2217
2218   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219    (let uuid = uuidgen () in
2220     [InitBasicFS, Always, TestOutput (
2221        [["set_e2uuid"; "/dev/sda1"; uuid];
2222         ["get_e2uuid"; "/dev/sda1"]], uuid);
2223      InitBasicFS, Always, TestOutput (
2224        [["set_e2uuid"; "/dev/sda1"; "clear"];
2225         ["get_e2uuid"; "/dev/sda1"]], "");
2226      (* We can't predict what UUIDs will be, so just check the commands run. *)
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229      InitBasicFS, Always, TestRun (
2230        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231    "set the ext2/3/4 filesystem UUID",
2232    "\
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>.  The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2240
2241   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2242    [],
2243    "get the ext2/3/4 filesystem UUID",
2244    "\
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device>.");
2247
2248   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249    [InitBasicFS, Always, TestOutputInt (
2250       [["umount"; "/dev/sda1"];
2251        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252     InitBasicFS, Always, TestOutputInt (
2253       [["umount"; "/dev/sda1"];
2254        ["zero"; "/dev/sda1"];
2255        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256    "run the filesystem checker",
2257    "\
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2260
2261 The returned integer is the status.  See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2263
2264 Notes:
2265
2266 =over 4
2267
2268 =item *
2269
2270 Multiple status codes can be summed together.
2271
2272 =item *
2273
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2276
2277 =item *
2278
2279 Checking or repairing NTFS volumes is not supported
2280 (by linux-ntfs).
2281
2282 =back
2283
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2285
2286   ("zero", (RErr, [Device "device"]), 85, [],
2287    [InitBasicFS, Always, TestOutput (
2288       [["umount"; "/dev/sda1"];
2289        ["zero"; "/dev/sda1"];
2290        ["file"; "/dev/sda1"]], "data")],
2291    "write zeroes to the device",
2292    "\
2293 This command writes zeroes over the first few blocks of C<device>.
2294
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device).  It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2298
2299 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2300
2301   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302    (* Test disabled because grub-install incompatible with virtio-blk driver.
2303     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2304     *)
2305    [InitBasicFS, Disabled, TestOutputTrue (
2306       [["grub_install"; "/"; "/dev/sda1"];
2307        ["is_dir"; "/boot"]])],
2308    "install GRUB",
2309    "\
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2312
2313   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["write_file"; "/old"; "file content"; "0"];
2316        ["cp"; "/old"; "/new"];
2317        ["cat"; "/new"]], "file content");
2318     InitBasicFS, Always, TestOutputTrue (
2319       [["write_file"; "/old"; "file content"; "0"];
2320        ["cp"; "/old"; "/new"];
2321        ["is_file"; "/old"]]);
2322     InitBasicFS, Always, TestOutput (
2323       [["write_file"; "/old"; "file content"; "0"];
2324        ["mkdir"; "/dir"];
2325        ["cp"; "/old"; "/dir/new"];
2326        ["cat"; "/dir/new"]], "file content")],
2327    "copy a file",
2328    "\
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2331
2332   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333    [InitBasicFS, Always, TestOutput (
2334       [["mkdir"; "/olddir"];
2335        ["mkdir"; "/newdir"];
2336        ["write_file"; "/olddir/file"; "file content"; "0"];
2337        ["cp_a"; "/olddir"; "/newdir"];
2338        ["cat"; "/newdir/olddir/file"]], "file content")],
2339    "copy a file or directory recursively",
2340    "\
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2343
2344   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["mv"; "/old"; "/new"];
2348        ["cat"; "/new"]], "file content");
2349     InitBasicFS, Always, TestOutputFalse (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mv"; "/old"; "/new"];
2352        ["is_file"; "/old"]])],
2353    "move a file",
2354    "\
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2357
2358   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359    [InitEmpty, Always, TestRun (
2360       [["drop_caches"; "3"]])],
2361    "drop kernel page cache, dentries and inodes",
2362    "\
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches.  The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2367
2368 Setting C<whattodrop> to 3 should drop everything.
2369
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2372
2373   ("dmesg", (RString "kmsgs", []), 91, [],
2374    [InitEmpty, Always, TestRun (
2375       [["dmesg"]])],
2376    "return kernel messages",
2377    "\
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel.  This is sometimes useful for extended
2380 debugging of problems.
2381
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2386
2387   ("ping_daemon", (RErr, []), 92, [],
2388    [InitEmpty, Always, TestRun (
2389       [["ping_daemon"]])],
2390    "ping the guest daemon",
2391    "\
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess.  Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2396
2397   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398    [InitBasicFS, Always, TestOutputTrue (
2399       [["write_file"; "/file1"; "contents of a file"; "0"];
2400        ["cp"; "/file1"; "/file2"];
2401        ["equal"; "/file1"; "/file2"]]);
2402     InitBasicFS, Always, TestOutputFalse (
2403       [["write_file"; "/file1"; "contents of a file"; "0"];
2404        ["write_file"; "/file2"; "contents of another file"; "0"];
2405        ["equal"; "/file1"; "/file2"]]);
2406     InitBasicFS, Always, TestLastFail (
2407       [["equal"; "/file1"; "/file2"]])],
2408    "test if two files have equal contents",
2409    "\
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2412
2413 The external L<cmp(1)> program is used for the comparison.");
2414
2415   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416    [InitISOFS, Always, TestOutputList (
2417       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418     InitISOFS, Always, TestOutputList (
2419       [["strings"; "/empty"]], [])],
2420    "print the printable strings in a file",
2421    "\
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2424
2425   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings_e"; "b"; "/known-5"]], []);
2428     InitBasicFS, Disabled, TestOutputList (
2429       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431    "print the printable strings in a file",
2432    "\
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2435
2436 See the L<strings(1)> manpage for the full list of encodings.
2437
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2440
2441 The returned strings are transcoded to UTF-8.");
2442
2443   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444    [InitISOFS, Always, TestOutput (
2445       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2446     (* Test for RHBZ#501888c2 regression which caused large hexdump
2447      * commands to segfault.
2448      *)
2449     InitISOFS, Always, TestRun (
2450       [["hexdump"; "/100krandom"]])],
2451    "dump a file in hexadecimal",
2452    "\
2453 This runs C<hexdump -C> on the given C<path>.  The result is
2454 the human-readable, canonical hex dump of the file.");
2455
2456   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457    [InitNone, Always, TestOutput (
2458       [["part_disk"; "/dev/sda"; "mbr"];
2459        ["mkfs"; "ext3"; "/dev/sda1"];
2460        ["mount_options"; ""; "/dev/sda1"; "/"];
2461        ["write_file"; "/new"; "test file"; "0"];
2462        ["umount"; "/dev/sda1"];
2463        ["zerofree"; "/dev/sda1"];
2464        ["mount_options"; ""; "/dev/sda1"; "/"];
2465        ["cat"; "/new"]], "test file")],
2466    "zero unused inodes and disk blocks on ext2/3 filesystem",
2467    "\
2468 This runs the I<zerofree> program on C<device>.  This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2471 more effectively.
2472
2473 You should B<not> run this program if the filesystem is
2474 mounted.
2475
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2478
2479   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2480    [],
2481    "resize an LVM physical volume",
2482    "\
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2485
2486   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487                        Int "cyls"; Int "heads"; Int "sectors";
2488                        String "line"]), 99, [DangerWillRobinson],
2489    [],
2490    "modify a single partition on a block device",
2491    "\
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2494
2495 For other parameters, see C<guestfs_sfdisk>.  You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2497
2498 See also: C<guestfs_part_add>");
2499
2500   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2501    [],
2502    "display the partition table",
2503    "\
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command.  It is
2506 not intended to be parsed.
2507
2508 See also: C<guestfs_part_list>");
2509
2510   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2511    [],
2512    "display the kernel geometry",
2513    "\
2514 This displays the kernel's idea of the geometry of C<device>.
2515
2516 The result is in human-readable format, and not designed to
2517 be parsed.");
2518
2519   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2520    [],
2521    "display the disk geometry from the partition table",
2522    "\
2523 This displays the disk geometry of C<device> read from the
2524 partition table.  Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2532    [],
2533    "activate or deactivate all volume groups",
2534    "\
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2539 then those devices disappear.
2540
2541 This command is the same as running C<vgchange -a y|n>");
2542
2543   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate some volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2554
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2557
2558   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559    [InitNone, Always, TestOutput (
2560       [["part_disk"; "/dev/sda"; "mbr"];
2561        ["pvcreate"; "/dev/sda1"];
2562        ["vgcreate"; "VG"; "/dev/sda1"];
2563        ["lvcreate"; "LV"; "VG"; "10"];
2564        ["mkfs"; "ext2"; "/dev/VG/LV"];
2565        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566        ["write_file"; "/new"; "test content"; "0"];
2567        ["umount"; "/"];
2568        ["lvresize"; "/dev/VG/LV"; "20"];
2569        ["e2fsck_f"; "/dev/VG/LV"];
2570        ["resize2fs"; "/dev/VG/LV"];
2571        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572        ["cat"; "/new"]], "test content")],
2573    "resize an LVM logical volume",
2574    "\
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>.  When reducing, data in the reduced part
2577 is lost.");
2578
2579   ("resize2fs", (RErr, [Device "device"]), 106, [],
2580    [], (* lvresize tests this *)
2581    "resize an ext2/ext3 filesystem",
2582    "\
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2585
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command.  For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2591
2592   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593    [InitBasicFS, Always, TestOutputList (
2594       [["find"; "/"]], ["lost+found"]);
2595     InitBasicFS, Always, TestOutputList (
2596       [["touch"; "/a"];
2597        ["mkdir"; "/b"];
2598        ["touch"; "/b/c"];
2599        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600     InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["find"; "/a/b/"]], ["c"; "c/d"])],
2604    "find all files and directories",
2605    "\
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>.  It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2610
2611 This returns a list of strings I<without any prefix>.  Thus
2612 if the directory structure was:
2613
2614  /tmp/a
2615  /tmp/b
2616  /tmp/c/d
2617
2618 then the returned list from C<guestfs_find> C</tmp> would be
2619 4 elements:
2620
2621  a
2622  b
2623  c
2624  c/d
2625
2626 If C<directory> is not a directory, then this command returns
2627 an error.
2628
2629 The returned list is sorted.
2630
2631 See also C<guestfs_find0>.");
2632
2633   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634    [], (* lvresize tests this *)
2635    "check an ext2/ext3 filesystem",
2636    "\
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2640
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.).  Normally you should use C<guestfs_fsck>.");
2643
2644   ("sleep", (RErr, [Int "secs"]), 109, [],
2645    [InitNone, Always, TestRun (
2646       [["sleep"; "1"]])],
2647    "sleep for some seconds",
2648    "\
2649 Sleep for C<secs> seconds.");
2650
2651   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652    [InitNone, Always, TestOutputInt (
2653       [["part_disk"; "/dev/sda"; "mbr"];
2654        ["mkfs"; "ntfs"; "/dev/sda1"];
2655        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656     InitNone, Always, TestOutputInt (
2657       [["part_disk"; "/dev/sda"; "mbr"];
2658        ["mkfs"; "ext2"; "/dev/sda1"];
2659        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660    "probe NTFS volume",
2661    "\
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2665
2666 C<rw> is a boolean flag.  Set it to true if you want to test
2667 if the volume can be mounted read-write.  Set it to false if
2668 you want to test if the volume can be mounted read-only.
2669
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2673
2674   ("sh", (RString "output", [String "command"]), 111, [],
2675    [], (* XXX needs tests *)
2676    "run a command via the shell",
2677    "\
2678 This call runs a command from the guest filesystem via the
2679 guest's C</bin/sh>.
2680
2681 This is like C<guestfs_command>, but passes the command to:
2682
2683  /bin/sh -c \"command\"
2684
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2687 and so on.
2688
2689 All the provisos about C<guestfs_command> apply to this call.");
2690
2691   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692    [], (* XXX needs tests *)
2693    "run a command via the shell returning lines",
2694    "\
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2697
2698 See also: C<guestfs_command_lines>");
2699
2700   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702     * code in stubs.c, since all valid glob patterns must start with "/".
2703     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2704     *)
2705    [InitBasicFS, Always, TestOutputList (
2706       [["mkdir_p"; "/a/b/c"];
2707        ["touch"; "/a/b/c/d"];
2708        ["touch"; "/a/b/c/e"];
2709        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710     InitBasicFS, Always, TestOutputList (
2711       [["mkdir_p"; "/a/b/c"];
2712        ["touch"; "/a/b/c/d"];
2713        ["touch"; "/a/b/c/e"];
2714        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715     InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/*/x/*"]], [])],
2720    "expand a wildcard path",
2721    "\
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2724 used by the shell.
2725
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2728
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2732
2733   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735       [["scrub_device"; "/dev/sdc"]])],
2736    "scrub (securely wipe) a device",
2737    "\
2738 This command writes patterns over C<device> to make data retrieval
2739 more difficult.
2740
2741 It is an interface to the L<scrub(1)> program.  See that
2742 manual page for more details.");
2743
2744   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745    [InitBasicFS, Always, TestRun (
2746       [["write_file"; "/file"; "content"; "0"];
2747        ["scrub_file"; "/file"]])],
2748    "scrub (securely wipe) a file",
2749    "\
2750 This command writes patterns over a file to make data retrieval
2751 more difficult.
2752
2753 The file is I<removed> after scrubbing.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759    [], (* XXX needs testing *)
2760    "scrub (securely wipe) free space",
2761    "\
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2766 containing C<dir>.
2767
2768 It is an interface to the L<scrub(1)> program.  See that
2769 manual page for more details.");
2770
2771   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772    [InitBasicFS, Always, TestRun (
2773       [["mkdir"; "/tmp"];
2774        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775    "create a temporary directory",
2776    "\
2777 This command creates a temporary directory.  The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2780 \"XXXXXX\".
2781
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2784
2785 The name of the temporary directory that was created
2786 is returned.
2787
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2790
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2793
2794 See also: L<mkdtemp(3)>");
2795
2796   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["wc_l"; "/10klines"]], 10000)],
2799    "count lines in a file",
2800    "\
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2803
2804   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805    [InitISOFS, Always, TestOutputInt (
2806       [["wc_w"; "/10klines"]], 10000)],
2807    "count words in a file",
2808    "\
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2811
2812   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813    [InitISOFS, Always, TestOutputInt (
2814       [["wc_c"; "/100kallspaces"]], 102400)],
2815    "count characters in a file",
2816    "\
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2819
2820   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821    [InitISOFS, Always, TestOutputList (
2822       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823    "return first 10 lines of a file",
2824    "\
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2827
2828   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829    [InitISOFS, Always, TestOutputList (
2830       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833     InitISOFS, Always, TestOutputList (
2834       [["head_n"; "0"; "/10klines"]], [])],
2835    "return first N lines of a file",
2836    "\
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2839
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2842
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2844
2845   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846    [InitISOFS, Always, TestOutputList (
2847       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848    "return last 10 lines of a file",
2849    "\
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2852
2853   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854    [InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858     InitISOFS, Always, TestOutputList (
2859       [["tail_n"; "0"; "/10klines"]], [])],
2860    "return last N lines of a file",
2861    "\
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2864
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2867
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2869
2870   ("df", (RString "output", []), 125, [],
2871    [], (* XXX Tricky to test because it depends on the exact format
2872         * of the 'df' command and other imponderables.
2873         *)
2874    "report file system disk space usage",
2875    "\
2876 This command runs the C<df> command to report disk space used.
2877
2878 This command is mostly useful for interactive sessions.  It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2881
2882   ("df_h", (RString "output", []), 126, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage (human readable)",
2887    "\
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2890
2891 This command is mostly useful for interactive sessions.  It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2894
2895   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896    [InitISOFS, Always, TestOutputInt (
2897       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898    "estimate file space usage",
2899    "\
2900 This command runs the C<du -s> command to estimate file space
2901 usage for C<path>.
2902
2903 C<path> can be a file or a directory.  If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2906
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2909
2910   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911    [InitISOFS, Always, TestOutputList (
2912       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913    "list files in an initrd",
2914    "\
2915 This command lists out files contained in an initrd.
2916
2917 The files are listed without any initial C</> character.  The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical).  Directory names are listed as separate items.
2920
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd.  We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2924
2925   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2926    [],
2927    "mount a file using the loop device",
2928    "\
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point.  It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2932
2933   ("mkswap", (RErr, [Device "device"]), 130, [],
2934    [InitEmpty, Always, TestRun (
2935       [["part_disk"; "/dev/sda"; "mbr"];
2936        ["mkswap"; "/dev/sda1"]])],
2937    "create a swap partition",
2938    "\
2939 Create a swap partition on C<device>.");
2940
2941   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942    [InitEmpty, Always, TestRun (
2943       [["part_disk"; "/dev/sda"; "mbr"];
2944        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945    "create a swap partition with a label",
2946    "\
2947 Create a swap partition on C<device> with label C<label>.
2948
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition.  This appears to be
2951 a limitation of the kernel or swap tools.");
2952
2953   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954    (let uuid = uuidgen () in
2955     [InitEmpty, Always, TestRun (
2956        [["part_disk"; "/dev/sda"; "mbr"];
2957         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958    "create a swap partition with an explicit UUID",
2959    "\
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2961
2962   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963    [InitBasicFS, Always, TestOutputStruct (
2964       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967     InitBasicFS, Always, TestOutputStruct (
2968       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970    "make block, character or FIFO devices",
2971    "\
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2974
2975 The C<mode> parameter should be the mode, using the standard
2976 constants.  C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.");
2979
2980   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2981    [InitBasicFS, Always, TestOutputStruct (
2982       [["mkfifo"; "0o777"; "/node"];
2983        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2984    "make FIFO (named pipe)",
2985    "\
2986 This call creates a FIFO (named pipe) called C<path> with
2987 mode C<mode>.  It is just a convenient wrapper around
2988 C<guestfs_mknod>.");
2989
2990   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2994    "make block device node",
2995    "\
2996 This call creates a block device node called C<path> with
2997 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2998 It is just a convenient wrapper around C<guestfs_mknod>.");
2999
3000   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3001    [InitBasicFS, Always, TestOutputStruct (
3002       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3004    "make char device node",
3005    "\
3006 This call creates a char device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3009
3010   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3011    [], (* XXX umask is one of those stateful things that we should
3012         * reset between each test.
3013         *)
3014    "set file mode creation mask (umask)",
3015    "\
3016 This function sets the mask used for creating new files and
3017 device nodes to C<mask & 0777>.
3018
3019 Typical umask values would be C<022> which creates new files
3020 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3021 C<002> which creates new files with permissions like
3022 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3023
3024 The default umask is C<022>.  This is important because it
3025 means that directories and device nodes will be created with
3026 C<0644> or C<0755> mode even if you specify C<0777>.
3027
3028 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3029
3030 This call returns the previous umask.");
3031
3032   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3033    [],
3034    "read directories entries",
3035    "\
3036 This returns the list of directory entries in directory C<dir>.
3037
3038 All entries in the directory are returned, including C<.> and
3039 C<..>.  The entries are I<not> sorted, but returned in the same
3040 order as the underlying filesystem.
3041
3042 Also this call returns basic file type information about each
3043 file.  The C<ftyp> field will contain one of the following characters:
3044
3045 =over 4
3046
3047 =item 'b'
3048
3049 Block special
3050
3051 =item 'c'
3052
3053 Char special
3054
3055 =item 'd'
3056
3057 Directory
3058
3059 =item 'f'
3060
3061 FIFO (named pipe)
3062
3063 =item 'l'
3064
3065 Symbolic link
3066
3067 =item 'r'
3068
3069 Regular file
3070
3071 =item 's'
3072
3073 Socket
3074
3075 =item 'u'
3076
3077 Unknown file type
3078
3079 =item '?'
3080
3081 The L<readdir(3)> returned a C<d_type> field with an
3082 unexpected value
3083
3084 =back
3085
3086 This function is primarily intended for use by programs.  To
3087 get a simple list of names, use C<guestfs_ls>.  To get a printable
3088 directory for human consumption, use C<guestfs_ll>.");
3089
3090   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3091    [],
3092    "create partitions on a block device",
3093    "\
3094 This is a simplified interface to the C<guestfs_sfdisk>
3095 command, where partition sizes are specified in megabytes
3096 only (rounded to the nearest cylinder) and you don't need
3097 to specify the cyls, heads and sectors parameters which
3098 were rarely if ever used anyway.
3099
3100 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3101 and C<guestfs_part_disk>");
3102
3103   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3104    [],
3105    "determine file type inside a compressed file",
3106    "\
3107 This command runs C<file> after first decompressing C<path>
3108 using C<method>.
3109
3110 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3111
3112 Since 1.0.63, use C<guestfs_file> instead which can now
3113 process compressed files.");
3114
3115   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3116    [],
3117    "list extended attributes of a file or directory",
3118    "\
3119 This call lists the extended attributes of the file or directory
3120 C<path>.
3121
3122 At the system call level, this is a combination of the
3123 L<listxattr(2)> and L<getxattr(2)> calls.
3124
3125 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3126
3127   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3128    [],
3129    "list extended attributes of a file or directory",
3130    "\
3131 This is the same as C<guestfs_getxattrs>, but if C<path>
3132 is a symbolic link, then it returns the extended attributes
3133 of the link itself.");
3134
3135   ("setxattr", (RErr, [String "xattr";
3136                        String "val"; Int "vallen"; (* will be BufferIn *)
3137                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3138    [],
3139    "set extended attribute of a file or directory",
3140    "\
3141 This call sets the extended attribute named C<xattr>
3142 of the file C<path> to the value C<val> (of length C<vallen>).
3143 The value is arbitrary 8 bit data.
3144
3145 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3146
3147   ("lsetxattr", (RErr, [String "xattr";
3148                         String "val"; Int "vallen"; (* will be BufferIn *)
3149                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3150    [],
3151    "set extended attribute of a file or directory",
3152    "\
3153 This is the same as C<guestfs_setxattr>, but if C<path>
3154 is a symbolic link, then it sets an extended attribute
3155 of the link itself.");
3156
3157   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3158    [],
3159    "remove extended attribute of a file or directory",
3160    "\
3161 This call removes the extended attribute named C<xattr>
3162 of the file C<path>.
3163
3164 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3165
3166   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3167    [],
3168    "remove extended attribute of a file or directory",
3169    "\
3170 This is the same as C<guestfs_removexattr>, but if C<path>
3171 is a symbolic link, then it removes an extended attribute
3172 of the link itself.");
3173
3174   ("mountpoints", (RHashtable "mps", []), 147, [],
3175    [],
3176    "show mountpoints",
3177    "\
3178 This call is similar to C<guestfs_mounts>.  That call returns
3179 a list of devices.  This one returns a hash table (map) of
3180 device name to directory where the device is mounted.");
3181
3182   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3183    (* This is a special case: while you would expect a parameter
3184     * of type "Pathname", that doesn't work, because it implies
3185     * NEED_ROOT in the generated calling code in stubs.c, and
3186     * this function cannot use NEED_ROOT.
3187     *)
3188    [],
3189    "create a mountpoint",
3190    "\
3191 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3192 specialized calls that can be used to create extra mountpoints
3193 before mounting the first filesystem.
3194
3195 These calls are I<only> necessary in some very limited circumstances,
3196 mainly the case where you want to mount a mix of unrelated and/or
3197 read-only filesystems together.
3198
3199 For example, live CDs often contain a \"Russian doll\" nest of
3200 filesystems, an ISO outer layer, with a squashfs image inside, with
3201 an ext2/3 image inside that.  You can unpack this as follows
3202 in guestfish:
3203
3204  add-ro Fedora-11-i686-Live.iso
3205  run
3206  mkmountpoint /cd
3207  mkmountpoint /squash
3208  mkmountpoint /ext3
3209  mount /dev/sda /cd
3210  mount-loop /cd/LiveOS/squashfs.img /squash
3211  mount-loop /squash/LiveOS/ext3fs.img /ext3
3212
3213 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3214
3215   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3216    [],
3217    "remove a mountpoint",
3218    "\
3219 This calls removes a mountpoint that was previously created
3220 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3221 for full details.");
3222
3223   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3224    [InitISOFS, Always, TestOutputBuffer (
3225       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3226    "read a file",
3227    "\
3228 This calls returns the contents of the file C<path> as a
3229 buffer.
3230
3231 Unlike C<guestfs_cat>, this function can correctly
3232 handle files that contain embedded ASCII NUL characters.
3233 However unlike C<guestfs_download>, this function is limited
3234 in the total size of file that can be handled.");
3235
3236   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3237    [InitISOFS, Always, TestOutputList (
3238       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3239     InitISOFS, Always, TestOutputList (
3240       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3241    "return lines matching a pattern",
3242    "\
3243 This calls the external C<grep> program and returns the
3244 matching lines.");
3245
3246   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3247    [InitISOFS, Always, TestOutputList (
3248       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3249    "return lines matching a pattern",
3250    "\
3251 This calls the external C<egrep> program and returns the
3252 matching lines.");
3253
3254   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3255    [InitISOFS, Always, TestOutputList (
3256       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3257    "return lines matching a pattern",
3258    "\
3259 This calls the external C<fgrep> program and returns the
3260 matching lines.");
3261
3262   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3263    [InitISOFS, Always, TestOutputList (
3264       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3265    "return lines matching a pattern",
3266    "\
3267 This calls the external C<grep -i> program and returns the
3268 matching lines.");
3269
3270   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3271    [InitISOFS, Always, TestOutputList (
3272       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3273    "return lines matching a pattern",
3274    "\
3275 This calls the external C<egrep -i> program and returns the
3276 matching lines.");
3277
3278   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3279    [InitISOFS, Always, TestOutputList (
3280       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3281    "return lines matching a pattern",
3282    "\
3283 This calls the external C<fgrep -i> program and returns the
3284 matching lines.");
3285
3286   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputList (
3288       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3289    "return lines matching a pattern",
3290    "\
3291 This calls the external C<zgrep> program and returns the
3292 matching lines.");
3293
3294   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3295    [InitISOFS, Always, TestOutputList (
3296       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3297    "return lines matching a pattern",
3298    "\
3299 This calls the external C<zegrep> program and returns the
3300 matching lines.");
3301
3302   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3303    [InitISOFS, Always, TestOutputList (
3304       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3305    "return lines matching a pattern",
3306    "\
3307 This calls the external C<zfgrep> program and returns the
3308 matching lines.");
3309
3310   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3311    [InitISOFS, Always, TestOutputList (
3312       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3313    "return lines matching a pattern",
3314    "\
3315 This calls the external C<zgrep -i> program and returns the
3316 matching lines.");
3317
3318   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3319    [InitISOFS, Always, TestOutputList (
3320       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<zegrep -i> program and returns the
3324 matching lines.");
3325
3326   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<zfgrep -i> program and returns the
3332 matching lines.");
3333
3334   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3335    [InitISOFS, Always, TestOutput (
3336       [["realpath"; "/../directory"]], "/directory")],
3337    "canonicalized absolute pathname",
3338    "\
3339 Return the canonicalized absolute pathname of C<path>.  The
3340 returned path has no C<.>, C<..> or symbolic link path elements.");
3341
3342   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3343    [InitBasicFS, Always, TestOutputStruct (
3344       [["touch"; "/a"];
3345        ["ln"; "/a"; "/b"];
3346        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3347    "create a hard link",
3348    "\
3349 This command creates a hard link using the C<ln> command.");
3350
3351   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3352    [InitBasicFS, Always, TestOutputStruct (
3353       [["touch"; "/a"];
3354        ["touch"; "/b"];
3355        ["ln_f"; "/a"; "/b"];
3356        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357    "create a hard link",
3358    "\
3359 This command creates a hard link using the C<ln -f> command.
3360 The C<-f> option removes the link (C<linkname>) if it exists already.");
3361
3362   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3363    [InitBasicFS, Always, TestOutputStruct (
3364       [["touch"; "/a"];
3365        ["ln_s"; "a"; "/b"];
3366        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3367    "create a symbolic link",
3368    "\
3369 This command creates a symbolic link using the C<ln -s> command.");
3370
3371   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3372    [InitBasicFS, Always, TestOutput (
3373       [["mkdir_p"; "/a/b"];
3374        ["touch"; "/a/b/c"];
3375        ["ln_sf"; "../d"; "/a/b/c"];
3376        ["readlink"; "/a/b/c"]], "../d")],
3377    "create a symbolic link",
3378    "\
3379 This command creates a symbolic link using the C<ln -sf> command,
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3381
3382   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3383    [] (* XXX tested above *),
3384    "read the target of a symbolic link",
3385    "\
3386 This command reads the target of a symbolic link.");
3387
3388   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3389    [InitBasicFS, Always, TestOutputStruct (
3390       [["fallocate"; "/a"; "1000000"];
3391        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3392    "preallocate a file in the guest filesystem",
3393    "\
3394 This command preallocates a file (containing zero bytes) named
3395 C<path> of size C<len> bytes.  If the file exists already, it
3396 is overwritten.
3397
3398 Do not confuse this with the guestfish-specific
3399 C<alloc> command which allocates a file in the host and
3400 attaches it as a device.");
3401
3402   ("swapon_device", (RErr, [Device "device"]), 170, [],
3403    [InitPartition, Always, TestRun (
3404       [["mkswap"; "/dev/sda1"];
3405        ["swapon_device"; "/dev/sda1"];
3406        ["swapoff_device"; "/dev/sda1"]])],
3407    "enable swap on device",
3408    "\
3409 This command enables the libguestfs appliance to use the
3410 swap device or partition named C<device>.  The increased
3411 memory is made available for all commands, for example
3412 those run using C<guestfs_command> or C<guestfs_sh>.
3413
3414 Note that you should not swap to existing guest swap
3415 partitions unless you know what you are doing.  They may
3416 contain hibernation information, or other information that
3417 the guest doesn't want you to trash.  You also risk leaking
3418 information about the host to the guest this way.  Instead,
3419 attach a new host device to the guest and swap on that.");
3420
3421   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3422    [], (* XXX tested by swapon_device *)
3423    "disable swap on device",
3424    "\
3425 This command disables the libguestfs appliance swap
3426 device or partition named C<device>.
3427 See C<guestfs_swapon_device>.");
3428
3429   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3430    [InitBasicFS, Always, TestRun (
3431       [["fallocate"; "/swap"; "8388608"];
3432        ["mkswap_file"; "/swap"];
3433        ["swapon_file"; "/swap"];
3434        ["swapoff_file"; "/swap"]])],
3435    "enable swap on file",
3436    "\
3437 This command enables swap to a file.
3438 See C<guestfs_swapon_device> for other notes.");
3439
3440   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3441    [], (* XXX tested by swapon_file *)
3442    "disable swap on file",
3443    "\
3444 This command disables the libguestfs appliance swap on file.");
3445
3446   ("swapon_label", (RErr, [String "label"]), 174, [],
3447    [InitEmpty, Always, TestRun (
3448       [["part_disk"; "/dev/sdb"; "mbr"];
3449        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3450        ["swapon_label"; "swapit"];
3451        ["swapoff_label"; "swapit"];
3452        ["zero"; "/dev/sdb"];
3453        ["blockdev_rereadpt"; "/dev/sdb"]])],
3454    "enable swap on labeled swap partition",
3455    "\
3456 This command enables swap to a labeled swap partition.
3457 See C<guestfs_swapon_device> for other notes.");
3458
3459   ("swapoff_label", (RErr, [String "label"]), 175, [],
3460    [], (* XXX tested by swapon_label *)
3461    "disable swap on labeled swap partition",
3462    "\
3463 This command disables the libguestfs appliance swap on
3464 labeled swap partition.");
3465
3466   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3467    (let uuid = uuidgen () in
3468     [InitEmpty, Always, TestRun (
3469        [["mkswap_U"; uuid; "/dev/sdb"];
3470         ["swapon_uuid"; uuid];
3471         ["swapoff_uuid"; uuid]])]),
3472    "enable swap on swap partition by UUID",
3473    "\
3474 This command enables swap to a swap partition with the given UUID.
3475 See C<guestfs_swapon_device> for other notes.");
3476
3477   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3478    [], (* XXX tested by swapon_uuid *)
3479    "disable swap on swap partition by UUID",
3480    "\
3481 This command disables the libguestfs appliance swap partition
3482 with the given UUID.");
3483
3484   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3485    [InitBasicFS, Always, TestRun (
3486       [["fallocate"; "/swap"; "8388608"];
3487        ["mkswap_file"; "/swap"]])],
3488    "create a swap file",
3489    "\
3490 Create a swap file.
3491
3492 This command just writes a swap file signature to an existing
3493 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3494
3495   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3496    [InitISOFS, Always, TestRun (
3497       [["inotify_init"; "0"]])],
3498    "create an inotify handle",
3499    "\
3500 This command creates a new inotify handle.
3501 The inotify subsystem can be used to notify events which happen to
3502 objects in the guest filesystem.
3503
3504 C<maxevents> is the maximum number of events which will be
3505 queued up between calls to C<guestfs_inotify_read> or
3506 C<guestfs_inotify_files>.
3507 If this is passed as C<0>, then the kernel (or previously set)
3508 default is used.  For Linux 2.6.29 the default was 16384 events.
3509 Beyond this limit, the kernel throws away events, but records
3510 the fact that it threw them away by setting a flag
3511 C<IN_Q_OVERFLOW> in the returned structure list (see
3512 C<guestfs_inotify_read>).
3513
3514 Before any events are generated, you have to add some
3515 watches to the internal watch list.  See:
3516 C<guestfs_inotify_add_watch>,
3517 C<guestfs_inotify_rm_watch> and
3518 C<guestfs_inotify_watch_all>.
3519
3520 Queued up events should be read periodically by calling
3521 C<guestfs_inotify_read>
3522 (or C<guestfs_inotify_files> which is just a helpful
3523 wrapper around C<guestfs_inotify_read>).  If you don't
3524 read the events out often enough then you risk the internal
3525 queue overflowing.
3526
3527 The handle should be closed after use by calling
3528 C<guestfs_inotify_close>.  This also removes any
3529 watches automatically.
3530
3531 See also L<inotify(7)> for an overview of the inotify interface
3532 as exposed by the Linux kernel, which is roughly what we expose
3533 via libguestfs.  Note that there is one global inotify handle
3534 per libguestfs instance.");
3535
3536   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3537    [InitBasicFS, Always, TestOutputList (
3538       [["inotify_init"; "0"];
3539        ["inotify_add_watch"; "/"; "1073741823"];
3540        ["touch"; "/a"];
3541        ["touch"; "/b"];
3542        ["inotify_files"]], ["a"; "b"])],
3543    "add an inotify watch",
3544    "\
3545 Watch C<path> for the events listed in C<mask>.
3546
3547 Note that if C<path> is a directory then events within that
3548 directory are watched, but this does I<not> happen recursively
3549 (in subdirectories).
3550
3551 Note for non-C or non-Linux callers: the inotify events are
3552 defined by the Linux kernel ABI and are listed in
3553 C</usr/include/sys/inotify.h>.");
3554
3555   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3556    [],
3557    "remove an inotify watch",
3558    "\
3559 Remove a previously defined inotify watch.
3560 See C<guestfs_inotify_add_watch>.");
3561
3562   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3563    [],
3564    "return list of inotify events",
3565    "\
3566 Return the complete queue of events that have happened
3567 since the previous read call.
3568
3569 If no events have happened, this returns an empty list.
3570
3571 I<Note>: In order to make sure that all events have been
3572 read, you must call this function repeatedly until it
3573 returns an empty list.  The reason is that the call will
3574 read events up to the maximum appliance-to-host message
3575 size and leave remaining events in the queue.");
3576
3577   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3578    [],
3579    "return list of watched files that had events",
3580    "\
3581 This function is a helpful wrapper around C<guestfs_inotify_read>
3582 which just returns a list of pathnames of objects that were
3583 touched.  The returned pathnames are sorted and deduplicated.");
3584
3585   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3586    [],
3587    "close the inotify handle",
3588    "\
3589 This closes the inotify handle which was previously
3590 opened by inotify_init.  It removes all watches, throws
3591 away any pending events, and deallocates all resources.");
3592
3593   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3594    [],
3595    "set SELinux security context",
3596    "\
3597 This sets the SELinux security context of the daemon
3598 to the string C<context>.
3599
3600 See the documentation about SELINUX in L<guestfs(3)>.");
3601
3602   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3603    [],
3604    "get SELinux security context",
3605    "\
3606 This gets the SELinux security context of the daemon.
3607
3608 See the documentation about SELINUX in L<guestfs(3)>,
3609 and C<guestfs_setcon>");
3610
3611   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3612    [InitEmpty, Always, TestOutput (
3613       [["part_disk"; "/dev/sda"; "mbr"];
3614        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3615        ["mount_options"; ""; "/dev/sda1"; "/"];
3616        ["write_file"; "/new"; "new file contents"; "0"];
3617        ["cat"; "/new"]], "new file contents")],
3618    "make a filesystem with block size",
3619    "\
3620 This call is similar to C<guestfs_mkfs>, but it allows you to
3621 control the block size of the resulting filesystem.  Supported
3622 block sizes depend on the filesystem type, but typically they
3623 are C<1024>, C<2048> or C<4096> only.");
3624
3625   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3626    [InitEmpty, Always, TestOutput (
3627       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3628        ["mke2journal"; "4096"; "/dev/sda1"];
3629        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3630        ["mount_options"; ""; "/dev/sda2"; "/"];
3631        ["write_file"; "/new"; "new file contents"; "0"];
3632        ["cat"; "/new"]], "new file contents")],
3633    "make ext2/3/4 external journal",
3634    "\
3635 This creates an ext2 external journal on C<device>.  It is equivalent
3636 to the command:
3637
3638  mke2fs -O journal_dev -b blocksize device");
3639
3640   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3641    [InitEmpty, Always, TestOutput (
3642       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3644        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3645        ["mount_options"; ""; "/dev/sda2"; "/"];
3646        ["write_file"; "/new"; "new file contents"; "0"];
3647        ["cat"; "/new"]], "new file contents")],
3648    "make ext2/3/4 external journal with label",
3649    "\
3650 This creates an ext2 external journal on C<device> with label C<label>.");
3651
3652   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3653    (let uuid = uuidgen () in
3654     [InitEmpty, Always, TestOutput (
3655        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3656         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3657         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3658         ["mount_options"; ""; "/dev/sda2"; "/"];
3659         ["write_file"; "/new"; "new file contents"; "0"];
3660         ["cat"; "/new"]], "new file contents")]),
3661    "make ext2/3/4 external journal with UUID",
3662    "\
3663 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3664
3665   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3666    [],
3667    "make ext2/3/4 filesystem with external journal",
3668    "\
3669 This creates an ext2/3/4 filesystem on C<device> with
3670 an external journal on C<journal>.  It is equivalent
3671 to the command:
3672
3673  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3674
3675 See also C<guestfs_mke2journal>.");
3676
3677   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3678    [],
3679    "make ext2/3/4 filesystem with external journal",
3680    "\
3681 This creates an ext2/3/4 filesystem on C<device> with
3682 an external journal on the journal labeled C<label>.
3683
3684 See also C<guestfs_mke2journal_L>.");
3685
3686   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3687    [],
3688    "make ext2/3/4 filesystem with external journal",
3689    "\
3690 This creates an ext2/3/4 filesystem on C<device> with
3691 an external journal on the journal with UUID C<uuid>.
3692
3693 See also C<guestfs_mke2journal_U>.");
3694
3695   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3696    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3697    "load a kernel module",
3698    "\
3699 This loads a kernel module in the appliance.
3700
3701 The kernel module must have been whitelisted when libguestfs
3702 was built (see C<appliance/kmod.whitelist.in> in the source).");
3703
3704   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3705    [InitNone, Always, TestOutput (
3706       [["echo_daemon"; "This is a test"]], "This is a test"
3707     )],
3708    "echo arguments back to the client",
3709    "\
3710 This command concatenate the list of C<words> passed with single spaces between
3711 them and returns the resulting string.
3712
3713 You can use this command to test the connection through to the daemon.
3714
3715 See also C<guestfs_ping_daemon>.");
3716
3717   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3718    [], (* There is a regression test for this. *)
3719    "find all files and directories, returning NUL-separated list",
3720    "\
3721 This command lists out all files and directories, recursively,
3722 starting at C<directory>, placing the resulting list in the
3723 external file called C<files>.
3724
3725 This command works the same way as C<guestfs_find> with the
3726 following exceptions:
3727
3728 =over 4
3729
3730 =item *
3731
3732 The resulting list is written to an external file.
3733
3734 =item *
3735
3736 Items (filenames) in the result are separated
3737 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3738
3739 =item *
3740
3741 This command is not limited in the number of names that it
3742 can return.
3743
3744 =item *
3745
3746 The result list is not sorted.
3747
3748 =back");
3749
3750   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3751    [InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3755     InitISOFS, Always, TestOutput (
3756       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3757     InitISOFS, Always, TestLastFail (
3758       [["case_sensitive_path"; "/Known-1/"]]);
3759     InitBasicFS, Always, TestOutput (
3760       [["mkdir"; "/a"];
3761        ["mkdir"; "/a/bbb"];
3762        ["touch"; "/a/bbb/c"];
3763        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3764     InitBasicFS, Always, TestOutput (
3765       [["mkdir"; "/a"];
3766        ["mkdir"; "/a/bbb"];
3767        ["touch"; "/a/bbb/c"];
3768        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3769     InitBasicFS, Always, TestLastFail (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3774    "return true path on case-insensitive filesystem",
3775    "\
3776 This can be used to resolve case insensitive paths on
3777 a filesystem which is case sensitive.  The use case is
3778 to resolve paths which you have read from Windows configuration
3779 files or the Windows Registry, to the true path.
3780
3781 The command handles a peculiarity of the Linux ntfs-3g
3782 filesystem driver (and probably others), which is that although
3783 the underlying filesystem is case-insensitive, the driver
3784 exports the filesystem to Linux as case-sensitive.
3785
3786 One consequence of this is that special directories such
3787 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3788 (or other things) depending on the precise details of how
3789 they were created.  In Windows itself this would not be
3790 a problem.
3791
3792 Bug or feature?  You decide:
3793 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3794
3795 This function resolves the true case of each element in the
3796 path and returns the case-sensitive path.
3797
3798 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3799 might return C<\"/WINDOWS/system32\"> (the exact return value
3800 would depend on details of how the directories were originally
3801 created under Windows).
3802
3803 I<Note>:
3804 This function does not handle drive names, backslashes etc.
3805
3806 See also C<guestfs_realpath>.");
3807
3808   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3809    [InitBasicFS, Always, TestOutput (
3810       [["vfs_type"; "/dev/sda1"]], "ext2")],
3811    "get the Linux VFS type corresponding to a mounted device",
3812    "\
3813 This command gets the block device type corresponding to
3814 a mounted device called C<device>.
3815
3816 Usually the result is the name of the Linux VFS module that
3817 is used to mount this device (probably determined automatically
3818 if you used the C<guestfs_mount> call).");
3819
3820   ("truncate", (RErr, [Pathname "path"]), 199, [],
3821    [InitBasicFS, Always, TestOutputStruct (
3822       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3823        ["truncate"; "/test"];
3824        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3825    "truncate a file to zero size",
3826    "\
3827 This command truncates C<path> to a zero-length file.  The
3828 file must exist already.");
3829
3830   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3831    [InitBasicFS, Always, TestOutputStruct (
3832       [["touch"; "/test"];
3833        ["truncate_size"; "/test"; "1000"];
3834        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3835    "truncate a file to a particular size",
3836    "\
3837 This command truncates C<path> to size C<size> bytes.  The file
3838 must exist already.  If the file is smaller than C<size> then
3839 the file is extended to the required size with null bytes.");
3840
3841   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3842    [InitBasicFS, Always, TestOutputStruct (
3843       [["touch"; "/test"];
3844        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3845        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3846    "set timestamp of a file with nanosecond precision",
3847    "\
3848 This command sets the timestamps of a file with nanosecond
3849 precision.
3850
3851 C<atsecs, atnsecs> are the last access time (atime) in secs and
3852 nanoseconds from the epoch.
3853
3854 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3855 secs and nanoseconds from the epoch.
3856
3857 If the C<*nsecs> field contains the special value C<-1> then
3858 the corresponding timestamp is set to the current time.  (The
3859 C<*secs> field is ignored in this case).
3860
3861 If the C<*nsecs> field contains the special value C<-2> then
3862 the corresponding timestamp is left unchanged.  (The
3863 C<*secs> field is ignored in this case).");
3864
3865   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3866    [InitBasicFS, Always, TestOutputStruct (
3867       [["mkdir_mode"; "/test"; "0o111"];
3868        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3869    "create a directory with a particular mode",
3870    "\
3871 This command creates a directory, setting the initial permissions
3872 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3873
3874   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3875    [], (* XXX *)
3876    "change file owner and group",
3877    "\
3878 Change the file owner to C<owner> and group to C<group>.
3879 This is like C<guestfs_chown> but if C<path> is a symlink then
3880 the link itself is changed, not the target.
3881
3882 Only numeric uid and gid are supported.  If you want to use
3883 names, you will need to locate and parse the password file
3884 yourself (Augeas support makes this relatively easy).");
3885
3886   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3887    [], (* XXX *)
3888    "lstat on multiple files",
3889    "\
3890 This call allows you to perform the C<guestfs_lstat> operation
3891 on multiple files, where all files are in the directory C<path>.
3892 C<names> is the list of files from this directory.
3893
3894 On return you get a list of stat structs, with a one-to-one
3895 correspondence to the C<names> list.  If any name did not exist
3896 or could not be lstat'd, then the C<ino> field of that structure
3897 is set to C<-1>.
3898
3899 This call is intended for programs that want to efficiently
3900 list a directory contents without making many round-trips.
3901 See also C<guestfs_lxattrlist> for a similarly efficient call
3902 for getting extended attributes.  Very long directory listings
3903 might cause the protocol message size to be exceeded, causing
3904 this call to fail.  The caller must split up such requests
3905 into smaller groups of names.");
3906
3907   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3908    [], (* XXX *)
3909    "lgetxattr on multiple files",
3910    "\
3911 This call allows you to get the extended attributes
3912 of multiple files, where all files are in the directory C<path>.
3913 C<names> is the list of files from this directory.
3914
3915 On return you get a flat list of xattr structs which must be
3916 interpreted sequentially.  The first xattr struct always has a zero-length
3917 C<attrname>.  C<attrval> in this struct is zero-length
3918 to indicate there was an error doing C<lgetxattr> for this
3919 file, I<or> is a C string which is a decimal number
3920 (the number of following attributes for this file, which could
3921 be C<\"0\">).  Then after the first xattr struct are the
3922 zero or more attributes for the first named file.
3923 This repeats for the second and subsequent files.
3924
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lstatlist> for a similarly efficient call
3928 for getting standard stats.  Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail.  The caller must split up such requests
3931 into smaller groups of names.");
3932
3933   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3934    [], (* XXX *)
3935    "readlink on multiple files",
3936    "\
3937 This call allows you to do a C<readlink> operation
3938 on multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3940
3941 On return you get a list of strings, with a one-to-one
3942 correspondence to the C<names> list.  Each string is the
3943 value of the symbol link.
3944
3945 If the C<readlink(2)> operation fails on any name, then
3946 the corresponding result string is the empty string C<\"\">.
3947 However the whole operation is completed even if there
3948 were C<readlink(2)> errors, and so you can call this
3949 function with names where you don't know if they are
3950 symbolic links already (albeit slightly less efficient).
3951
3952 This call is intended for programs that want to efficiently
3953 list a directory contents without making many round-trips.
3954 Very long directory listings might cause the protocol
3955 message size to be exceeded, causing
3956 this call to fail.  The caller must split up such requests
3957 into smaller groups of names.");
3958
3959   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3960    [InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/known-4"; "1"; "3"]], "\n");
3962     InitISOFS, Always, TestOutputBuffer (
3963       [["pread"; "/empty"; "0"; "100"]], "")],
3964    "read part of a file",
3965    "\
3966 This command lets you read part of a file.  It reads C<count>
3967 bytes of the file, starting at C<offset>, from file C<path>.
3968
3969 This may read fewer bytes than requested.  For further details
3970 see the L<pread(2)> system call.");
3971
3972   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3973    [InitEmpty, Always, TestRun (
3974       [["part_init"; "/dev/sda"; "gpt"]])],
3975    "create an empty partition table",
3976    "\
3977 This creates an empty partition table on C<device> of one of the
3978 partition types listed below.  Usually C<parttype> should be
3979 either C<msdos> or C<gpt> (for large disks).
3980
3981 Initially there are no partitions.  Following this, you should
3982 call C<guestfs_part_add> for each partition required.
3983
3984 Possible values for C<parttype> are:
3985
3986 =over 4
3987
3988 =item B<efi> | B<gpt>
3989
3990 Intel EFI / GPT partition table.
3991
3992 This is recommended for >= 2 TB partitions that will be accessed
3993 from Linux and Intel-based Mac OS X.  It also has limited backwards
3994 compatibility with the C<mbr> format.
3995
3996 =item B<mbr> | B<msdos>
3997
3998 The standard PC \"Master Boot Record\" (MBR) format used
3999 by MS-DOS and Windows.  This partition type will B<only> work
4000 for device sizes up to 2 TB.  For large disks we recommend
4001 using C<gpt>.
4002
4003 =back
4004
4005 Other partition table types that may work but are not
4006 supported include:
4007
4008 =over 4
4009
4010 =item B<aix>
4011
4012 AIX disk labels.
4013
4014 =item B<amiga> | B<rdb>
4015
4016 Amiga \"Rigid Disk Block\" format.
4017
4018 =item B<bsd>
4019
4020 BSD disk labels.
4021
4022 =item B<dasd>
4023
4024 DASD, used on IBM mainframes.
4025
4026 =item B<dvh>
4027
4028 MIPS/SGI volumes.
4029
4030 =item B<mac>
4031
4032 Old Mac partition format.  Modern Macs use C<gpt>.
4033
4034 =item B<pc98>
4035
4036 NEC PC-98 format, common in Japan apparently.
4037
4038 =item B<sun>
4039
4040 Sun disk labels.
4041
4042 =back");
4043
4044   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4045    [InitEmpty, Always, TestRun (
4046       [["part_init"; "/dev/sda"; "mbr"];
4047        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4048     InitEmpty, Always, TestRun (
4049       [["part_init"; "/dev/sda"; "gpt"];
4050        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4051        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4052     InitEmpty, Always, TestRun (
4053       [["part_init"; "/dev/sda"; "mbr"];
4054        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4055        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4056        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4057        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4058    "add a partition to the device",
4059    "\
4060 This command adds a partition to C<device>.  If there is no partition
4061 table on the device, call C<guestfs_part_init> first.
4062
4063 The C<prlogex> parameter is the type of partition.  Normally you
4064 should pass C<p> or C<primary> here, but MBR partition tables also
4065 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4066 types.
4067
4068 C<startsect> and C<endsect> are the start and end of the partition
4069 in I<sectors>.  C<endsect> may be negative, which means it counts
4070 backwards from the end of the disk (C<-1> is the last sector).
4071
4072 Creating a partition which covers the whole disk is not so easy.
4073 Use C<guestfs_part_disk> to do that.");
4074
4075   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4076    [InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "mbr"]]);
4078     InitEmpty, Always, TestRun (
4079       [["part_disk"; "/dev/sda"; "gpt"]])],
4080    "partition whole disk with a single primary partition",
4081    "\
4082 This command is simply a combination of C<guestfs_part_init>
4083 followed by C<guestfs_part_add> to create a single primary partition
4084 covering the whole disk.
4085
4086 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4087 but other possible values are described in C<guestfs_part_init>.");
4088
4089   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4090    [InitEmpty, Always, TestRun (
4091       [["part_disk"; "/dev/sda"; "mbr"];
4092        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4093    "make a partition bootable",
4094    "\
4095 This sets the bootable flag on partition numbered C<partnum> on
4096 device C<device>.  Note that partitions are numbered from 1.
4097
4098 The bootable flag is used by some operating systems (notably
4099 Windows) to determine which partition to boot from.  It is by
4100 no means universally recognized.");
4101
4102   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4103    [InitEmpty, Always, TestRun (
4104       [["part_disk"; "/dev/sda"; "gpt"];
4105        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4106    "set partition name",
4107    "\
4108 This sets the partition name on partition numbered C<partnum> on
4109 device C<device>.  Note that partitions are numbered from 1.
4110
4111 The partition name can only be set on certain types of partition
4112 table.  This works on C<gpt> but not on C<mbr> partitions.");
4113
4114   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4115    [], (* XXX Add a regression test for this. *)
4116    "list partitions on a device",
4117    "\
4118 This command parses the partition table on C<device> and
4119 returns the list of partitions found.
4120
4121 The fields in the returned structure are:
4122
4123 =over 4
4124
4125 =item B<part_num>
4126
4127 Partition number, counting from 1.
4128
4129 =item B<part_start>
4130
4131 Start of the partition I<in bytes>.  To get sectors you have to
4132 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4133
4134 =item B<part_end>
4135
4136 End of the partition in bytes.
4137
4138 =item B<part_size>
4139
4140 Size of the partition in bytes.
4141
4142 =back");
4143
4144   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4145    [InitEmpty, Always, TestOutput (
4146       [["part_disk"; "/dev/sda"; "gpt"];
4147        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4148    "get the partition table type",
4149    "\
4150 This command examines the partition table on C<device> and
4151 returns the partition table type (format) being used.
4152
4153 Common return values include: C<msdos> (a DOS/Windows style MBR
4154 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4155 values are possible, although unusual.  See C<guestfs_part_init>
4156 for a full list.");
4157
4158   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4159    [InitBasicFS, Always, TestOutputBuffer (
4160       [["fill"; "0x63"; "10"; "/test"];
4161        ["read_file"; "/test"]], "cccccccccc")],
4162    "fill a file with octets",
4163    "\
4164 This command creates a new file called C<path>.  The initial
4165 content of the file is C<len> octets of C<c>, where C<c>
4166 must be a number in the range C<[0..255]>.
4167
4168 To fill a file with zero bytes (sparsely), it is
4169 much more efficient to use C<guestfs_truncate_size>.");
4170
4171   ("available", (RErr, [StringList "groups"]), 216, [],
4172    [InitNone, Always, TestRun [["available"; ""]]],
4173    "test availability of some parts of the API",
4174    "\
4175 This command is used to check the availability of some
4176 groups of functionality in the appliance, which not all builds of
4177 the libguestfs appliance will be able to provide.
4178
4179 The libguestfs groups, and the functions that those
4180 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4181
4182 The argument C<groups> is a list of group names, eg:
4183 C<[\"inotify\", \"augeas\"]> would check for the availability of
4184 the Linux inotify functions and Augeas (configuration file
4185 editing) functions.
4186
4187 The command returns no error if I<all> requested groups are available.
4188
4189 It fails with an error if one or more of the requested
4190 groups is unavailable in the appliance.
4191
4192 If an unknown group name is included in the
4193 list of groups then an error is always returned.
4194
4195 I<Notes:>
4196
4197 =over 4
4198
4199 =item *
4200
4201 You must call C<guestfs_launch> before calling this function.
4202
4203 The reason is because we don't know what groups are
4204 supported by the appliance/daemon until it is running and can
4205 be queried.
4206
4207 =item *
4208
4209 If a group of functions is available, this does not necessarily
4210 mean that they will work.  You still have to check for errors
4211 when calling individual API functions even if they are
4212 available.
4213
4214 =item *
4215
4216 It is usually the job of distro packagers to build
4217 complete functionality into the libguestfs appliance.
4218 Upstream libguestfs, if built from source with all
4219 requirements satisfied, will support everything.
4220
4221 =item *
4222
4223 This call was added in version C<1.0.80>.  In previous
4224 versions of libguestfs all you could do would be to speculatively
4225 execute a command to find out if the daemon implemented it.
4226 See also C<guestfs_version>.
4227
4228 =back");
4229
4230   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4231    [InitBasicFS, Always, TestOutputBuffer (
4232       [["write_file"; "/src"; "hello, world"; "0"];
4233        ["dd"; "/src"; "/dest"];
4234        ["read_file"; "/dest"]], "hello, world")],
4235    "copy from source to destination using dd",
4236    "\
4237 This command copies from one source device or file C<src>
4238 to another destination device or file C<dest>.  Normally you
4239 would use this to copy to or from a device or partition, for
4240 example to duplicate a filesystem.
4241
4242 If the destination is a device, it must be as large or larger
4243 than the source file or device, otherwise the copy will fail.
4244 This command cannot do partial copies (see C<guestfs_copy_size>).");
4245
4246   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4247    [InitBasicFS, Always, TestOutputInt (
4248       [["write_file"; "/file"; "hello, world"; "0"];
4249        ["filesize"; "/file"]], 12)],
4250    "return the size of the file in bytes",
4251    "\
4252 This command returns the size of C<file> in bytes.
4253
4254 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4255 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4256 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4257
4258   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4259    [InitBasicFSonLVM, Always, TestOutputList (
4260       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4261        ["lvs"]], ["/dev/VG/LV2"])],
4262    "rename an LVM logical volume",
4263    "\
4264 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4265
4266   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4267    [InitBasicFSonLVM, Always, TestOutputList (
4268       [["umount"; "/"];
4269        ["vg_activate"; "false"; "VG"];
4270        ["vgrename"; "VG"; "VG2"];
4271        ["vg_activate"; "true"; "VG2"];
4272        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4273        ["vgs"]], ["VG2"])],
4274    "rename an LVM volume group",
4275    "\
4276 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4277
4278   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4279    [InitISOFS, Always, TestOutputBuffer (
4280       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4281    "list the contents of a single file in an initrd",
4282    "\
4283 This command unpacks the file C<filename> from the initrd file
4284 called C<initrdpath>.  The filename must be given I<without> the
4285 initial C</> character.
4286
4287 For example, in guestfish you could use the following command
4288 to examine the boot script (usually called C</init>)
4289 contained in a Linux initrd or initramfs image:
4290
4291  initrd-cat /boot/initrd-<version>.img init
4292
4293 See also C<guestfs_initrd_list>.");
4294
4295   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4296    [],
4297    "get the UUID of a physical volume",
4298    "\
4299 This command returns the UUID of the LVM PV C<device>.");
4300
4301   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4302    [],
4303    "get the UUID of a volume group",
4304    "\
4305 This command returns the UUID of the LVM VG named C<vgname>.");
4306
4307   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4308    [],
4309    "get the UUID of a logical volume",
4310    "\
4311 This command returns the UUID of the LVM LV C<device>.");
4312
4313   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4314    [],
4315    "get the PV UUIDs containing the volume group",
4316    "\
4317 Given a VG called C<vgname>, this returns the UUIDs of all
4318 the physical volumes that this volume group resides on.
4319
4320 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4321 calls to associate physical volumes and volume groups.
4322
4323 See also C<guestfs_vglvuuids>.");
4324
4325   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4326    [],
4327    "get the LV UUIDs of all LVs in the volume group",
4328    "\
4329 Given a VG called C<vgname>, this returns the UUIDs of all
4330 the logical volumes created in this volume group.
4331
4332 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4333 calls to associate logical volumes and volume groups.
4334
4335 See also C<guestfs_vgpvuuids>.");
4336
4337   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4338    [InitBasicFS, Always, TestOutputBuffer (
4339       [["write_file"; "/src"; "hello, world"; "0"];
4340        ["copy_size"; "/src"; "/dest"; "5"];
4341        ["read_file"; "/dest"]], "hello")],
4342    "copy size bytes from source to destination using dd",
4343    "\
4344 This command copies exactly C<size> bytes from one source device
4345 or file C<src> to another destination device or file C<dest>.
4346
4347 Note this will fail if the source is too short or if the destination
4348 is not large enough.");
4349
4350   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4351    [InitBasicFSonLVM, Always, TestRun (
4352       [["zero_device"; "/dev/VG/LV"]])],
4353    "write zeroes to an entire device",
4354    "\
4355 This command writes zeroes over the entire C<device>.  Compare
4356 with C<guestfs_zero> which just zeroes the first few blocks of
4357 a device.");
4358
4359   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4360    [InitBasicFS, Always, TestOutput (
4361       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4362        ["cat"; "/hello"]], "hello\n")],
4363    "unpack compressed tarball to directory",
4364    "\
4365 This command uploads and unpacks local file C<tarball> (an
4366 I<xz compressed> tar file) into C<directory>.");
4367
4368   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4369    [],
4370    "pack directory into compressed tarball",
4371    "\
4372 This command packs the contents of C<directory> and downloads
4373 it to local file C<tarball> (as an xz compressed tar archive).");
4374
4375   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4376    [],
4377    "resize an NTFS filesystem",
4378    "\
4379 This command resizes an NTFS filesystem, expanding or
4380 shrinking it to the size of the underlying device.
4381 See also L<ntfsresize(8)>.");
4382
4383   ("vgscan", (RErr, []), 232, [],
4384    [InitEmpty, Always, TestRun (
4385       [["vgscan"]])],
4386    "rescan for LVM physical volumes, volume groups and logical volumes",
4387    "\
4388 This rescans all block devices and rebuilds the list of LVM
4389 physical volumes, volume groups and logical volumes.");
4390
4391   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4392    [InitEmpty, Always, TestRun (
4393       [["part_init"; "/dev/sda"; "mbr"];
4394        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4395        ["part_del"; "/dev/sda"; "1"]])],
4396    "delete a partition",
4397    "\
4398 This command deletes the partition numbered C<partnum> on C<device>.
4399
4400 Note that in the case of MBR partitioning, deleting an
4401 extended partition also deletes any logical partitions
4402 it contains.");
4403
4404   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4405    [InitEmpty, Always, TestOutputTrue (
4406       [["part_init"; "/dev/sda"; "mbr"];
4407        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4408        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4409        ["part_get_bootable"; "/dev/sda"; "1"]])],
4410    "return true if a partition is bootable",
4411    "\
4412 This command returns true if the partition C<partnum> on
4413 C<device> has the bootable flag set.
4414
4415 See also C<guestfs_part_set_bootable>.");
4416
4417   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4418    [InitEmpty, Always, TestOutputInt (
4419       [["part_init"; "/dev/sda"; "mbr"];
4420        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4421        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4422        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4423    "get the MBR type byte (ID byte) from a partition",
4424    "\
4425 Returns the MBR type byte (also known as the ID byte) from
4426 the numbered partition C<partnum>.
4427
4428 Note that only MBR (old DOS-style) partitions have type bytes.
4429 You will get undefined results for other partition table
4430 types (see C<guestfs_part_get_parttype>).");
4431
4432   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4433    [], (* tested by part_get_mbr_id *)
4434    "set the MBR type byte (ID byte) of a partition",
4435    "\
4436 Sets the MBR type byte (also known as the ID byte) of
4437 the numbered partition C<partnum> to C<idbyte>.  Note
4438 that the type bytes quoted in most documentation are
4439 in fact hexadecimal numbers, but usually documented
4440 without any leading \"0x\" which might be confusing.
4441
4442 Note that only MBR (old DOS-style) partitions have type bytes.
4443 You will get undefined results for other partition table
4444 types (see C<guestfs_part_get_parttype>).");
4445
4446   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4447    [InitISOFS, Always, TestOutput (
4448       [["checksum_device"; "md5"; "/dev/sdd"]],
4449       (Digest.to_hex (Digest.file "images/test.iso")))],
4450    "compute MD5, SHAx or CRC checksum of the contents of a device",
4451    "\
4452 This call computes the MD5, SHAx or CRC checksum of the
4453 contents of the device named C<device>.  For the types of
4454 checksums supported see the C<guestfs_checksum> command.");
4455
4456 ]
4457
4458 let all_functions = non_daemon_functions @ daemon_functions
4459
4460 (* In some places we want the functions to be displayed sorted
4461  * alphabetically, so this is useful:
4462  *)
4463 let all_functions_sorted =
4464   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4465                compare n1 n2) all_functions
4466
4467 (* Field types for structures. *)
4468 type field =
4469   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4470   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4471   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4472   | FUInt32
4473   | FInt32
4474   | FUInt64
4475   | FInt64
4476   | FBytes                      (* Any int measure that counts bytes. *)
4477   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4478   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4479
4480 (* Because we generate extra parsing code for LVM command line tools,
4481  * we have to pull out the LVM columns separately here.
4482  *)
4483 let lvm_pv_cols = [
4484   "pv_name", FString;
4485   "pv_uuid", FUUID;
4486   "pv_fmt", FString;
4487   "pv_size", FBytes;
4488   "dev_size", FBytes;
4489   "pv_free", FBytes;
4490   "pv_used", FBytes;
4491   "pv_attr", FString (* XXX *);
4492   "pv_pe_count", FInt64;
4493   "pv_pe_alloc_count", FInt64;
4494   "pv_tags", FString;
4495   "pe_start", FBytes;
4496   "pv_mda_count", FInt64;
4497   "pv_mda_free", FBytes;
4498   (* Not in Fedora 10:
4499      "pv_mda_size", FBytes;
4500   *)
4501 ]
4502 let lvm_vg_cols = [
4503   "vg_name", FString;
4504   "vg_uuid", FUUID;
4505   "vg_fmt", FString;
4506   "vg_attr", FString (* XXX *);
4507   "vg_size", FBytes;
4508   "vg_free", FBytes;
4509   "vg_sysid", FString;
4510   "vg_extent_size", FBytes;
4511   "vg_extent_count", FInt64;
4512   "vg_free_count", FInt64;
4513   "max_lv", FInt64;
4514   "max_pv", FInt64;
4515   "pv_count", FInt64;
4516   "lv_count", FInt64;
4517   "snap_count", FInt64;
4518   "vg_seqno", FInt64;
4519   "vg_tags", FString;
4520   "vg_mda_count", FInt64;
4521   "vg_mda_free", FBytes;
4522   (* Not in Fedora 10:
4523      "vg_mda_size", FBytes;
4524   *)
4525 ]
4526 let lvm_lv_cols = [
4527   "lv_name", FString;
4528   "lv_uuid", FUUID;
4529   "lv_attr", FString (* XXX *);
4530   "lv_major", FInt64;
4531   "lv_minor", FInt64;
4532   "lv_kernel_major", FInt64;
4533   "lv_kernel_minor", FInt64;
4534   "lv_size", FBytes;
4535   "seg_count", FInt64;
4536   "origin", FString;
4537   "snap_percent", FOptPercent;
4538   "copy_percent", FOptPercent;
4539   "move_pv", FString;
4540   "lv_tags", FString;
4541   "mirror_log", FString;
4542   "modules", FString;
4543 ]
4544
4545 (* Names and fields in all structures (in RStruct and RStructList)
4546  * that we support.
4547  *)
4548 let structs = [
4549   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4550    * not use this struct in any new code.
4551    *)
4552   "int_bool", [
4553     "i", FInt32;                (* for historical compatibility *)
4554     "b", FInt32;                (* for historical compatibility *)
4555   ];
4556
4557   (* LVM PVs, VGs, LVs. *)
4558   "lvm_pv", lvm_pv_cols;
4559   "lvm_vg", lvm_vg_cols;
4560   "lvm_lv", lvm_lv_cols;
4561
4562   (* Column names and types from stat structures.
4563    * NB. Can't use things like 'st_atime' because glibc header files
4564    * define some of these as macros.  Ugh.
4565    *)
4566   "stat", [
4567     "dev", FInt64;
4568     "ino", FInt64;
4569     "mode", FInt64;
4570     "nlink", FInt64;
4571     "uid", FInt64;
4572     "gid", FInt64;
4573     "rdev", FInt64;
4574     "size", FInt64;
4575     "blksize", FInt64;
4576     "blocks", FInt64;
4577     "atime", FInt64;
4578     "mtime", FInt64;
4579     "ctime", FInt64;
4580   ];
4581   "statvfs", [
4582     "bsize", FInt64;
4583     "frsize", FInt64;
4584     "blocks", FInt64;
4585     "bfree", FInt64;
4586     "bavail", FInt64;
4587     "files", FInt64;
4588     "ffree", FInt64;
4589     "favail", FInt64;
4590     "fsid", FInt64;
4591     "flag", FInt64;
4592     "namemax", FInt64;
4593   ];
4594
4595   (* Column names in dirent structure. *)
4596   "dirent", [
4597     "ino", FInt64;
4598     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4599     "ftyp", FChar;
4600     "name", FString;
4601   ];
4602
4603   (* Version numbers. *)
4604   "version", [
4605     "major", FInt64;
4606     "minor", FInt64;
4607     "release", FInt64;
4608     "extra", FString;
4609   ];
4610
4611   (* Extended attribute. *)
4612   "xattr", [
4613     "attrname", FString;
4614     "attrval", FBuffer;
4615   ];
4616
4617   (* Inotify events. *)
4618   "inotify_event", [
4619     "in_wd", FInt64;
4620     "in_mask", FUInt32;
4621     "in_cookie", FUInt32;
4622     "in_name", FString;
4623   ];
4624
4625   (* Partition table entry. *)
4626   "partition", [
4627     "part_num", FInt32;
4628     "part_start", FBytes;
4629     "part_end", FBytes;
4630     "part_size", FBytes;
4631   ];
4632 ] (* end of structs *)
4633
4634 (* Ugh, Java has to be different ..
4635  * These names are also used by the Haskell bindings.
4636  *)
4637 let java_structs = [
4638   "int_bool", "IntBool";
4639   "lvm_pv", "PV";
4640   "lvm_vg", "VG";
4641   "lvm_lv", "LV";
4642   "stat", "Stat";
4643   "statvfs", "StatVFS";
4644   "dirent", "Dirent";
4645   "version", "Version";
4646   "xattr", "XAttr";
4647   "inotify_event", "INotifyEvent";
4648   "partition", "Partition";
4649 ]
4650
4651 (* What structs are actually returned. *)
4652 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4653
4654 (* Returns a list of RStruct/RStructList structs that are returned
4655  * by any function.  Each element of returned list is a pair:
4656  *
4657  * (structname, RStructOnly)
4658  *    == there exists function which returns RStruct (_, structname)
4659  * (structname, RStructListOnly)
4660  *    == there exists function which returns RStructList (_, structname)
4661  * (structname, RStructAndList)
4662  *    == there are functions returning both RStruct (_, structname)
4663  *                                      and RStructList (_, structname)
4664  *)
4665 let rstructs_used_by functions =
4666   (* ||| is a "logical OR" for rstructs_used_t *)
4667   let (|||) a b =
4668     match a, b with
4669     | RStructAndList, _
4670     | _, RStructAndList -> RStructAndList
4671     | RStructOnly, RStructListOnly
4672     | RStructListOnly, RStructOnly -> RStructAndList
4673     | RStructOnly, RStructOnly -> RStructOnly
4674     | RStructListOnly, RStructListOnly -> RStructListOnly
4675   in
4676
4677   let h = Hashtbl.create 13 in
4678
4679   (* if elem->oldv exists, update entry using ||| operator,
4680    * else just add elem->newv to the hash
4681    *)
4682   let update elem newv =
4683     try  let oldv = Hashtbl.find h elem in
4684          Hashtbl.replace h elem (newv ||| oldv)
4685     with Not_found -> Hashtbl.add h elem newv
4686   in
4687
4688   List.iter (
4689     fun (_, style, _, _, _, _, _) ->
4690       match fst style with
4691       | RStruct (_, structname) -> update structname RStructOnly
4692       | RStructList (_, structname) -> update structname RStructListOnly
4693       | _ -> ()
4694   ) functions;
4695
4696   (* return key->values as a list of (key,value) *)
4697   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4698
4699 (* Used for testing language bindings. *)
4700 type callt =
4701   | CallString of string
4702   | CallOptString of string option
4703   | CallStringList of string list
4704   | CallInt of int
4705   | CallInt64 of int64
4706   | CallBool of bool
4707
4708 (* Used to memoize the result of pod2text. *)
4709 let pod2text_memo_filename = "src/.pod2text.data"
4710 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4711   try
4712     let chan = open_in pod2text_memo_filename in
4713     let v = input_value chan in
4714     close_in chan;
4715     v
4716   with
4717     _ -> Hashtbl.create 13
4718 let pod2text_memo_updated () =
4719   let chan = open_out pod2text_memo_filename in
4720   output_value chan pod2text_memo;
4721   close_out chan
4722
4723 (* Useful functions.
4724  * Note we don't want to use any external OCaml libraries which
4725  * makes this a bit harder than it should be.
4726  *)
4727 module StringMap = Map.Make (String)
4728
4729 let failwithf fs = ksprintf failwith fs
4730
4731 let unique = let i = ref 0 in fun () -> incr i; !i
4732
4733 let replace_char s c1 c2 =
4734   let s2 = String.copy s in
4735   let r = ref false in
4736   for i = 0 to String.length s2 - 1 do
4737     if String.unsafe_get s2 i = c1 then (
4738       String.unsafe_set s2 i c2;
4739       r := true
4740     )
4741   done;
4742   if not !r then s else s2
4743
4744 let isspace c =
4745   c = ' '
4746   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4747
4748 let triml ?(test = isspace) str =
4749   let i = ref 0 in
4750   let n = ref (String.length str) in
4751   while !n > 0 && test str.[!i]; do
4752     decr n;
4753     incr i
4754   done;
4755   if !i = 0 then str
4756   else String.sub str !i !n
4757
4758 let trimr ?(test = isspace) str =
4759   let n = ref (String.length str) in
4760   while !n > 0 && test str.[!n-1]; do
4761     decr n
4762   done;
4763   if !n = String.length str then str
4764   else String.sub str 0 !n
4765
4766 let trim ?(test = isspace) str =
4767   trimr ~test (triml ~test str)
4768
4769 let rec find s sub =
4770   let len = String.length s in
4771   let sublen = String.length sub in
4772   let rec loop i =
4773     if i <= len-sublen then (
4774       let rec loop2 j =
4775         if j < sublen then (
4776           if s.[i+j] = sub.[j] then loop2 (j+1)
4777           else -1
4778         ) else
4779           i (* found *)
4780       in
4781       let r = loop2 0 in
4782       if r = -1 then loop (i+1) else r
4783     ) else
4784       -1 (* not found *)
4785   in
4786   loop 0
4787
4788 let rec replace_str s s1 s2 =
4789   let len = String.length s in
4790   let sublen = String.length s1 in
4791   let i = find s s1 in
4792   if i = -1 then s
4793   else (
4794     let s' = String.sub s 0 i in
4795     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4796     s' ^ s2 ^ replace_str s'' s1 s2
4797   )
4798
4799 let rec string_split sep str =
4800   let len = String.length str in
4801   let seplen = String.length sep in
4802   let i = find str sep in
4803   if i = -1 then [str]
4804   else (
4805     let s' = String.sub str 0 i in
4806     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4807     s' :: string_split sep s''
4808   )
4809
4810 let files_equal n1 n2 =
4811   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4812   match Sys.command cmd with
4813   | 0 -> true
4814   | 1 -> false
4815   | i -> failwithf "%s: failed with error code %d" cmd i
4816
4817 let rec filter_map f = function
4818   | [] -> []
4819   | x :: xs ->
4820       match f x with
4821       | Some y -> y :: filter_map f xs
4822       | None -> filter_map f xs
4823
4824 let rec find_map f = function
4825   | [] -> raise Not_found
4826   | x :: xs ->
4827       match f x with
4828       | Some y -> y
4829       | None -> find_map f xs
4830
4831 let iteri f xs =
4832   let rec loop i = function
4833     | [] -> ()
4834     | x :: xs -> f i x; loop (i+1) xs
4835   in
4836   loop 0 xs
4837
4838 let mapi f xs =
4839   let rec loop i = function
4840     | [] -> []
4841     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4842   in
4843   loop 0 xs
4844
4845 let count_chars c str =
4846   let count = ref 0 in
4847   for i = 0 to String.length str - 1 do
4848     if c = String.unsafe_get str i then incr count
4849   done;
4850   !count
4851
4852 let name_of_argt = function
4853   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4854   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4855   | FileIn n | FileOut n -> n
4856
4857 let java_name_of_struct typ =
4858   try List.assoc typ java_structs
4859   with Not_found ->
4860     failwithf
4861       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4862
4863 let cols_of_struct typ =
4864   try List.assoc typ structs
4865   with Not_found ->
4866     failwithf "cols_of_struct: unknown struct %s" typ
4867
4868 let seq_of_test = function
4869   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4870   | TestOutputListOfDevices (s, _)
4871   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4872   | TestOutputTrue s | TestOutputFalse s
4873   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4874   | TestOutputStruct (s, _)
4875   | TestLastFail s -> s
4876
4877 (* Handling for function flags. *)
4878 let protocol_limit_warning =
4879   "Because of the message protocol, there is a transfer limit
4880 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4881
4882 let danger_will_robinson =
4883   "B<This command is dangerous.  Without careful use you
4884 can easily destroy all your data>."
4885
4886 let deprecation_notice flags =
4887   try
4888     let alt =
4889       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4890     let txt =
4891       sprintf "This function is deprecated.
4892 In new code, use the C<%s> call instead.
4893
4894 Deprecated functions will not be removed from the API, but the
4895 fact that they are deprecated indicates that there are problems
4896 with correct use of these functions." alt in
4897     Some txt
4898   with
4899     Not_found -> None
4900
4901 (* Create list of optional groups. *)
4902 let optgroups =
4903   let h = Hashtbl.create 13 in
4904   List.iter (
4905     fun (name, _, _, flags, _, _, _) ->
4906       List.iter (
4907         function
4908         | Optional group ->
4909             let names = try Hashtbl.find h group with Not_found -> [] in
4910             Hashtbl.replace h group (name :: names)
4911         | _ -> ()
4912       ) flags
4913   ) daemon_functions;
4914   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4915   let groups =
4916     List.map (
4917       fun group -> group, List.sort compare (Hashtbl.find h group)
4918     ) groups in
4919   List.sort (fun x y -> compare (fst x) (fst y)) groups
4920
4921 (* Check function names etc. for consistency. *)
4922 let check_functions () =
4923   let contains_uppercase str =
4924     let len = String.length str in
4925     let rec loop i =
4926       if i >= len then false
4927       else (
4928         let c = str.[i] in
4929         if c >= 'A' && c <= 'Z' then true
4930         else loop (i+1)
4931       )
4932     in
4933     loop 0
4934   in
4935
4936   (* Check function names. *)
4937   List.iter (
4938     fun (name, _, _, _, _, _, _) ->
4939       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4940         failwithf "function name %s does not need 'guestfs' prefix" name;
4941       if name = "" then
4942         failwithf "function name is empty";
4943       if name.[0] < 'a' || name.[0] > 'z' then
4944         failwithf "function name %s must start with lowercase a-z" name;
4945       if String.contains name '-' then
4946         failwithf "function name %s should not contain '-', use '_' instead."
4947           name
4948   ) all_functions;
4949
4950   (* Check function parameter/return names. *)
4951   List.iter (
4952     fun (name, style, _, _, _, _, _) ->
4953       let check_arg_ret_name n =
4954         if contains_uppercase n then
4955           failwithf "%s param/ret %s should not contain uppercase chars"
4956             name n;
4957         if String.contains n '-' || String.contains n '_' then
4958           failwithf "%s param/ret %s should not contain '-' or '_'"
4959             name n;
4960         if n = "value" then
4961           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;
4962         if n = "int" || n = "char" || n = "short" || n = "long" then
4963           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4964         if n = "i" || n = "n" then
4965           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4966         if n = "argv" || n = "args" then
4967           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4968
4969         (* List Haskell, OCaml and C keywords here.
4970          * http://www.haskell.org/haskellwiki/Keywords
4971          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4972          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4973          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4974          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4975          * Omitting _-containing words, since they're handled above.
4976          * Omitting the OCaml reserved word, "val", is ok,
4977          * and saves us from renaming several parameters.
4978          *)
4979         let reserved = [
4980           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4981           "char"; "class"; "const"; "constraint"; "continue"; "data";
4982           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4983           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4984           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4985           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4986           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4987           "interface";
4988           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4989           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4990           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4991           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4992           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4993           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4994           "volatile"; "when"; "where"; "while";
4995           ] in
4996         if List.mem n reserved then
4997           failwithf "%s has param/ret using reserved word %s" name n;
4998       in
4999
5000       (match fst style with
5001        | RErr -> ()
5002        | RInt n | RInt64 n | RBool n
5003        | RConstString n | RConstOptString n | RString n
5004        | RStringList n | RStruct (n, _) | RStructList (n, _)
5005        | RHashtable n | RBufferOut n ->
5006            check_arg_ret_name n
5007       );
5008       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5009   ) all_functions;
5010
5011   (* Check short descriptions. *)
5012   List.iter (
5013     fun (name, _, _, _, _, shortdesc, _) ->
5014       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5015         failwithf "short description of %s should begin with lowercase." name;
5016       let c = shortdesc.[String.length shortdesc-1] in
5017       if c = '\n' || c = '.' then
5018         failwithf "short description of %s should not end with . or \\n." name
5019   ) all_functions;
5020
5021   (* Check long dscriptions. *)
5022   List.iter (
5023     fun (name, _, _, _, _, _, longdesc) ->
5024       if longdesc.[String.length longdesc-1] = '\n' then
5025         failwithf "long description of %s should not end with \\n." name
5026   ) all_functions;
5027
5028   (* Check proc_nrs. *)
5029   List.iter (
5030     fun (name, _, proc_nr, _, _, _, _) ->
5031       if proc_nr <= 0 then
5032         failwithf "daemon function %s should have proc_nr > 0" name
5033   ) daemon_functions;
5034
5035   List.iter (
5036     fun (name, _, proc_nr, _, _, _, _) ->
5037       if proc_nr <> -1 then
5038         failwithf "non-daemon function %s should have proc_nr -1" name
5039   ) non_daemon_functions;
5040
5041   let proc_nrs =
5042     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5043       daemon_functions in
5044   let proc_nrs =
5045     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5046   let rec loop = function
5047     | [] -> ()
5048     | [_] -> ()
5049     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5050         loop rest
5051     | (name1,nr1) :: (name2,nr2) :: _ ->
5052         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5053           name1 name2 nr1 nr2
5054   in
5055   loop proc_nrs;
5056
5057   (* Check tests. *)
5058   List.iter (
5059     function
5060       (* Ignore functions that have no tests.  We generate a
5061        * warning when the user does 'make check' instead.
5062        *)
5063     | name, _, _, _, [], _, _ -> ()
5064     | name, _, _, _, tests, _, _ ->
5065         let funcs =
5066           List.map (
5067             fun (_, _, test) ->
5068               match seq_of_test test with
5069               | [] ->
5070                   failwithf "%s has a test containing an empty sequence" name
5071               | cmds -> List.map List.hd cmds
5072           ) tests in
5073         let funcs = List.flatten funcs in
5074
5075         let tested = List.mem name funcs in
5076
5077         if not tested then
5078           failwithf "function %s has tests but does not test itself" name
5079   ) all_functions
5080
5081 (* 'pr' prints to the current output file. *)
5082 let chan = ref Pervasives.stdout
5083 let lines = ref 0
5084 let pr fs =
5085   ksprintf
5086     (fun str ->
5087        let i = count_chars '\n' str in
5088        lines := !lines + i;
5089        output_string !chan str
5090     ) fs
5091
5092 let copyright_years =
5093   let this_year = 1900 + (localtime (time ())).tm_year in
5094   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5095
5096 (* Generate a header block in a number of standard styles. *)
5097 type comment_style =
5098     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5099 type license = GPLv2plus | LGPLv2plus
5100
5101 let generate_header ?(extra_inputs = []) comment license =
5102   let inputs = "src/generator.ml" :: extra_inputs in
5103   let c = match comment with
5104     | CStyle ->         pr "/* "; " *"
5105     | CPlusPlusStyle -> pr "// "; "//"
5106     | HashStyle ->      pr "# ";  "#"
5107     | OCamlStyle ->     pr "(* "; " *"
5108     | HaskellStyle ->   pr "{- "; "  " in
5109   pr "libguestfs generated file\n";
5110   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5111   List.iter (pr "%s   %s\n" c) inputs;
5112   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5113   pr "%s\n" c;
5114   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5115   pr "%s\n" c;
5116   (match license with
5117    | GPLv2plus ->
5118        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5119        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5120        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5121        pr "%s (at your option) any later version.\n" c;
5122        pr "%s\n" c;
5123        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5124        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5125        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5126        pr "%s GNU General Public License for more details.\n" c;
5127        pr "%s\n" c;
5128        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5129        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5130        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5131
5132    | LGPLv2plus ->
5133        pr "%s This library is free software; you can redistribute it and/or\n" c;
5134        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5135        pr "%s License as published by the Free Software Foundation; either\n" c;
5136        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5137        pr "%s\n" c;
5138        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5139        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5140        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5141        pr "%s Lesser General Public License for more details.\n" c;
5142        pr "%s\n" c;
5143        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5144        pr "%s License along with this library; if not, write to the Free Software\n" c;
5145        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5146   );
5147   (match comment with
5148    | CStyle -> pr " */\n"
5149    | CPlusPlusStyle
5150    | HashStyle -> ()
5151    | OCamlStyle -> pr " *)\n"
5152    | HaskellStyle -> pr "-}\n"
5153   );
5154   pr "\n"
5155
5156 (* Start of main code generation functions below this line. *)
5157
5158 (* Generate the pod documentation for the C API. *)
5159 let rec generate_actions_pod () =
5160   List.iter (
5161     fun (shortname, style, _, flags, _, _, longdesc) ->
5162       if not (List.mem NotInDocs flags) then (
5163         let name = "guestfs_" ^ shortname in
5164         pr "=head2 %s\n\n" name;
5165         pr " ";
5166         generate_prototype ~extern:false ~handle:"handle" name style;
5167         pr "\n\n";
5168         pr "%s\n\n" longdesc;
5169         (match fst style with
5170          | RErr ->
5171              pr "This function returns 0 on success or -1 on error.\n\n"
5172          | RInt _ ->
5173              pr "On error this function returns -1.\n\n"
5174          | RInt64 _ ->
5175              pr "On error this function returns -1.\n\n"
5176          | RBool _ ->
5177              pr "This function returns a C truth value on success or -1 on error.\n\n"
5178          | RConstString _ ->
5179              pr "This function returns a string, or NULL on error.
5180 The string is owned by the guest handle and must I<not> be freed.\n\n"
5181          | RConstOptString _ ->
5182              pr "This function returns a string which may be NULL.
5183 There is way to return an error from this function.
5184 The string is owned by the guest handle and must I<not> be freed.\n\n"
5185          | RString _ ->
5186              pr "This function returns a string, or NULL on error.
5187 I<The caller must free the returned string after use>.\n\n"
5188          | RStringList _ ->
5189              pr "This function returns a NULL-terminated array of strings
5190 (like L<environ(3)>), or NULL if there was an error.
5191 I<The caller must free the strings and the array after use>.\n\n"
5192          | RStruct (_, typ) ->
5193              pr "This function returns a C<struct guestfs_%s *>,
5194 or NULL if there was an error.
5195 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5196          | RStructList (_, typ) ->
5197              pr "This function returns a C<struct guestfs_%s_list *>
5198 (see E<lt>guestfs-structs.hE<gt>),
5199 or NULL if there was an error.
5200 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5201          | RHashtable _ ->
5202              pr "This function returns a NULL-terminated array of
5203 strings, or NULL if there was an error.
5204 The array of strings will always have length C<2n+1>, where
5205 C<n> keys and values alternate, followed by the trailing NULL entry.
5206 I<The caller must free the strings and the array after use>.\n\n"
5207          | RBufferOut _ ->
5208              pr "This function returns a buffer, or NULL on error.
5209 The size of the returned buffer is written to C<*size_r>.
5210 I<The caller must free the returned buffer after use>.\n\n"
5211         );
5212         if List.mem ProtocolLimitWarning flags then
5213           pr "%s\n\n" protocol_limit_warning;
5214         if List.mem DangerWillRobinson flags then
5215           pr "%s\n\n" danger_will_robinson;
5216         match deprecation_notice flags with
5217         | None -> ()
5218         | Some txt -> pr "%s\n\n" txt
5219       )
5220   ) all_functions_sorted
5221
5222 and generate_structs_pod () =
5223   (* Structs documentation. *)
5224   List.iter (
5225     fun (typ, cols) ->
5226       pr "=head2 guestfs_%s\n" typ;
5227       pr "\n";
5228       pr " struct guestfs_%s {\n" typ;
5229       List.iter (
5230         function
5231         | name, FChar -> pr "   char %s;\n" name
5232         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5233         | name, FInt32 -> pr "   int32_t %s;\n" name
5234         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5235         | name, FInt64 -> pr "   int64_t %s;\n" name
5236         | name, FString -> pr "   char *%s;\n" name
5237         | name, FBuffer ->
5238             pr "   /* The next two fields describe a byte array. */\n";
5239             pr "   uint32_t %s_len;\n" name;
5240             pr "   char *%s;\n" name
5241         | name, FUUID ->
5242             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5243             pr "   char %s[32];\n" name
5244         | name, FOptPercent ->
5245             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5246             pr "   float %s;\n" name
5247       ) cols;
5248       pr " };\n";
5249       pr " \n";
5250       pr " struct guestfs_%s_list {\n" typ;
5251       pr "   uint32_t len; /* Number of elements in list. */\n";
5252       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5253       pr " };\n";
5254       pr " \n";
5255       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5256       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5257         typ typ;
5258       pr "\n"
5259   ) structs
5260
5261 and generate_availability_pod () =
5262   (* Availability documentation. *)
5263   pr "=over 4\n";
5264   pr "\n";
5265   List.iter (
5266     fun (group, functions) ->
5267       pr "=item B<%s>\n" group;
5268       pr "\n";
5269       pr "The following functions:\n";
5270       List.iter (pr "L</guestfs_%s>\n") functions;
5271       pr "\n"
5272   ) optgroups;
5273   pr "=back\n";
5274   pr "\n"
5275
5276 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5277  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5278  *
5279  * We have to use an underscore instead of a dash because otherwise
5280  * rpcgen generates incorrect code.
5281  *
5282  * This header is NOT exported to clients, but see also generate_structs_h.
5283  *)
5284 and generate_xdr () =
5285   generate_header CStyle LGPLv2plus;
5286
5287   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5288   pr "typedef string str<>;\n";
5289   pr "\n";
5290
5291   (* Internal structures. *)
5292   List.iter (
5293     function
5294     | typ, cols ->
5295         pr "struct guestfs_int_%s {\n" typ;
5296         List.iter (function
5297                    | name, FChar -> pr "  char %s;\n" name
5298                    | name, FString -> pr "  string %s<>;\n" name
5299                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5300                    | name, FUUID -> pr "  opaque %s[32];\n" name
5301                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5302                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5303                    | name, FOptPercent -> pr "  float %s;\n" name
5304                   ) cols;
5305         pr "};\n";
5306         pr "\n";
5307         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5308         pr "\n";
5309   ) structs;
5310
5311   List.iter (
5312     fun (shortname, style, _, _, _, _, _) ->
5313       let name = "guestfs_" ^ shortname in
5314
5315       (match snd style with
5316        | [] -> ()
5317        | args ->
5318            pr "struct %s_args {\n" name;
5319            List.iter (
5320              function
5321              | Pathname n | Device n | Dev_or_Path n | String n ->
5322                  pr "  string %s<>;\n" n
5323              | OptString n -> pr "  str *%s;\n" n
5324              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5325              | Bool n -> pr "  bool %s;\n" n
5326              | Int n -> pr "  int %s;\n" n
5327              | Int64 n -> pr "  hyper %s;\n" n
5328              | FileIn _ | FileOut _ -> ()
5329            ) args;
5330            pr "};\n\n"
5331       );
5332       (match fst style with
5333        | RErr -> ()
5334        | RInt n ->
5335            pr "struct %s_ret {\n" name;
5336            pr "  int %s;\n" n;
5337            pr "};\n\n"
5338        | RInt64 n ->
5339            pr "struct %s_ret {\n" name;
5340            pr "  hyper %s;\n" n;
5341            pr "};\n\n"
5342        | RBool n ->
5343            pr "struct %s_ret {\n" name;
5344            pr "  bool %s;\n" n;
5345            pr "};\n\n"
5346        | RConstString _ | RConstOptString _ ->
5347            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5348        | RString n ->
5349            pr "struct %s_ret {\n" name;
5350            pr "  string %s<>;\n" n;
5351            pr "};\n\n"
5352        | RStringList n ->
5353            pr "struct %s_ret {\n" name;
5354            pr "  str %s<>;\n" n;
5355            pr "};\n\n"
5356        | RStruct (n, typ) ->
5357            pr "struct %s_ret {\n" name;
5358            pr "  guestfs_int_%s %s;\n" typ n;
5359            pr "};\n\n"
5360        | RStructList (n, typ) ->
5361            pr "struct %s_ret {\n" name;
5362            pr "  guestfs_int_%s_list %s;\n" typ n;
5363            pr "};\n\n"
5364        | RHashtable n ->
5365            pr "struct %s_ret {\n" name;
5366            pr "  str %s<>;\n" n;
5367            pr "};\n\n"
5368        | RBufferOut n ->
5369            pr "struct %s_ret {\n" name;
5370            pr "  opaque %s<>;\n" n;
5371            pr "};\n\n"
5372       );
5373   ) daemon_functions;
5374
5375   (* Table of procedure numbers. *)
5376   pr "enum guestfs_procedure {\n";
5377   List.iter (
5378     fun (shortname, _, proc_nr, _, _, _, _) ->
5379       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5380   ) daemon_functions;
5381   pr "  GUESTFS_PROC_NR_PROCS\n";
5382   pr "};\n";
5383   pr "\n";
5384
5385   (* Having to choose a maximum message size is annoying for several
5386    * reasons (it limits what we can do in the API), but it (a) makes
5387    * the protocol a lot simpler, and (b) provides a bound on the size
5388    * of the daemon which operates in limited memory space.
5389    *)
5390   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5391   pr "\n";
5392
5393   (* Message header, etc. *)
5394   pr "\
5395 /* The communication protocol is now documented in the guestfs(3)
5396  * manpage.
5397  */
5398
5399 const GUESTFS_PROGRAM = 0x2000F5F5;
5400 const GUESTFS_PROTOCOL_VERSION = 1;
5401
5402 /* These constants must be larger than any possible message length. */
5403 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5404 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5405
5406 enum guestfs_message_direction {
5407   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5408   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5409 };
5410
5411 enum guestfs_message_status {
5412   GUESTFS_STATUS_OK = 0,
5413   GUESTFS_STATUS_ERROR = 1
5414 };
5415
5416 const GUESTFS_ERROR_LEN = 256;
5417
5418 struct guestfs_message_error {
5419   string error_message<GUESTFS_ERROR_LEN>;
5420 };
5421
5422 struct guestfs_message_header {
5423   unsigned prog;                     /* GUESTFS_PROGRAM */
5424   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5425   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5426   guestfs_message_direction direction;
5427   unsigned serial;                   /* message serial number */
5428   guestfs_message_status status;
5429 };
5430
5431 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5432
5433 struct guestfs_chunk {
5434   int cancel;                        /* if non-zero, transfer is cancelled */
5435   /* data size is 0 bytes if the transfer has finished successfully */
5436   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5437 };
5438 "
5439
5440 (* Generate the guestfs-structs.h file. *)
5441 and generate_structs_h () =
5442   generate_header CStyle LGPLv2plus;
5443
5444   (* This is a public exported header file containing various
5445    * structures.  The structures are carefully written to have
5446    * exactly the same in-memory format as the XDR structures that
5447    * we use on the wire to the daemon.  The reason for creating
5448    * copies of these structures here is just so we don't have to
5449    * export the whole of guestfs_protocol.h (which includes much
5450    * unrelated and XDR-dependent stuff that we don't want to be
5451    * public, or required by clients).
5452    *
5453    * To reiterate, we will pass these structures to and from the
5454    * client with a simple assignment or memcpy, so the format
5455    * must be identical to what rpcgen / the RFC defines.
5456    *)
5457
5458   (* Public structures. *)
5459   List.iter (
5460     fun (typ, cols) ->
5461       pr "struct guestfs_%s {\n" typ;
5462       List.iter (
5463         function
5464         | name, FChar -> pr "  char %s;\n" name
5465         | name, FString -> pr "  char *%s;\n" name
5466         | name, FBuffer ->
5467             pr "  uint32_t %s_len;\n" name;
5468             pr "  char *%s;\n" name
5469         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5470         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5471         | name, FInt32 -> pr "  int32_t %s;\n" name
5472         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5473         | name, FInt64 -> pr "  int64_t %s;\n" name
5474         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5475       ) cols;
5476       pr "};\n";
5477       pr "\n";
5478       pr "struct guestfs_%s_list {\n" typ;
5479       pr "  uint32_t len;\n";
5480       pr "  struct guestfs_%s *val;\n" typ;
5481       pr "};\n";
5482       pr "\n";
5483       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5484       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5485       pr "\n"
5486   ) structs
5487
5488 (* Generate the guestfs-actions.h file. *)
5489 and generate_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   ) all_functions
5497
5498 (* Generate the guestfs-internal-actions.h file. *)
5499 and generate_internal_actions_h () =
5500   generate_header CStyle LGPLv2plus;
5501   List.iter (
5502     fun (shortname, style, _, _, _, _, _) ->
5503       let name = "guestfs__" ^ shortname in
5504       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5505         name style
5506   ) non_daemon_functions
5507
5508 (* Generate the client-side dispatch stubs. *)
5509 and generate_client_actions () =
5510   generate_header CStyle LGPLv2plus;
5511
5512   pr "\
5513 #include <stdio.h>
5514 #include <stdlib.h>
5515 #include <stdint.h>
5516 #include <string.h>
5517 #include <inttypes.h>
5518
5519 #include \"guestfs.h\"
5520 #include \"guestfs-internal.h\"
5521 #include \"guestfs-internal-actions.h\"
5522 #include \"guestfs_protocol.h\"
5523
5524 #define error guestfs_error
5525 //#define perrorf guestfs_perrorf
5526 #define safe_malloc guestfs_safe_malloc
5527 #define safe_realloc guestfs_safe_realloc
5528 //#define safe_strdup guestfs_safe_strdup
5529 #define safe_memdup guestfs_safe_memdup
5530
5531 /* Check the return message from a call for validity. */
5532 static int
5533 check_reply_header (guestfs_h *g,
5534                     const struct guestfs_message_header *hdr,
5535                     unsigned int proc_nr, unsigned int serial)
5536 {
5537   if (hdr->prog != GUESTFS_PROGRAM) {
5538     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5539     return -1;
5540   }
5541   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5542     error (g, \"wrong protocol version (%%d/%%d)\",
5543            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5544     return -1;
5545   }
5546   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5547     error (g, \"unexpected message direction (%%d/%%d)\",
5548            hdr->direction, GUESTFS_DIRECTION_REPLY);
5549     return -1;
5550   }
5551   if (hdr->proc != proc_nr) {
5552     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5553     return -1;
5554   }
5555   if (hdr->serial != serial) {
5556     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5557     return -1;
5558   }
5559
5560   return 0;
5561 }
5562
5563 /* Check we are in the right state to run a high-level action. */
5564 static int
5565 check_state (guestfs_h *g, const char *caller)
5566 {
5567   if (!guestfs__is_ready (g)) {
5568     if (guestfs__is_config (g) || guestfs__is_launching (g))
5569       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5570         caller);
5571     else
5572       error (g, \"%%s called from the wrong state, %%d != READY\",
5573         caller, guestfs__get_state (g));
5574     return -1;
5575   }
5576   return 0;
5577 }
5578
5579 ";
5580
5581   (* Generate code to generate guestfish call traces. *)
5582   let trace_call shortname style =
5583     pr "  if (guestfs__get_trace (g)) {\n";
5584
5585     let needs_i =
5586       List.exists (function
5587                    | StringList _ | DeviceList _ -> true
5588                    | _ -> false) (snd style) in
5589     if needs_i then (
5590       pr "    int i;\n";
5591       pr "\n"
5592     );
5593
5594     pr "    printf (\"%s\");\n" shortname;
5595     List.iter (
5596       function
5597       | String n                        (* strings *)
5598       | Device n
5599       | Pathname n
5600       | Dev_or_Path n
5601       | FileIn n
5602       | FileOut n ->
5603           (* guestfish doesn't support string escaping, so neither do we *)
5604           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5605       | OptString n ->                  (* string option *)
5606           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5607           pr "    else printf (\" null\");\n"
5608       | StringList n
5609       | DeviceList n ->                 (* string list *)
5610           pr "    putchar (' ');\n";
5611           pr "    putchar ('\"');\n";
5612           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5613           pr "      if (i > 0) putchar (' ');\n";
5614           pr "      fputs (%s[i], stdout);\n" n;
5615           pr "    }\n";
5616           pr "    putchar ('\"');\n";
5617       | Bool n ->                       (* boolean *)
5618           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5619       | Int n ->                        (* int *)
5620           pr "    printf (\" %%d\", %s);\n" n
5621       | Int64 n ->
5622           pr "    printf (\" %%\" PRIi64, %s);\n" n
5623     ) (snd style);
5624     pr "    putchar ('\\n');\n";
5625     pr "  }\n";
5626     pr "\n";
5627   in
5628
5629   (* For non-daemon functions, generate a wrapper around each function. *)
5630   List.iter (
5631     fun (shortname, style, _, _, _, _, _) ->
5632       let name = "guestfs_" ^ shortname in
5633
5634       generate_prototype ~extern:false ~semicolon:false ~newline:true
5635         ~handle:"g" name style;
5636       pr "{\n";
5637       trace_call shortname style;
5638       pr "  return guestfs__%s " shortname;
5639       generate_c_call_args ~handle:"g" style;
5640       pr ";\n";
5641       pr "}\n";
5642       pr "\n"
5643   ) non_daemon_functions;
5644
5645   (* Client-side stubs for each function. *)
5646   List.iter (
5647     fun (shortname, style, _, _, _, _, _) ->
5648       let name = "guestfs_" ^ shortname in
5649
5650       (* Generate the action stub. *)
5651       generate_prototype ~extern:false ~semicolon:false ~newline:true
5652         ~handle:"g" name style;
5653
5654       let error_code =
5655         match fst style with
5656         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5657         | RConstString _ | RConstOptString _ ->
5658             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5659         | RString _ | RStringList _
5660         | RStruct _ | RStructList _
5661         | RHashtable _ | RBufferOut _ ->
5662             "NULL" in
5663
5664       pr "{\n";
5665
5666       (match snd style with
5667        | [] -> ()
5668        | _ -> pr "  struct %s_args args;\n" name
5669       );
5670
5671       pr "  guestfs_message_header hdr;\n";
5672       pr "  guestfs_message_error err;\n";
5673       let has_ret =
5674         match fst style with
5675         | RErr -> false
5676         | RConstString _ | RConstOptString _ ->
5677             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5678         | RInt _ | RInt64 _
5679         | RBool _ | RString _ | RStringList _
5680         | RStruct _ | RStructList _
5681         | RHashtable _ | RBufferOut _ ->
5682             pr "  struct %s_ret ret;\n" name;
5683             true in
5684
5685       pr "  int serial;\n";
5686       pr "  int r;\n";
5687       pr "\n";
5688       trace_call shortname style;
5689       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5690       pr "  guestfs___set_busy (g);\n";
5691       pr "\n";
5692
5693       (* Send the main header and arguments. *)
5694       (match snd style with
5695        | [] ->
5696            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5697              (String.uppercase shortname)
5698        | args ->
5699            List.iter (
5700              function
5701              | Pathname n | Device n | Dev_or_Path n | String n ->
5702                  pr "  args.%s = (char *) %s;\n" n n
5703              | OptString n ->
5704                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5705              | StringList n | DeviceList n ->
5706                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5707                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5708              | Bool n ->
5709                  pr "  args.%s = %s;\n" n n
5710              | Int n ->
5711                  pr "  args.%s = %s;\n" n n
5712              | Int64 n ->
5713                  pr "  args.%s = %s;\n" n n
5714              | FileIn _ | FileOut _ -> ()
5715            ) args;
5716            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5717              (String.uppercase shortname);
5718            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5719              name;
5720       );
5721       pr "  if (serial == -1) {\n";
5722       pr "    guestfs___end_busy (g);\n";
5723       pr "    return %s;\n" error_code;
5724       pr "  }\n";
5725       pr "\n";
5726
5727       (* Send any additional files (FileIn) requested. *)
5728       let need_read_reply_label = ref false in
5729       List.iter (
5730         function
5731         | FileIn n ->
5732             pr "  r = guestfs___send_file (g, %s);\n" n;
5733             pr "  if (r == -1) {\n";
5734             pr "    guestfs___end_busy (g);\n";
5735             pr "    return %s;\n" error_code;
5736             pr "  }\n";
5737             pr "  if (r == -2) /* daemon cancelled */\n";
5738             pr "    goto read_reply;\n";
5739             need_read_reply_label := true;
5740             pr "\n";
5741         | _ -> ()
5742       ) (snd style);
5743
5744       (* Wait for the reply from the remote end. *)
5745       if !need_read_reply_label then pr " read_reply:\n";
5746       pr "  memset (&hdr, 0, sizeof hdr);\n";
5747       pr "  memset (&err, 0, sizeof err);\n";
5748       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5749       pr "\n";
5750       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5751       if not has_ret then
5752         pr "NULL, NULL"
5753       else
5754         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5755       pr ");\n";
5756
5757       pr "  if (r == -1) {\n";
5758       pr "    guestfs___end_busy (g);\n";
5759       pr "    return %s;\n" error_code;
5760       pr "  }\n";
5761       pr "\n";
5762
5763       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5764         (String.uppercase shortname);
5765       pr "    guestfs___end_busy (g);\n";
5766       pr "    return %s;\n" error_code;
5767       pr "  }\n";
5768       pr "\n";
5769
5770       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5771       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5772       pr "    free (err.error_message);\n";
5773       pr "    guestfs___end_busy (g);\n";
5774       pr "    return %s;\n" error_code;
5775       pr "  }\n";
5776       pr "\n";
5777
5778       (* Expecting to receive further files (FileOut)? *)
5779       List.iter (
5780         function
5781         | FileOut n ->
5782             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5783             pr "    guestfs___end_busy (g);\n";
5784             pr "    return %s;\n" error_code;
5785             pr "  }\n";
5786             pr "\n";
5787         | _ -> ()
5788       ) (snd style);
5789
5790       pr "  guestfs___end_busy (g);\n";
5791
5792       (match fst style with
5793        | RErr -> pr "  return 0;\n"
5794        | RInt n | RInt64 n | RBool n ->
5795            pr "  return ret.%s;\n" n
5796        | RConstString _ | RConstOptString _ ->
5797            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5798        | RString n ->
5799            pr "  return ret.%s; /* caller will free */\n" n
5800        | RStringList n | RHashtable n ->
5801            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5802            pr "  ret.%s.%s_val =\n" n n;
5803            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5804            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5805              n n;
5806            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5807            pr "  return ret.%s.%s_val;\n" n n
5808        | RStruct (n, _) ->
5809            pr "  /* caller will free this */\n";
5810            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5811        | RStructList (n, _) ->
5812            pr "  /* caller will free this */\n";
5813            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5814        | RBufferOut n ->
5815            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5816            pr "   * _val might be NULL here.  To make the API saner for\n";
5817            pr "   * callers, we turn this case into a unique pointer (using\n";
5818            pr "   * malloc(1)).\n";
5819            pr "   */\n";
5820            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5821            pr "    *size_r = ret.%s.%s_len;\n" n n;
5822            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5823            pr "  } else {\n";
5824            pr "    free (ret.%s.%s_val);\n" n n;
5825            pr "    char *p = safe_malloc (g, 1);\n";
5826            pr "    *size_r = ret.%s.%s_len;\n" n n;
5827            pr "    return p;\n";
5828            pr "  }\n";
5829       );
5830
5831       pr "}\n\n"
5832   ) daemon_functions;
5833
5834   (* Functions to free structures. *)
5835   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5836   pr " * structure format is identical to the XDR format.  See note in\n";
5837   pr " * generator.ml.\n";
5838   pr " */\n";
5839   pr "\n";
5840
5841   List.iter (
5842     fun (typ, _) ->
5843       pr "void\n";
5844       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5845       pr "{\n";
5846       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5847       pr "  free (x);\n";
5848       pr "}\n";
5849       pr "\n";
5850
5851       pr "void\n";
5852       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5853       pr "{\n";
5854       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5855       pr "  free (x);\n";
5856       pr "}\n";
5857       pr "\n";
5858
5859   ) structs;
5860
5861 (* Generate daemon/actions.h. *)
5862 and generate_daemon_actions_h () =
5863   generate_header CStyle GPLv2plus;
5864
5865   pr "#include \"../src/guestfs_protocol.h\"\n";
5866   pr "\n";
5867
5868   List.iter (
5869     fun (name, style, _, _, _, _, _) ->
5870       generate_prototype
5871         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5872         name style;
5873   ) daemon_functions
5874
5875 (* Generate the linker script which controls the visibility of
5876  * symbols in the public ABI and ensures no other symbols get
5877  * exported accidentally.
5878  *)
5879 and generate_linker_script () =
5880   generate_header HashStyle GPLv2plus;
5881
5882   let globals = [
5883     "guestfs_create";
5884     "guestfs_close";
5885     "guestfs_get_error_handler";
5886     "guestfs_get_out_of_memory_handler";
5887     "guestfs_last_error";
5888     "guestfs_set_error_handler";
5889     "guestfs_set_launch_done_callback";
5890     "guestfs_set_log_message_callback";
5891     "guestfs_set_out_of_memory_handler";
5892     "guestfs_set_subprocess_quit_callback";
5893
5894     (* Unofficial parts of the API: the bindings code use these
5895      * functions, so it is useful to export them.
5896      *)
5897     "guestfs_safe_calloc";
5898     "guestfs_safe_malloc";
5899   ] in
5900   let functions =
5901     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5902       all_functions in
5903   let structs =
5904     List.concat (
5905       List.map (fun (typ, _) ->
5906                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5907         structs
5908     ) in
5909   let globals = List.sort compare (globals @ functions @ structs) in
5910
5911   pr "{\n";
5912   pr "    global:\n";
5913   List.iter (pr "        %s;\n") globals;
5914   pr "\n";
5915
5916   pr "    local:\n";
5917   pr "        *;\n";
5918   pr "};\n"
5919
5920 (* Generate the server-side stubs. *)
5921 and generate_daemon_actions () =
5922   generate_header CStyle GPLv2plus;
5923
5924   pr "#include <config.h>\n";
5925   pr "\n";
5926   pr "#include <stdio.h>\n";
5927   pr "#include <stdlib.h>\n";
5928   pr "#include <string.h>\n";
5929   pr "#include <inttypes.h>\n";
5930   pr "#include <rpc/types.h>\n";
5931   pr "#include <rpc/xdr.h>\n";
5932   pr "\n";
5933   pr "#include \"daemon.h\"\n";
5934   pr "#include \"c-ctype.h\"\n";
5935   pr "#include \"../src/guestfs_protocol.h\"\n";
5936   pr "#include \"actions.h\"\n";
5937   pr "\n";
5938
5939   List.iter (
5940     fun (name, style, _, _, _, _, _) ->
5941       (* Generate server-side stubs. *)
5942       pr "static void %s_stub (XDR *xdr_in)\n" name;
5943       pr "{\n";
5944       let error_code =
5945         match fst style with
5946         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5947         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5948         | RBool _ -> pr "  int r;\n"; "-1"
5949         | RConstString _ | RConstOptString _ ->
5950             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5951         | RString _ -> pr "  char *r;\n"; "NULL"
5952         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5953         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5954         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5955         | RBufferOut _ ->
5956             pr "  size_t size = 1;\n";
5957             pr "  char *r;\n";
5958             "NULL" in
5959
5960       (match snd style with
5961        | [] -> ()
5962        | args ->
5963            pr "  struct guestfs_%s_args args;\n" name;
5964            List.iter (
5965              function
5966              | Device n | Dev_or_Path n
5967              | Pathname n
5968              | String n -> ()
5969              | OptString n -> pr "  char *%s;\n" n
5970              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5971              | Bool n -> pr "  int %s;\n" n
5972              | Int n -> pr "  int %s;\n" n
5973              | Int64 n -> pr "  int64_t %s;\n" n
5974              | FileIn _ | FileOut _ -> ()
5975            ) args
5976       );
5977       pr "\n";
5978
5979       (match snd style with
5980        | [] -> ()
5981        | args ->
5982            pr "  memset (&args, 0, sizeof args);\n";
5983            pr "\n";
5984            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5985            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5986            pr "    return;\n";
5987            pr "  }\n";
5988            let pr_args n =
5989              pr "  char *%s = args.%s;\n" n n
5990            in
5991            let pr_list_handling_code n =
5992              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5993              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5994              pr "  if (%s == NULL) {\n" n;
5995              pr "    reply_with_perror (\"realloc\");\n";
5996              pr "    goto done;\n";
5997              pr "  }\n";
5998              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5999              pr "  args.%s.%s_val = %s;\n" n n n;
6000            in
6001            List.iter (
6002              function
6003              | Pathname n ->
6004                  pr_args n;
6005                  pr "  ABS_PATH (%s, goto done);\n" n;
6006              | Device n ->
6007                  pr_args n;
6008                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6009              | Dev_or_Path n ->
6010                  pr_args n;
6011                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6012              | String n -> pr_args n
6013              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6014              | StringList n ->
6015                  pr_list_handling_code n;
6016              | DeviceList n ->
6017                  pr_list_handling_code n;
6018                  pr "  /* Ensure that each is a device,\n";
6019                  pr "   * and perform device name translation. */\n";
6020                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6021                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6022                  pr "  }\n";
6023              | Bool n -> pr "  %s = args.%s;\n" n n
6024              | Int n -> pr "  %s = args.%s;\n" n n
6025              | Int64 n -> pr "  %s = args.%s;\n" n n
6026              | FileIn _ | FileOut _ -> ()
6027            ) args;
6028            pr "\n"
6029       );
6030
6031
6032       (* this is used at least for do_equal *)
6033       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6034         (* Emit NEED_ROOT just once, even when there are two or
6035            more Pathname args *)
6036         pr "  NEED_ROOT (goto done);\n";
6037       );
6038
6039       (* Don't want to call the impl with any FileIn or FileOut
6040        * parameters, since these go "outside" the RPC protocol.
6041        *)
6042       let args' =
6043         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6044           (snd style) in
6045       pr "  r = do_%s " name;
6046       generate_c_call_args (fst style, args');
6047       pr ";\n";
6048
6049       (match fst style with
6050        | RErr | RInt _ | RInt64 _ | RBool _
6051        | RConstString _ | RConstOptString _
6052        | RString _ | RStringList _ | RHashtable _
6053        | RStruct (_, _) | RStructList (_, _) ->
6054            pr "  if (r == %s)\n" error_code;
6055            pr "    /* do_%s has already called reply_with_error */\n" name;
6056            pr "    goto done;\n";
6057            pr "\n"
6058        | RBufferOut _ ->
6059            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6060            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6061            pr "   */\n";
6062            pr "  if (size == 1 && r == %s)\n" error_code;
6063            pr "    /* do_%s has already called reply_with_error */\n" name;
6064            pr "    goto done;\n";
6065            pr "\n"
6066       );
6067
6068       (* If there are any FileOut parameters, then the impl must
6069        * send its own reply.
6070        *)
6071       let no_reply =
6072         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6073       if no_reply then
6074         pr "  /* do_%s has already sent a reply */\n" name
6075       else (
6076         match fst style with
6077         | RErr -> pr "  reply (NULL, NULL);\n"
6078         | RInt n | RInt64 n | RBool n ->
6079             pr "  struct guestfs_%s_ret ret;\n" name;
6080             pr "  ret.%s = r;\n" n;
6081             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6082               name
6083         | RConstString _ | RConstOptString _ ->
6084             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6085         | RString n ->
6086             pr "  struct guestfs_%s_ret ret;\n" name;
6087             pr "  ret.%s = r;\n" n;
6088             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6089               name;
6090             pr "  free (r);\n"
6091         | RStringList n | RHashtable n ->
6092             pr "  struct guestfs_%s_ret ret;\n" name;
6093             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6094             pr "  ret.%s.%s_val = r;\n" n n;
6095             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6096               name;
6097             pr "  free_strings (r);\n"
6098         | RStruct (n, _) ->
6099             pr "  struct guestfs_%s_ret ret;\n" name;
6100             pr "  ret.%s = *r;\n" n;
6101             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6102               name;
6103             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6104               name
6105         | RStructList (n, _) ->
6106             pr "  struct guestfs_%s_ret ret;\n" name;
6107             pr "  ret.%s = *r;\n" n;
6108             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6109               name;
6110             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6111               name
6112         | RBufferOut n ->
6113             pr "  struct guestfs_%s_ret ret;\n" name;
6114             pr "  ret.%s.%s_val = r;\n" n n;
6115             pr "  ret.%s.%s_len = size;\n" n n;
6116             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6117               name;
6118             pr "  free (r);\n"
6119       );
6120
6121       (* Free the args. *)
6122       (match snd style with
6123        | [] ->
6124            pr "done: ;\n";
6125        | _ ->
6126            pr "done:\n";
6127            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6128              name
6129       );
6130
6131       pr "}\n\n";
6132   ) daemon_functions;
6133
6134   (* Dispatch function. *)
6135   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6136   pr "{\n";
6137   pr "  switch (proc_nr) {\n";
6138
6139   List.iter (
6140     fun (name, style, _, _, _, _, _) ->
6141       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6142       pr "      %s_stub (xdr_in);\n" name;
6143       pr "      break;\n"
6144   ) daemon_functions;
6145
6146   pr "    default:\n";
6147   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";
6148   pr "  }\n";
6149   pr "}\n";
6150   pr "\n";
6151
6152   (* LVM columns and tokenization functions. *)
6153   (* XXX This generates crap code.  We should rethink how we
6154    * do this parsing.
6155    *)
6156   List.iter (
6157     function
6158     | typ, cols ->
6159         pr "static const char *lvm_%s_cols = \"%s\";\n"
6160           typ (String.concat "," (List.map fst cols));
6161         pr "\n";
6162
6163         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6164         pr "{\n";
6165         pr "  char *tok, *p, *next;\n";
6166         pr "  int i, j;\n";
6167         pr "\n";
6168         (*
6169           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6170           pr "\n";
6171         *)
6172         pr "  if (!str) {\n";
6173         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6174         pr "    return -1;\n";
6175         pr "  }\n";
6176         pr "  if (!*str || c_isspace (*str)) {\n";
6177         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6178         pr "    return -1;\n";
6179         pr "  }\n";
6180         pr "  tok = str;\n";
6181         List.iter (
6182           fun (name, coltype) ->
6183             pr "  if (!tok) {\n";
6184             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6185             pr "    return -1;\n";
6186             pr "  }\n";
6187             pr "  p = strchrnul (tok, ',');\n";
6188             pr "  if (*p) next = p+1; else next = NULL;\n";
6189             pr "  *p = '\\0';\n";
6190             (match coltype with
6191              | FString ->
6192                  pr "  r->%s = strdup (tok);\n" name;
6193                  pr "  if (r->%s == NULL) {\n" name;
6194                  pr "    perror (\"strdup\");\n";
6195                  pr "    return -1;\n";
6196                  pr "  }\n"
6197              | FUUID ->
6198                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6199                  pr "    if (tok[j] == '\\0') {\n";
6200                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6201                  pr "      return -1;\n";
6202                  pr "    } else if (tok[j] != '-')\n";
6203                  pr "      r->%s[i++] = tok[j];\n" name;
6204                  pr "  }\n";
6205              | FBytes ->
6206                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6207                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6208                  pr "    return -1;\n";
6209                  pr "  }\n";
6210              | FInt64 ->
6211                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6212                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6213                  pr "    return -1;\n";
6214                  pr "  }\n";
6215              | FOptPercent ->
6216                  pr "  if (tok[0] == '\\0')\n";
6217                  pr "    r->%s = -1;\n" name;
6218                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6219                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6220                  pr "    return -1;\n";
6221                  pr "  }\n";
6222              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6223                  assert false (* can never be an LVM column *)
6224             );
6225             pr "  tok = next;\n";
6226         ) cols;
6227
6228         pr "  if (tok != NULL) {\n";
6229         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6230         pr "    return -1;\n";
6231         pr "  }\n";
6232         pr "  return 0;\n";
6233         pr "}\n";
6234         pr "\n";
6235
6236         pr "guestfs_int_lvm_%s_list *\n" typ;
6237         pr "parse_command_line_%ss (void)\n" typ;
6238         pr "{\n";
6239         pr "  char *out, *err;\n";
6240         pr "  char *p, *pend;\n";
6241         pr "  int r, i;\n";
6242         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6243         pr "  void *newp;\n";
6244         pr "\n";
6245         pr "  ret = malloc (sizeof *ret);\n";
6246         pr "  if (!ret) {\n";
6247         pr "    reply_with_perror (\"malloc\");\n";
6248         pr "    return NULL;\n";
6249         pr "  }\n";
6250         pr "\n";
6251         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6252         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6253         pr "\n";
6254         pr "  r = command (&out, &err,\n";
6255         pr "           \"lvm\", \"%ss\",\n" typ;
6256         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6257         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6258         pr "  if (r == -1) {\n";
6259         pr "    reply_with_error (\"%%s\", err);\n";
6260         pr "    free (out);\n";
6261         pr "    free (err);\n";
6262         pr "    free (ret);\n";
6263         pr "    return NULL;\n";
6264         pr "  }\n";
6265         pr "\n";
6266         pr "  free (err);\n";
6267         pr "\n";
6268         pr "  /* Tokenize each line of the output. */\n";
6269         pr "  p = out;\n";
6270         pr "  i = 0;\n";
6271         pr "  while (p) {\n";
6272         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6273         pr "    if (pend) {\n";
6274         pr "      *pend = '\\0';\n";
6275         pr "      pend++;\n";
6276         pr "    }\n";
6277         pr "\n";
6278         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6279         pr "      p++;\n";
6280         pr "\n";
6281         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6282         pr "      p = pend;\n";
6283         pr "      continue;\n";
6284         pr "    }\n";
6285         pr "\n";
6286         pr "    /* Allocate some space to store this next entry. */\n";
6287         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6288         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6289         pr "    if (newp == NULL) {\n";
6290         pr "      reply_with_perror (\"realloc\");\n";
6291         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6292         pr "      free (ret);\n";
6293         pr "      free (out);\n";
6294         pr "      return NULL;\n";
6295         pr "    }\n";
6296         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6297         pr "\n";
6298         pr "    /* Tokenize the next entry. */\n";
6299         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6300         pr "    if (r == -1) {\n";
6301         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6302         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6303         pr "      free (ret);\n";
6304         pr "      free (out);\n";
6305         pr "      return NULL;\n";
6306         pr "    }\n";
6307         pr "\n";
6308         pr "    ++i;\n";
6309         pr "    p = pend;\n";
6310         pr "  }\n";
6311         pr "\n";
6312         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6313         pr "\n";
6314         pr "  free (out);\n";
6315         pr "  return ret;\n";
6316         pr "}\n"
6317
6318   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6319
6320 (* Generate a list of function names, for debugging in the daemon.. *)
6321 and generate_daemon_names () =
6322   generate_header CStyle GPLv2plus;
6323
6324   pr "#include <config.h>\n";
6325   pr "\n";
6326   pr "#include \"daemon.h\"\n";
6327   pr "\n";
6328
6329   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6330   pr "const char *function_names[] = {\n";
6331   List.iter (
6332     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6333   ) daemon_functions;
6334   pr "};\n";
6335
6336 (* Generate the optional groups for the daemon to implement
6337  * guestfs_available.
6338  *)
6339 and generate_daemon_optgroups_c () =
6340   generate_header CStyle GPLv2plus;
6341
6342   pr "#include <config.h>\n";
6343   pr "\n";
6344   pr "#include \"daemon.h\"\n";
6345   pr "#include \"optgroups.h\"\n";
6346   pr "\n";
6347
6348   pr "struct optgroup optgroups[] = {\n";
6349   List.iter (
6350     fun (group, _) ->
6351       pr "  { \"%s\", optgroup_%s_available },\n" group group
6352   ) optgroups;
6353   pr "  { NULL, NULL }\n";
6354   pr "};\n"
6355
6356 and generate_daemon_optgroups_h () =
6357   generate_header CStyle GPLv2plus;
6358
6359   List.iter (
6360     fun (group, _) ->
6361       pr "extern int optgroup_%s_available (void);\n" group
6362   ) optgroups
6363
6364 (* Generate the tests. *)
6365 and generate_tests () =
6366   generate_header CStyle GPLv2plus;
6367
6368   pr "\
6369 #include <stdio.h>
6370 #include <stdlib.h>
6371 #include <string.h>
6372 #include <unistd.h>
6373 #include <sys/types.h>
6374 #include <fcntl.h>
6375
6376 #include \"guestfs.h\"
6377 #include \"guestfs-internal.h\"
6378
6379 static guestfs_h *g;
6380 static int suppress_error = 0;
6381
6382 static void print_error (guestfs_h *g, void *data, const char *msg)
6383 {
6384   if (!suppress_error)
6385     fprintf (stderr, \"%%s\\n\", msg);
6386 }
6387
6388 /* FIXME: nearly identical code appears in fish.c */
6389 static void print_strings (char *const *argv)
6390 {
6391   int argc;
6392
6393   for (argc = 0; argv[argc] != NULL; ++argc)
6394     printf (\"\\t%%s\\n\", argv[argc]);
6395 }
6396
6397 /*
6398 static void print_table (char const *const *argv)
6399 {
6400   int i;
6401
6402   for (i = 0; argv[i] != NULL; i += 2)
6403     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6404 }
6405 */
6406
6407 ";
6408
6409   (* Generate a list of commands which are not tested anywhere. *)
6410   pr "static void no_test_warnings (void)\n";
6411   pr "{\n";
6412
6413   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6414   List.iter (
6415     fun (_, _, _, _, tests, _, _) ->
6416       let tests = filter_map (
6417         function
6418         | (_, (Always|If _|Unless _), test) -> Some test
6419         | (_, Disabled, _) -> None
6420       ) tests in
6421       let seq = List.concat (List.map seq_of_test tests) in
6422       let cmds_tested = List.map List.hd seq in
6423       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6424   ) all_functions;
6425
6426   List.iter (
6427     fun (name, _, _, _, _, _, _) ->
6428       if not (Hashtbl.mem hash name) then
6429         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6430   ) all_functions;
6431
6432   pr "}\n";
6433   pr "\n";
6434
6435   (* Generate the actual tests.  Note that we generate the tests
6436    * in reverse order, deliberately, so that (in general) the
6437    * newest tests run first.  This makes it quicker and easier to
6438    * debug them.
6439    *)
6440   let test_names =
6441     List.map (
6442       fun (name, _, _, flags, tests, _, _) ->
6443         mapi (generate_one_test name flags) tests
6444     ) (List.rev all_functions) in
6445   let test_names = List.concat test_names in
6446   let nr_tests = List.length test_names in
6447
6448   pr "\
6449 int main (int argc, char *argv[])
6450 {
6451   char c = 0;
6452   unsigned long int n_failed = 0;
6453   const char *filename;
6454   int fd;
6455   int nr_tests, test_num = 0;
6456
6457   setbuf (stdout, NULL);
6458
6459   no_test_warnings ();
6460
6461   g = guestfs_create ();
6462   if (g == NULL) {
6463     printf (\"guestfs_create FAILED\\n\");
6464     exit (EXIT_FAILURE);
6465   }
6466
6467   guestfs_set_error_handler (g, print_error, NULL);
6468
6469   guestfs_set_path (g, \"../appliance\");
6470
6471   filename = \"test1.img\";
6472   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6473   if (fd == -1) {
6474     perror (filename);
6475     exit (EXIT_FAILURE);
6476   }
6477   if (lseek (fd, %d, SEEK_SET) == -1) {
6478     perror (\"lseek\");
6479     close (fd);
6480     unlink (filename);
6481     exit (EXIT_FAILURE);
6482   }
6483   if (write (fd, &c, 1) == -1) {
6484     perror (\"write\");
6485     close (fd);
6486     unlink (filename);
6487     exit (EXIT_FAILURE);
6488   }
6489   if (close (fd) == -1) {
6490     perror (filename);
6491     unlink (filename);
6492     exit (EXIT_FAILURE);
6493   }
6494   if (guestfs_add_drive (g, filename) == -1) {
6495     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6496     exit (EXIT_FAILURE);
6497   }
6498
6499   filename = \"test2.img\";
6500   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6501   if (fd == -1) {
6502     perror (filename);
6503     exit (EXIT_FAILURE);
6504   }
6505   if (lseek (fd, %d, SEEK_SET) == -1) {
6506     perror (\"lseek\");
6507     close (fd);
6508     unlink (filename);
6509     exit (EXIT_FAILURE);
6510   }
6511   if (write (fd, &c, 1) == -1) {
6512     perror (\"write\");
6513     close (fd);
6514     unlink (filename);
6515     exit (EXIT_FAILURE);
6516   }
6517   if (close (fd) == -1) {
6518     perror (filename);
6519     unlink (filename);
6520     exit (EXIT_FAILURE);
6521   }
6522   if (guestfs_add_drive (g, filename) == -1) {
6523     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6524     exit (EXIT_FAILURE);
6525   }
6526
6527   filename = \"test3.img\";
6528   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6529   if (fd == -1) {
6530     perror (filename);
6531     exit (EXIT_FAILURE);
6532   }
6533   if (lseek (fd, %d, SEEK_SET) == -1) {
6534     perror (\"lseek\");
6535     close (fd);
6536     unlink (filename);
6537     exit (EXIT_FAILURE);
6538   }
6539   if (write (fd, &c, 1) == -1) {
6540     perror (\"write\");
6541     close (fd);
6542     unlink (filename);
6543     exit (EXIT_FAILURE);
6544   }
6545   if (close (fd) == -1) {
6546     perror (filename);
6547     unlink (filename);
6548     exit (EXIT_FAILURE);
6549   }
6550   if (guestfs_add_drive (g, filename) == -1) {
6551     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6552     exit (EXIT_FAILURE);
6553   }
6554
6555   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6556     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6557     exit (EXIT_FAILURE);
6558   }
6559
6560   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6561   alarm (600);
6562
6563   if (guestfs_launch (g) == -1) {
6564     printf (\"guestfs_launch FAILED\\n\");
6565     exit (EXIT_FAILURE);
6566   }
6567
6568   /* Cancel previous alarm. */
6569   alarm (0);
6570
6571   nr_tests = %d;
6572
6573 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6574
6575   iteri (
6576     fun i test_name ->
6577       pr "  test_num++;\n";
6578       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6579       pr "  if (%s () == -1) {\n" test_name;
6580       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6581       pr "    n_failed++;\n";
6582       pr "  }\n";
6583   ) test_names;
6584   pr "\n";
6585
6586   pr "  guestfs_close (g);\n";
6587   pr "  unlink (\"test1.img\");\n";
6588   pr "  unlink (\"test2.img\");\n";
6589   pr "  unlink (\"test3.img\");\n";
6590   pr "\n";
6591
6592   pr "  if (n_failed > 0) {\n";
6593   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6594   pr "    exit (EXIT_FAILURE);\n";
6595   pr "  }\n";
6596   pr "\n";
6597
6598   pr "  exit (EXIT_SUCCESS);\n";
6599   pr "}\n"
6600
6601 and generate_one_test name flags i (init, prereq, test) =
6602   let test_name = sprintf "test_%s_%d" name i in
6603
6604   pr "\
6605 static int %s_skip (void)
6606 {
6607   const char *str;
6608
6609   str = getenv (\"TEST_ONLY\");
6610   if (str)
6611     return strstr (str, \"%s\") == NULL;
6612   str = getenv (\"SKIP_%s\");
6613   if (str && STREQ (str, \"1\")) return 1;
6614   str = getenv (\"SKIP_TEST_%s\");
6615   if (str && STREQ (str, \"1\")) return 1;
6616   return 0;
6617 }
6618
6619 " test_name name (String.uppercase test_name) (String.uppercase name);
6620
6621   (match prereq with
6622    | Disabled | Always -> ()
6623    | If code | Unless code ->
6624        pr "static int %s_prereq (void)\n" test_name;
6625        pr "{\n";
6626        pr "  %s\n" code;
6627        pr "}\n";
6628        pr "\n";
6629   );
6630
6631   pr "\
6632 static int %s (void)
6633 {
6634   if (%s_skip ()) {
6635     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6636     return 0;
6637   }
6638
6639 " test_name test_name test_name;
6640
6641   (* Optional functions should only be tested if the relevant
6642    * support is available in the daemon.
6643    *)
6644   List.iter (
6645     function
6646     | Optional group ->
6647         pr "  {\n";
6648         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6649         pr "    int r;\n";
6650         pr "    suppress_error = 1;\n";
6651         pr "    r = guestfs_available (g, (char **) groups);\n";
6652         pr "    suppress_error = 0;\n";
6653         pr "    if (r == -1) {\n";
6654         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6655         pr "      return 0;\n";
6656         pr "    }\n";
6657         pr "  }\n";
6658     | _ -> ()
6659   ) flags;
6660
6661   (match prereq with
6662    | Disabled ->
6663        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6664    | If _ ->
6665        pr "  if (! %s_prereq ()) {\n" test_name;
6666        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6667        pr "    return 0;\n";
6668        pr "  }\n";
6669        pr "\n";
6670        generate_one_test_body name i test_name init test;
6671    | Unless _ ->
6672        pr "  if (%s_prereq ()) {\n" test_name;
6673        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6674        pr "    return 0;\n";
6675        pr "  }\n";
6676        pr "\n";
6677        generate_one_test_body name i test_name init test;
6678    | Always ->
6679        generate_one_test_body name i test_name init test
6680   );
6681
6682   pr "  return 0;\n";
6683   pr "}\n";
6684   pr "\n";
6685   test_name
6686
6687 and generate_one_test_body name i test_name init test =
6688   (match init with
6689    | InitNone (* XXX at some point, InitNone and InitEmpty became
6690                * folded together as the same thing.  Really we should
6691                * make InitNone do nothing at all, but the tests may
6692                * need to be checked to make sure this is OK.
6693                *)
6694    | InitEmpty ->
6695        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6696        List.iter (generate_test_command_call test_name)
6697          [["blockdev_setrw"; "/dev/sda"];
6698           ["umount_all"];
6699           ["lvm_remove_all"]]
6700    | InitPartition ->
6701        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6702        List.iter (generate_test_command_call test_name)
6703          [["blockdev_setrw"; "/dev/sda"];
6704           ["umount_all"];
6705           ["lvm_remove_all"];
6706           ["part_disk"; "/dev/sda"; "mbr"]]
6707    | InitBasicFS ->
6708        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" 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           ["mkfs"; "ext2"; "/dev/sda1"];
6715           ["mount_options"; ""; "/dev/sda1"; "/"]]
6716    | InitBasicFSonLVM ->
6717        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6718          test_name;
6719        List.iter (generate_test_command_call test_name)
6720          [["blockdev_setrw"; "/dev/sda"];
6721           ["umount_all"];
6722           ["lvm_remove_all"];
6723           ["part_disk"; "/dev/sda"; "mbr"];
6724           ["pvcreate"; "/dev/sda1"];
6725           ["vgcreate"; "VG"; "/dev/sda1"];
6726           ["lvcreate"; "LV"; "VG"; "8"];
6727           ["mkfs"; "ext2"; "/dev/VG/LV"];
6728           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6729    | InitISOFS ->
6730        pr "  /* InitISOFS for %s */\n" test_name;
6731        List.iter (generate_test_command_call test_name)
6732          [["blockdev_setrw"; "/dev/sda"];
6733           ["umount_all"];
6734           ["lvm_remove_all"];
6735           ["mount_ro"; "/dev/sdd"; "/"]]
6736   );
6737
6738   let get_seq_last = function
6739     | [] ->
6740         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6741           test_name
6742     | seq ->
6743         let seq = List.rev seq in
6744         List.rev (List.tl seq), List.hd seq
6745   in
6746
6747   match test with
6748   | TestRun seq ->
6749       pr "  /* TestRun for %s (%d) */\n" name i;
6750       List.iter (generate_test_command_call test_name) seq
6751   | TestOutput (seq, expected) ->
6752       pr "  /* TestOutput for %s (%d) */\n" name i;
6753       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6754       let seq, last = get_seq_last seq in
6755       let test () =
6756         pr "    if (STRNEQ (r, expected)) {\n";
6757         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6758         pr "      return -1;\n";
6759         pr "    }\n"
6760       in
6761       List.iter (generate_test_command_call test_name) seq;
6762       generate_test_command_call ~test test_name last
6763   | TestOutputList (seq, expected) ->
6764       pr "  /* TestOutputList for %s (%d) */\n" name i;
6765       let seq, last = get_seq_last seq in
6766       let test () =
6767         iteri (
6768           fun i str ->
6769             pr "    if (!r[%d]) {\n" i;
6770             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6771             pr "      print_strings (r);\n";
6772             pr "      return -1;\n";
6773             pr "    }\n";
6774             pr "    {\n";
6775             pr "      const char *expected = \"%s\";\n" (c_quote str);
6776             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6777             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6778             pr "        return -1;\n";
6779             pr "      }\n";
6780             pr "    }\n"
6781         ) expected;
6782         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6783         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6784           test_name;
6785         pr "      print_strings (r);\n";
6786         pr "      return -1;\n";
6787         pr "    }\n"
6788       in
6789       List.iter (generate_test_command_call test_name) seq;
6790       generate_test_command_call ~test test_name last
6791   | TestOutputListOfDevices (seq, expected) ->
6792       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6793       let seq, last = get_seq_last seq in
6794       let test () =
6795         iteri (
6796           fun i str ->
6797             pr "    if (!r[%d]) {\n" i;
6798             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6799             pr "      print_strings (r);\n";
6800             pr "      return -1;\n";
6801             pr "    }\n";
6802             pr "    {\n";
6803             pr "      const char *expected = \"%s\";\n" (c_quote str);
6804             pr "      r[%d][5] = 's';\n" i;
6805             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6806             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6807             pr "        return -1;\n";
6808             pr "      }\n";
6809             pr "    }\n"
6810         ) expected;
6811         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6812         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6813           test_name;
6814         pr "      print_strings (r);\n";
6815         pr "      return -1;\n";
6816         pr "    }\n"
6817       in
6818       List.iter (generate_test_command_call test_name) seq;
6819       generate_test_command_call ~test test_name last
6820   | TestOutputInt (seq, expected) ->
6821       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6822       let seq, last = get_seq_last seq in
6823       let test () =
6824         pr "    if (r != %d) {\n" expected;
6825         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6826           test_name expected;
6827         pr "               (int) r);\n";
6828         pr "      return -1;\n";
6829         pr "    }\n"
6830       in
6831       List.iter (generate_test_command_call test_name) seq;
6832       generate_test_command_call ~test test_name last
6833   | TestOutputIntOp (seq, op, expected) ->
6834       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6835       let seq, last = get_seq_last seq in
6836       let test () =
6837         pr "    if (! (r %s %d)) {\n" op expected;
6838         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6839           test_name op expected;
6840         pr "               (int) r);\n";
6841         pr "      return -1;\n";
6842         pr "    }\n"
6843       in
6844       List.iter (generate_test_command_call test_name) seq;
6845       generate_test_command_call ~test test_name last
6846   | TestOutputTrue seq ->
6847       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6848       let seq, last = get_seq_last seq in
6849       let test () =
6850         pr "    if (!r) {\n";
6851         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6852           test_name;
6853         pr "      return -1;\n";
6854         pr "    }\n"
6855       in
6856       List.iter (generate_test_command_call test_name) seq;
6857       generate_test_command_call ~test test_name last
6858   | TestOutputFalse seq ->
6859       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6860       let seq, last = get_seq_last seq in
6861       let test () =
6862         pr "    if (r) {\n";
6863         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6864           test_name;
6865         pr "      return -1;\n";
6866         pr "    }\n"
6867       in
6868       List.iter (generate_test_command_call test_name) seq;
6869       generate_test_command_call ~test test_name last
6870   | TestOutputLength (seq, expected) ->
6871       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6872       let seq, last = get_seq_last seq in
6873       let test () =
6874         pr "    int j;\n";
6875         pr "    for (j = 0; j < %d; ++j)\n" expected;
6876         pr "      if (r[j] == NULL) {\n";
6877         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6878           test_name;
6879         pr "        print_strings (r);\n";
6880         pr "        return -1;\n";
6881         pr "      }\n";
6882         pr "    if (r[j] != NULL) {\n";
6883         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6884           test_name;
6885         pr "      print_strings (r);\n";
6886         pr "      return -1;\n";
6887         pr "    }\n"
6888       in
6889       List.iter (generate_test_command_call test_name) seq;
6890       generate_test_command_call ~test test_name last
6891   | TestOutputBuffer (seq, expected) ->
6892       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6893       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6894       let seq, last = get_seq_last seq in
6895       let len = String.length expected in
6896       let test () =
6897         pr "    if (size != %d) {\n" len;
6898         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6899         pr "      return -1;\n";
6900         pr "    }\n";
6901         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6902         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6903         pr "      return -1;\n";
6904         pr "    }\n"
6905       in
6906       List.iter (generate_test_command_call test_name) seq;
6907       generate_test_command_call ~test test_name last
6908   | TestOutputStruct (seq, checks) ->
6909       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6910       let seq, last = get_seq_last seq in
6911       let test () =
6912         List.iter (
6913           function
6914           | CompareWithInt (field, expected) ->
6915               pr "    if (r->%s != %d) {\n" field expected;
6916               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6917                 test_name field expected;
6918               pr "               (int) r->%s);\n" field;
6919               pr "      return -1;\n";
6920               pr "    }\n"
6921           | CompareWithIntOp (field, op, expected) ->
6922               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6923               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6924                 test_name field op expected;
6925               pr "               (int) r->%s);\n" field;
6926               pr "      return -1;\n";
6927               pr "    }\n"
6928           | CompareWithString (field, expected) ->
6929               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6930               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6931                 test_name field expected;
6932               pr "               r->%s);\n" field;
6933               pr "      return -1;\n";
6934               pr "    }\n"
6935           | CompareFieldsIntEq (field1, field2) ->
6936               pr "    if (r->%s != r->%s) {\n" field1 field2;
6937               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6938                 test_name field1 field2;
6939               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6940               pr "      return -1;\n";
6941               pr "    }\n"
6942           | CompareFieldsStrEq (field1, field2) ->
6943               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6944               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6945                 test_name field1 field2;
6946               pr "               r->%s, r->%s);\n" field1 field2;
6947               pr "      return -1;\n";
6948               pr "    }\n"
6949         ) checks
6950       in
6951       List.iter (generate_test_command_call test_name) seq;
6952       generate_test_command_call ~test test_name last
6953   | TestLastFail seq ->
6954       pr "  /* TestLastFail for %s (%d) */\n" name i;
6955       let seq, last = get_seq_last seq in
6956       List.iter (generate_test_command_call test_name) seq;
6957       generate_test_command_call test_name ~expect_error:true last
6958
6959 (* Generate the code to run a command, leaving the result in 'r'.
6960  * If you expect to get an error then you should set expect_error:true.
6961  *)
6962 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6963   match cmd with
6964   | [] -> assert false
6965   | name :: args ->
6966       (* Look up the command to find out what args/ret it has. *)
6967       let style =
6968         try
6969           let _, style, _, _, _, _, _ =
6970             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6971           style
6972         with Not_found ->
6973           failwithf "%s: in test, command %s was not found" test_name name in
6974
6975       if List.length (snd style) <> List.length args then
6976         failwithf "%s: in test, wrong number of args given to %s"
6977           test_name name;
6978
6979       pr "  {\n";
6980
6981       List.iter (
6982         function
6983         | OptString n, "NULL" -> ()
6984         | Pathname n, arg
6985         | Device n, arg
6986         | Dev_or_Path n, arg
6987         | String n, arg
6988         | OptString n, arg ->
6989             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6990         | Int _, _
6991         | Int64 _, _
6992         | Bool _, _
6993         | FileIn _, _ | FileOut _, _ -> ()
6994         | StringList n, "" | DeviceList n, "" ->
6995             pr "    const char *const %s[1] = { NULL };\n" n
6996         | StringList n, arg | DeviceList n, arg ->
6997             let strs = string_split " " arg in
6998             iteri (
6999               fun i str ->
7000                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7001             ) strs;
7002             pr "    const char *const %s[] = {\n" n;
7003             iteri (
7004               fun i _ -> pr "      %s_%d,\n" n i
7005             ) strs;
7006             pr "      NULL\n";
7007             pr "    };\n";
7008       ) (List.combine (snd style) args);
7009
7010       let error_code =
7011         match fst style with
7012         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7013         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7014         | RConstString _ | RConstOptString _ ->
7015             pr "    const char *r;\n"; "NULL"
7016         | RString _ -> pr "    char *r;\n"; "NULL"
7017         | RStringList _ | RHashtable _ ->
7018             pr "    char **r;\n";
7019             pr "    int i;\n";
7020             "NULL"
7021         | RStruct (_, typ) ->
7022             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7023         | RStructList (_, typ) ->
7024             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7025         | RBufferOut _ ->
7026             pr "    char *r;\n";
7027             pr "    size_t size;\n";
7028             "NULL" in
7029
7030       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7031       pr "    r = guestfs_%s (g" name;
7032
7033       (* Generate the parameters. *)
7034       List.iter (
7035         function
7036         | OptString _, "NULL" -> pr ", NULL"
7037         | Pathname n, _
7038         | Device n, _ | Dev_or_Path n, _
7039         | String n, _
7040         | OptString n, _ ->
7041             pr ", %s" n
7042         | FileIn _, arg | FileOut _, arg ->
7043             pr ", \"%s\"" (c_quote arg)
7044         | StringList n, _ | DeviceList n, _ ->
7045             pr ", (char **) %s" n
7046         | Int _, arg ->
7047             let i =
7048               try int_of_string arg
7049               with Failure "int_of_string" ->
7050                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7051             pr ", %d" i
7052         | Int64 _, arg ->
7053             let i =
7054               try Int64.of_string arg
7055               with Failure "int_of_string" ->
7056                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7057             pr ", %Ld" i
7058         | Bool _, arg ->
7059             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7060       ) (List.combine (snd style) args);
7061
7062       (match fst style with
7063        | RBufferOut _ -> pr ", &size"
7064        | _ -> ()
7065       );
7066
7067       pr ");\n";
7068
7069       if not expect_error then
7070         pr "    if (r == %s)\n" error_code
7071       else
7072         pr "    if (r != %s)\n" error_code;
7073       pr "      return -1;\n";
7074
7075       (* Insert the test code. *)
7076       (match test with
7077        | None -> ()
7078        | Some f -> f ()
7079       );
7080
7081       (match fst style with
7082        | RErr | RInt _ | RInt64 _ | RBool _
7083        | RConstString _ | RConstOptString _ -> ()
7084        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7085        | RStringList _ | RHashtable _ ->
7086            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7087            pr "      free (r[i]);\n";
7088            pr "    free (r);\n"
7089        | RStruct (_, typ) ->
7090            pr "    guestfs_free_%s (r);\n" typ
7091        | RStructList (_, typ) ->
7092            pr "    guestfs_free_%s_list (r);\n" typ
7093       );
7094
7095       pr "  }\n"
7096
7097 and c_quote str =
7098   let str = replace_str str "\r" "\\r" in
7099   let str = replace_str str "\n" "\\n" in
7100   let str = replace_str str "\t" "\\t" in
7101   let str = replace_str str "\000" "\\0" in
7102   str
7103
7104 (* Generate a lot of different functions for guestfish. *)
7105 and generate_fish_cmds () =
7106   generate_header CStyle GPLv2plus;
7107
7108   let all_functions =
7109     List.filter (
7110       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7111     ) all_functions in
7112   let all_functions_sorted =
7113     List.filter (
7114       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7115     ) all_functions_sorted in
7116
7117   pr "#include <config.h>\n";
7118   pr "\n";
7119   pr "#include <stdio.h>\n";
7120   pr "#include <stdlib.h>\n";
7121   pr "#include <string.h>\n";
7122   pr "#include <inttypes.h>\n";
7123   pr "\n";
7124   pr "#include <guestfs.h>\n";
7125   pr "#include \"c-ctype.h\"\n";
7126   pr "#include \"full-write.h\"\n";
7127   pr "#include \"xstrtol.h\"\n";
7128   pr "#include \"fish.h\"\n";
7129   pr "\n";
7130
7131   (* list_commands function, which implements guestfish -h *)
7132   pr "void list_commands (void)\n";
7133   pr "{\n";
7134   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7135   pr "  list_builtin_commands ();\n";
7136   List.iter (
7137     fun (name, _, _, flags, _, shortdesc, _) ->
7138       let name = replace_char name '_' '-' in
7139       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7140         name shortdesc
7141   ) all_functions_sorted;
7142   pr "  printf (\"    %%s\\n\",";
7143   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7144   pr "}\n";
7145   pr "\n";
7146
7147   (* display_command function, which implements guestfish -h cmd *)
7148   pr "void display_command (const char *cmd)\n";
7149   pr "{\n";
7150   List.iter (
7151     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7152       let name2 = replace_char name '_' '-' in
7153       let alias =
7154         try find_map (function FishAlias n -> Some n | _ -> None) flags
7155         with Not_found -> name in
7156       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7157       let synopsis =
7158         match snd style with
7159         | [] -> name2
7160         | args ->
7161             sprintf "%s %s"
7162               name2 (String.concat " " (List.map name_of_argt args)) in
7163
7164       let warnings =
7165         if List.mem ProtocolLimitWarning flags then
7166           ("\n\n" ^ protocol_limit_warning)
7167         else "" in
7168
7169       (* For DangerWillRobinson commands, we should probably have
7170        * guestfish prompt before allowing you to use them (especially
7171        * in interactive mode). XXX
7172        *)
7173       let warnings =
7174         warnings ^
7175           if List.mem DangerWillRobinson flags then
7176             ("\n\n" ^ danger_will_robinson)
7177           else "" in
7178
7179       let warnings =
7180         warnings ^
7181           match deprecation_notice flags with
7182           | None -> ""
7183           | Some txt -> "\n\n" ^ txt in
7184
7185       let describe_alias =
7186         if name <> alias then
7187           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7188         else "" in
7189
7190       pr "  if (";
7191       pr "STRCASEEQ (cmd, \"%s\")" name;
7192       if name <> name2 then
7193         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7194       if name <> alias then
7195         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7196       pr ")\n";
7197       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7198         name2 shortdesc
7199         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7200          "=head1 DESCRIPTION\n\n" ^
7201          longdesc ^ warnings ^ describe_alias);
7202       pr "  else\n"
7203   ) all_functions;
7204   pr "    display_builtin_command (cmd);\n";
7205   pr "}\n";
7206   pr "\n";
7207
7208   let emit_print_list_function typ =
7209     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7210       typ typ typ;
7211     pr "{\n";
7212     pr "  unsigned int i;\n";
7213     pr "\n";
7214     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7215     pr "    printf (\"[%%d] = {\\n\", i);\n";
7216     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7217     pr "    printf (\"}\\n\");\n";
7218     pr "  }\n";
7219     pr "}\n";
7220     pr "\n";
7221   in
7222
7223   (* print_* functions *)
7224   List.iter (
7225     fun (typ, cols) ->
7226       let needs_i =
7227         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7228
7229       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7230       pr "{\n";
7231       if needs_i then (
7232         pr "  unsigned int i;\n";
7233         pr "\n"
7234       );
7235       List.iter (
7236         function
7237         | name, FString ->
7238             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7239         | name, FUUID ->
7240             pr "  printf (\"%%s%s: \", indent);\n" name;
7241             pr "  for (i = 0; i < 32; ++i)\n";
7242             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7243             pr "  printf (\"\\n\");\n"
7244         | name, FBuffer ->
7245             pr "  printf (\"%%s%s: \", indent);\n" name;
7246             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7247             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7248             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7249             pr "    else\n";
7250             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7251             pr "  printf (\"\\n\");\n"
7252         | name, (FUInt64|FBytes) ->
7253             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7254               name typ name
7255         | name, FInt64 ->
7256             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7257               name typ name
7258         | name, FUInt32 ->
7259             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7260               name typ name
7261         | name, FInt32 ->
7262             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7263               name typ name
7264         | name, FChar ->
7265             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7266               name typ name
7267         | name, FOptPercent ->
7268             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7269               typ name name typ name;
7270             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7271       ) cols;
7272       pr "}\n";
7273       pr "\n";
7274   ) structs;
7275
7276   (* Emit a print_TYPE_list function definition only if that function is used. *)
7277   List.iter (
7278     function
7279     | typ, (RStructListOnly | RStructAndList) ->
7280         (* generate the function for typ *)
7281         emit_print_list_function typ
7282     | typ, _ -> () (* empty *)
7283   ) (rstructs_used_by all_functions);
7284
7285   (* Emit a print_TYPE function definition only if that function is used. *)
7286   List.iter (
7287     function
7288     | typ, (RStructOnly | RStructAndList) ->
7289         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7290         pr "{\n";
7291         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7292         pr "}\n";
7293         pr "\n";
7294     | typ, _ -> () (* empty *)
7295   ) (rstructs_used_by all_functions);
7296
7297   (* run_<action> actions *)
7298   List.iter (
7299     fun (name, style, _, flags, _, _, _) ->
7300       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7301       pr "{\n";
7302       (match fst style with
7303        | RErr
7304        | RInt _
7305        | RBool _ -> pr "  int r;\n"
7306        | RInt64 _ -> pr "  int64_t r;\n"
7307        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7308        | RString _ -> pr "  char *r;\n"
7309        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7310        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7311        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7312        | RBufferOut _ ->
7313            pr "  char *r;\n";
7314            pr "  size_t size;\n";
7315       );
7316       List.iter (
7317         function
7318         | Device n
7319         | String n
7320         | OptString n
7321         | FileIn n
7322         | FileOut n -> pr "  const char *%s;\n" n
7323         | Pathname n
7324         | Dev_or_Path n -> pr "  char *%s;\n" n
7325         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7326         | Bool n -> pr "  int %s;\n" n
7327         | Int n -> pr "  int %s;\n" n
7328         | Int64 n -> pr "  int64_t %s;\n" n
7329       ) (snd style);
7330
7331       (* Check and convert parameters. *)
7332       let argc_expected = List.length (snd style) in
7333       pr "  if (argc != %d) {\n" argc_expected;
7334       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7335         argc_expected;
7336       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7337       pr "    return -1;\n";
7338       pr "  }\n";
7339
7340       let parse_integer fn fntyp rtyp range name i =
7341         pr "  {\n";
7342         pr "    strtol_error xerr;\n";
7343         pr "    %s r;\n" fntyp;
7344         pr "\n";
7345         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7346         pr "    if (xerr != LONGINT_OK) {\n";
7347         pr "      fprintf (stderr,\n";
7348         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7349         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7350         pr "      return -1;\n";
7351         pr "    }\n";
7352         (match range with
7353          | None -> ()
7354          | Some (min, max, comment) ->
7355              pr "    /* %s */\n" comment;
7356              pr "    if (r < %s || r > %s) {\n" min max;
7357              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7358                name;
7359              pr "      return -1;\n";
7360              pr "    }\n";
7361              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7362         );
7363         pr "    %s = r;\n" name;
7364         pr "  }\n";
7365       in
7366
7367       iteri (
7368         fun i ->
7369           function
7370           | Device name
7371           | String name ->
7372               pr "  %s = argv[%d];\n" name i
7373           | Pathname name
7374           | Dev_or_Path name ->
7375               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7376               pr "  if (%s == NULL) return -1;\n" name
7377           | OptString name ->
7378               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7379                 name i i
7380           | FileIn name ->
7381               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7382                 name i i
7383           | FileOut name ->
7384               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7385                 name i i
7386           | StringList name | DeviceList name ->
7387               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7388               pr "  if (%s == NULL) return -1;\n" name;
7389           | Bool name ->
7390               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7391           | Int name ->
7392               let range =
7393                 let min = "(-(2LL<<30))"
7394                 and max = "((2LL<<30)-1)"
7395                 and comment =
7396                   "The Int type in the generator is a signed 31 bit int." in
7397                 Some (min, max, comment) in
7398               parse_integer "xstrtoll" "long long" "int" range name i
7399           | Int64 name ->
7400               parse_integer "xstrtoll" "long long" "int64_t" None name i
7401       ) (snd style);
7402
7403       (* Call C API function. *)
7404       let fn =
7405         try find_map (function FishAction n -> Some n | _ -> None) flags
7406         with Not_found -> sprintf "guestfs_%s" name in
7407       pr "  r = %s " fn;
7408       generate_c_call_args ~handle:"g" style;
7409       pr ";\n";
7410
7411       List.iter (
7412         function
7413         | Device name | String name
7414         | OptString name | FileIn name | FileOut name | Bool name
7415         | Int name | Int64 name -> ()
7416         | Pathname name | Dev_or_Path name ->
7417             pr "  free (%s);\n" name
7418         | StringList name | DeviceList name ->
7419             pr "  free_strings (%s);\n" name
7420       ) (snd style);
7421
7422       (* Check return value for errors and display command results. *)
7423       (match fst style with
7424        | RErr -> pr "  return r;\n"
7425        | RInt _ ->
7426            pr "  if (r == -1) return -1;\n";
7427            pr "  printf (\"%%d\\n\", r);\n";
7428            pr "  return 0;\n"
7429        | RInt64 _ ->
7430            pr "  if (r == -1) return -1;\n";
7431            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7432            pr "  return 0;\n"
7433        | RBool _ ->
7434            pr "  if (r == -1) return -1;\n";
7435            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7436            pr "  return 0;\n"
7437        | RConstString _ ->
7438            pr "  if (r == NULL) return -1;\n";
7439            pr "  printf (\"%%s\\n\", r);\n";
7440            pr "  return 0;\n"
7441        | RConstOptString _ ->
7442            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7443            pr "  return 0;\n"
7444        | RString _ ->
7445            pr "  if (r == NULL) return -1;\n";
7446            pr "  printf (\"%%s\\n\", r);\n";
7447            pr "  free (r);\n";
7448            pr "  return 0;\n"
7449        | RStringList _ ->
7450            pr "  if (r == NULL) return -1;\n";
7451            pr "  print_strings (r);\n";
7452            pr "  free_strings (r);\n";
7453            pr "  return 0;\n"
7454        | RStruct (_, typ) ->
7455            pr "  if (r == NULL) return -1;\n";
7456            pr "  print_%s (r);\n" typ;
7457            pr "  guestfs_free_%s (r);\n" typ;
7458            pr "  return 0;\n"
7459        | RStructList (_, typ) ->
7460            pr "  if (r == NULL) return -1;\n";
7461            pr "  print_%s_list (r);\n" typ;
7462            pr "  guestfs_free_%s_list (r);\n" typ;
7463            pr "  return 0;\n"
7464        | RHashtable _ ->
7465            pr "  if (r == NULL) return -1;\n";
7466            pr "  print_table (r);\n";
7467            pr "  free_strings (r);\n";
7468            pr "  return 0;\n"
7469        | RBufferOut _ ->
7470            pr "  if (r == NULL) return -1;\n";
7471            pr "  if (full_write (1, r, size) != size) {\n";
7472            pr "    perror (\"write\");\n";
7473            pr "    free (r);\n";
7474            pr "    return -1;\n";
7475            pr "  }\n";
7476            pr "  free (r);\n";
7477            pr "  return 0;\n"
7478       );
7479       pr "}\n";
7480       pr "\n"
7481   ) all_functions;
7482
7483   (* run_action function *)
7484   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7485   pr "{\n";
7486   List.iter (
7487     fun (name, _, _, flags, _, _, _) ->
7488       let name2 = replace_char name '_' '-' in
7489       let alias =
7490         try find_map (function FishAlias n -> Some n | _ -> None) flags
7491         with Not_found -> name in
7492       pr "  if (";
7493       pr "STRCASEEQ (cmd, \"%s\")" name;
7494       if name <> name2 then
7495         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7496       if name <> alias then
7497         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7498       pr ")\n";
7499       pr "    return run_%s (cmd, argc, argv);\n" name;
7500       pr "  else\n";
7501   ) all_functions;
7502   pr "    {\n";
7503   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7504   pr "      if (command_num == 1)\n";
7505   pr "        extended_help_message ();\n";
7506   pr "      return -1;\n";
7507   pr "    }\n";
7508   pr "  return 0;\n";
7509   pr "}\n";
7510   pr "\n"
7511
7512 (* Readline completion for guestfish. *)
7513 and generate_fish_completion () =
7514   generate_header CStyle GPLv2plus;
7515
7516   let all_functions =
7517     List.filter (
7518       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7519     ) all_functions in
7520
7521   pr "\
7522 #include <config.h>
7523
7524 #include <stdio.h>
7525 #include <stdlib.h>
7526 #include <string.h>
7527
7528 #ifdef HAVE_LIBREADLINE
7529 #include <readline/readline.h>
7530 #endif
7531
7532 #include \"fish.h\"
7533
7534 #ifdef HAVE_LIBREADLINE
7535
7536 static const char *const commands[] = {
7537   BUILTIN_COMMANDS_FOR_COMPLETION,
7538 ";
7539
7540   (* Get the commands, including the aliases.  They don't need to be
7541    * sorted - the generator() function just does a dumb linear search.
7542    *)
7543   let commands =
7544     List.map (
7545       fun (name, _, _, flags, _, _, _) ->
7546         let name2 = replace_char name '_' '-' in
7547         let alias =
7548           try find_map (function FishAlias n -> Some n | _ -> None) flags
7549           with Not_found -> name in
7550
7551         if name <> alias then [name2; alias] else [name2]
7552     ) all_functions in
7553   let commands = List.flatten commands in
7554
7555   List.iter (pr "  \"%s\",\n") commands;
7556
7557   pr "  NULL
7558 };
7559
7560 static char *
7561 generator (const char *text, int state)
7562 {
7563   static int index, len;
7564   const char *name;
7565
7566   if (!state) {
7567     index = 0;
7568     len = strlen (text);
7569   }
7570
7571   rl_attempted_completion_over = 1;
7572
7573   while ((name = commands[index]) != NULL) {
7574     index++;
7575     if (STRCASEEQLEN (name, text, len))
7576       return strdup (name);
7577   }
7578
7579   return NULL;
7580 }
7581
7582 #endif /* HAVE_LIBREADLINE */
7583
7584 #ifdef HAVE_RL_COMPLETION_MATCHES
7585 #define RL_COMPLETION_MATCHES rl_completion_matches
7586 #else
7587 #ifdef HAVE_COMPLETION_MATCHES
7588 #define RL_COMPLETION_MATCHES completion_matches
7589 #endif
7590 #endif /* else just fail if we don't have either symbol */
7591
7592 char **
7593 do_completion (const char *text, int start, int end)
7594 {
7595   char **matches = NULL;
7596
7597 #ifdef HAVE_LIBREADLINE
7598   rl_completion_append_character = ' ';
7599
7600   if (start == 0)
7601     matches = RL_COMPLETION_MATCHES (text, generator);
7602   else if (complete_dest_paths)
7603     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7604 #endif
7605
7606   return matches;
7607 }
7608 ";
7609
7610 (* Generate the POD documentation for guestfish. *)
7611 and generate_fish_actions_pod () =
7612   let all_functions_sorted =
7613     List.filter (
7614       fun (_, _, _, flags, _, _, _) ->
7615         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7616     ) all_functions_sorted in
7617
7618   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7619
7620   List.iter (
7621     fun (name, style, _, flags, _, _, longdesc) ->
7622       let longdesc =
7623         Str.global_substitute rex (
7624           fun s ->
7625             let sub =
7626               try Str.matched_group 1 s
7627               with Not_found ->
7628                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7629             "C<" ^ replace_char sub '_' '-' ^ ">"
7630         ) longdesc in
7631       let name = replace_char name '_' '-' in
7632       let alias =
7633         try find_map (function FishAlias n -> Some n | _ -> None) flags
7634         with Not_found -> name in
7635
7636       pr "=head2 %s" name;
7637       if name <> alias then
7638         pr " | %s" alias;
7639       pr "\n";
7640       pr "\n";
7641       pr " %s" name;
7642       List.iter (
7643         function
7644         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7645         | OptString n -> pr " %s" n
7646         | StringList n | DeviceList n -> pr " '%s ...'" n
7647         | Bool _ -> pr " true|false"
7648         | Int n -> pr " %s" n
7649         | Int64 n -> pr " %s" n
7650         | FileIn n | FileOut n -> pr " (%s|-)" n
7651       ) (snd style);
7652       pr "\n";
7653       pr "\n";
7654       pr "%s\n\n" longdesc;
7655
7656       if List.exists (function FileIn _ | FileOut _ -> true
7657                       | _ -> false) (snd style) then
7658         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7659
7660       if List.mem ProtocolLimitWarning flags then
7661         pr "%s\n\n" protocol_limit_warning;
7662
7663       if List.mem DangerWillRobinson flags then
7664         pr "%s\n\n" danger_will_robinson;
7665
7666       match deprecation_notice flags with
7667       | None -> ()
7668       | Some txt -> pr "%s\n\n" txt
7669   ) all_functions_sorted
7670
7671 (* Generate a C function prototype. *)
7672 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7673     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7674     ?(prefix = "")
7675     ?handle name style =
7676   if extern then pr "extern ";
7677   if static then pr "static ";
7678   (match fst style with
7679    | RErr -> pr "int "
7680    | RInt _ -> pr "int "
7681    | RInt64 _ -> pr "int64_t "
7682    | RBool _ -> pr "int "
7683    | RConstString _ | RConstOptString _ -> pr "const char *"
7684    | RString _ | RBufferOut _ -> pr "char *"
7685    | RStringList _ | RHashtable _ -> pr "char **"
7686    | RStruct (_, typ) ->
7687        if not in_daemon then pr "struct guestfs_%s *" typ
7688        else pr "guestfs_int_%s *" typ
7689    | RStructList (_, typ) ->
7690        if not in_daemon then pr "struct guestfs_%s_list *" typ
7691        else pr "guestfs_int_%s_list *" typ
7692   );
7693   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7694   pr "%s%s (" prefix name;
7695   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7696     pr "void"
7697   else (
7698     let comma = ref false in
7699     (match handle with
7700      | None -> ()
7701      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7702     );
7703     let next () =
7704       if !comma then (
7705         if single_line then pr ", " else pr ",\n\t\t"
7706       );
7707       comma := true
7708     in
7709     List.iter (
7710       function
7711       | Pathname n
7712       | Device n | Dev_or_Path n
7713       | String n
7714       | OptString n ->
7715           next ();
7716           pr "const char *%s" n
7717       | StringList n | DeviceList n ->
7718           next ();
7719           pr "char *const *%s" n
7720       | Bool n -> next (); pr "int %s" n
7721       | Int n -> next (); pr "int %s" n
7722       | Int64 n -> next (); pr "int64_t %s" n
7723       | FileIn n
7724       | FileOut n ->
7725           if not in_daemon then (next (); pr "const char *%s" n)
7726     ) (snd style);
7727     if is_RBufferOut then (next (); pr "size_t *size_r");
7728   );
7729   pr ")";
7730   if semicolon then pr ";";
7731   if newline then pr "\n"
7732
7733 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7734 and generate_c_call_args ?handle ?(decl = false) style =
7735   pr "(";
7736   let comma = ref false in
7737   let next () =
7738     if !comma then pr ", ";
7739     comma := true
7740   in
7741   (match handle with
7742    | None -> ()
7743    | Some handle -> pr "%s" handle; comma := true
7744   );
7745   List.iter (
7746     fun arg ->
7747       next ();
7748       pr "%s" (name_of_argt arg)
7749   ) (snd style);
7750   (* For RBufferOut calls, add implicit &size parameter. *)
7751   if not decl then (
7752     match fst style with
7753     | RBufferOut _ ->
7754         next ();
7755         pr "&size"
7756     | _ -> ()
7757   );
7758   pr ")"
7759
7760 (* Generate the OCaml bindings interface. *)
7761 and generate_ocaml_mli () =
7762   generate_header OCamlStyle LGPLv2plus;
7763
7764   pr "\
7765 (** For API documentation you should refer to the C API
7766     in the guestfs(3) manual page.  The OCaml API uses almost
7767     exactly the same calls. *)
7768
7769 type t
7770 (** A [guestfs_h] handle. *)
7771
7772 exception Error of string
7773 (** This exception is raised when there is an error. *)
7774
7775 exception Handle_closed of string
7776 (** This exception is raised if you use a {!Guestfs.t} handle
7777     after calling {!close} on it.  The string is the name of
7778     the function. *)
7779
7780 val create : unit -> t
7781 (** Create a {!Guestfs.t} handle. *)
7782
7783 val close : t -> unit
7784 (** Close the {!Guestfs.t} handle and free up all resources used
7785     by it immediately.
7786
7787     Handles are closed by the garbage collector when they become
7788     unreferenced, but callers can call this in order to provide
7789     predictable cleanup. *)
7790
7791 ";
7792   generate_ocaml_structure_decls ();
7793
7794   (* The actions. *)
7795   List.iter (
7796     fun (name, style, _, _, _, shortdesc, _) ->
7797       generate_ocaml_prototype name style;
7798       pr "(** %s *)\n" shortdesc;
7799       pr "\n"
7800   ) all_functions_sorted
7801
7802 (* Generate the OCaml bindings implementation. *)
7803 and generate_ocaml_ml () =
7804   generate_header OCamlStyle LGPLv2plus;
7805
7806   pr "\
7807 type t
7808
7809 exception Error of string
7810 exception Handle_closed of string
7811
7812 external create : unit -> t = \"ocaml_guestfs_create\"
7813 external close : t -> unit = \"ocaml_guestfs_close\"
7814
7815 (* Give the exceptions names, so they can be raised from the C code. *)
7816 let () =
7817   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7818   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7819
7820 ";
7821
7822   generate_ocaml_structure_decls ();
7823
7824   (* The actions. *)
7825   List.iter (
7826     fun (name, style, _, _, _, shortdesc, _) ->
7827       generate_ocaml_prototype ~is_external:true name style;
7828   ) all_functions_sorted
7829
7830 (* Generate the OCaml bindings C implementation. *)
7831 and generate_ocaml_c () =
7832   generate_header CStyle LGPLv2plus;
7833
7834   pr "\
7835 #include <stdio.h>
7836 #include <stdlib.h>
7837 #include <string.h>
7838
7839 #include <caml/config.h>
7840 #include <caml/alloc.h>
7841 #include <caml/callback.h>
7842 #include <caml/fail.h>
7843 #include <caml/memory.h>
7844 #include <caml/mlvalues.h>
7845 #include <caml/signals.h>
7846
7847 #include <guestfs.h>
7848
7849 #include \"guestfs_c.h\"
7850
7851 /* Copy a hashtable of string pairs into an assoc-list.  We return
7852  * the list in reverse order, but hashtables aren't supposed to be
7853  * ordered anyway.
7854  */
7855 static CAMLprim value
7856 copy_table (char * const * argv)
7857 {
7858   CAMLparam0 ();
7859   CAMLlocal5 (rv, pairv, kv, vv, cons);
7860   int i;
7861
7862   rv = Val_int (0);
7863   for (i = 0; argv[i] != NULL; i += 2) {
7864     kv = caml_copy_string (argv[i]);
7865     vv = caml_copy_string (argv[i+1]);
7866     pairv = caml_alloc (2, 0);
7867     Store_field (pairv, 0, kv);
7868     Store_field (pairv, 1, vv);
7869     cons = caml_alloc (2, 0);
7870     Store_field (cons, 1, rv);
7871     rv = cons;
7872     Store_field (cons, 0, pairv);
7873   }
7874
7875   CAMLreturn (rv);
7876 }
7877
7878 ";
7879
7880   (* Struct copy functions. *)
7881
7882   let emit_ocaml_copy_list_function typ =
7883     pr "static CAMLprim value\n";
7884     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7885     pr "{\n";
7886     pr "  CAMLparam0 ();\n";
7887     pr "  CAMLlocal2 (rv, v);\n";
7888     pr "  unsigned int i;\n";
7889     pr "\n";
7890     pr "  if (%ss->len == 0)\n" typ;
7891     pr "    CAMLreturn (Atom (0));\n";
7892     pr "  else {\n";
7893     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7894     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7895     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7896     pr "      caml_modify (&Field (rv, i), v);\n";
7897     pr "    }\n";
7898     pr "    CAMLreturn (rv);\n";
7899     pr "  }\n";
7900     pr "}\n";
7901     pr "\n";
7902   in
7903
7904   List.iter (
7905     fun (typ, cols) ->
7906       let has_optpercent_col =
7907         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7908
7909       pr "static CAMLprim value\n";
7910       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7911       pr "{\n";
7912       pr "  CAMLparam0 ();\n";
7913       if has_optpercent_col then
7914         pr "  CAMLlocal3 (rv, v, v2);\n"
7915       else
7916         pr "  CAMLlocal2 (rv, v);\n";
7917       pr "\n";
7918       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7919       iteri (
7920         fun i col ->
7921           (match col with
7922            | name, FString ->
7923                pr "  v = caml_copy_string (%s->%s);\n" typ name
7924            | name, FBuffer ->
7925                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7926                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7927                  typ name typ name
7928            | name, FUUID ->
7929                pr "  v = caml_alloc_string (32);\n";
7930                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7931            | name, (FBytes|FInt64|FUInt64) ->
7932                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7933            | name, (FInt32|FUInt32) ->
7934                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7935            | name, FOptPercent ->
7936                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7937                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7938                pr "    v = caml_alloc (1, 0);\n";
7939                pr "    Store_field (v, 0, v2);\n";
7940                pr "  } else /* None */\n";
7941                pr "    v = Val_int (0);\n";
7942            | name, FChar ->
7943                pr "  v = Val_int (%s->%s);\n" typ name
7944           );
7945           pr "  Store_field (rv, %d, v);\n" i
7946       ) cols;
7947       pr "  CAMLreturn (rv);\n";
7948       pr "}\n";
7949       pr "\n";
7950   ) structs;
7951
7952   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7953   List.iter (
7954     function
7955     | typ, (RStructListOnly | RStructAndList) ->
7956         (* generate the function for typ *)
7957         emit_ocaml_copy_list_function typ
7958     | typ, _ -> () (* empty *)
7959   ) (rstructs_used_by all_functions);
7960
7961   (* The wrappers. *)
7962   List.iter (
7963     fun (name, style, _, _, _, _, _) ->
7964       pr "/* Automatically generated wrapper for function\n";
7965       pr " * ";
7966       generate_ocaml_prototype name style;
7967       pr " */\n";
7968       pr "\n";
7969
7970       let params =
7971         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7972
7973       let needs_extra_vs =
7974         match fst style with RConstOptString _ -> true | _ -> false in
7975
7976       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7977       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7978       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7979       pr "\n";
7980
7981       pr "CAMLprim value\n";
7982       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7983       List.iter (pr ", value %s") (List.tl params);
7984       pr ")\n";
7985       pr "{\n";
7986
7987       (match params with
7988        | [p1; p2; p3; p4; p5] ->
7989            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7990        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7991            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7992            pr "  CAMLxparam%d (%s);\n"
7993              (List.length rest) (String.concat ", " rest)
7994        | ps ->
7995            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7996       );
7997       if not needs_extra_vs then
7998         pr "  CAMLlocal1 (rv);\n"
7999       else
8000         pr "  CAMLlocal3 (rv, v, v2);\n";
8001       pr "\n";
8002
8003       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8004       pr "  if (g == NULL)\n";
8005       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8006       pr "\n";
8007
8008       List.iter (
8009         function
8010         | Pathname n
8011         | Device n | Dev_or_Path n
8012         | String n
8013         | FileIn n
8014         | FileOut n ->
8015             pr "  const char *%s = String_val (%sv);\n" n n
8016         | OptString n ->
8017             pr "  const char *%s =\n" n;
8018             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8019               n n
8020         | StringList n | DeviceList n ->
8021             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8022         | Bool n ->
8023             pr "  int %s = Bool_val (%sv);\n" n n
8024         | Int n ->
8025             pr "  int %s = Int_val (%sv);\n" n n
8026         | Int64 n ->
8027             pr "  int64_t %s = Int64_val (%sv);\n" n n
8028       ) (snd style);
8029       let error_code =
8030         match fst style with
8031         | RErr -> pr "  int r;\n"; "-1"
8032         | RInt _ -> pr "  int r;\n"; "-1"
8033         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8034         | RBool _ -> pr "  int r;\n"; "-1"
8035         | RConstString _ | RConstOptString _ ->
8036             pr "  const char *r;\n"; "NULL"
8037         | RString _ -> pr "  char *r;\n"; "NULL"
8038         | RStringList _ ->
8039             pr "  int i;\n";
8040             pr "  char **r;\n";
8041             "NULL"
8042         | RStruct (_, typ) ->
8043             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8044         | RStructList (_, typ) ->
8045             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8046         | RHashtable _ ->
8047             pr "  int i;\n";
8048             pr "  char **r;\n";
8049             "NULL"
8050         | RBufferOut _ ->
8051             pr "  char *r;\n";
8052             pr "  size_t size;\n";
8053             "NULL" in
8054       pr "\n";
8055
8056       pr "  caml_enter_blocking_section ();\n";
8057       pr "  r = guestfs_%s " name;
8058       generate_c_call_args ~handle:"g" style;
8059       pr ";\n";
8060       pr "  caml_leave_blocking_section ();\n";
8061
8062       List.iter (
8063         function
8064         | StringList n | DeviceList n ->
8065             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8066         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8067         | Bool _ | Int _ | Int64 _
8068         | FileIn _ | FileOut _ -> ()
8069       ) (snd style);
8070
8071       pr "  if (r == %s)\n" error_code;
8072       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8073       pr "\n";
8074
8075       (match fst style with
8076        | RErr -> pr "  rv = Val_unit;\n"
8077        | RInt _ -> pr "  rv = Val_int (r);\n"
8078        | RInt64 _ ->
8079            pr "  rv = caml_copy_int64 (r);\n"
8080        | RBool _ -> pr "  rv = Val_bool (r);\n"
8081        | RConstString _ ->
8082            pr "  rv = caml_copy_string (r);\n"
8083        | RConstOptString _ ->
8084            pr "  if (r) { /* Some string */\n";
8085            pr "    v = caml_alloc (1, 0);\n";
8086            pr "    v2 = caml_copy_string (r);\n";
8087            pr "    Store_field (v, 0, v2);\n";
8088            pr "  } else /* None */\n";
8089            pr "    v = Val_int (0);\n";
8090        | RString _ ->
8091            pr "  rv = caml_copy_string (r);\n";
8092            pr "  free (r);\n"
8093        | RStringList _ ->
8094            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8095            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8096            pr "  free (r);\n"
8097        | RStruct (_, typ) ->
8098            pr "  rv = copy_%s (r);\n" typ;
8099            pr "  guestfs_free_%s (r);\n" typ;
8100        | RStructList (_, typ) ->
8101            pr "  rv = copy_%s_list (r);\n" typ;
8102            pr "  guestfs_free_%s_list (r);\n" typ;
8103        | RHashtable _ ->
8104            pr "  rv = copy_table (r);\n";
8105            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8106            pr "  free (r);\n";
8107        | RBufferOut _ ->
8108            pr "  rv = caml_alloc_string (size);\n";
8109            pr "  memcpy (String_val (rv), r, size);\n";
8110       );
8111
8112       pr "  CAMLreturn (rv);\n";
8113       pr "}\n";
8114       pr "\n";
8115
8116       if List.length params > 5 then (
8117         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8118         pr "CAMLprim value ";
8119         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8120         pr "CAMLprim value\n";
8121         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8122         pr "{\n";
8123         pr "  return ocaml_guestfs_%s (argv[0]" name;
8124         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8125         pr ");\n";
8126         pr "}\n";
8127         pr "\n"
8128       )
8129   ) all_functions_sorted
8130
8131 and generate_ocaml_structure_decls () =
8132   List.iter (
8133     fun (typ, cols) ->
8134       pr "type %s = {\n" typ;
8135       List.iter (
8136         function
8137         | name, FString -> pr "  %s : string;\n" name
8138         | name, FBuffer -> pr "  %s : string;\n" name
8139         | name, FUUID -> pr "  %s : string;\n" name
8140         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8141         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8142         | name, FChar -> pr "  %s : char;\n" name
8143         | name, FOptPercent -> pr "  %s : float option;\n" name
8144       ) cols;
8145       pr "}\n";
8146       pr "\n"
8147   ) structs
8148
8149 and generate_ocaml_prototype ?(is_external = false) name style =
8150   if is_external then pr "external " else pr "val ";
8151   pr "%s : t -> " name;
8152   List.iter (
8153     function
8154     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8155     | OptString _ -> pr "string option -> "
8156     | StringList _ | DeviceList _ -> pr "string array -> "
8157     | Bool _ -> pr "bool -> "
8158     | Int _ -> pr "int -> "
8159     | Int64 _ -> pr "int64 -> "
8160   ) (snd style);
8161   (match fst style with
8162    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8163    | RInt _ -> pr "int"
8164    | RInt64 _ -> pr "int64"
8165    | RBool _ -> pr "bool"
8166    | RConstString _ -> pr "string"
8167    | RConstOptString _ -> pr "string option"
8168    | RString _ | RBufferOut _ -> pr "string"
8169    | RStringList _ -> pr "string array"
8170    | RStruct (_, typ) -> pr "%s" typ
8171    | RStructList (_, typ) -> pr "%s array" typ
8172    | RHashtable _ -> pr "(string * string) list"
8173   );
8174   if is_external then (
8175     pr " = ";
8176     if List.length (snd style) + 1 > 5 then
8177       pr "\"ocaml_guestfs_%s_byte\" " name;
8178     pr "\"ocaml_guestfs_%s\"" name
8179   );
8180   pr "\n"
8181
8182 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8183 and generate_perl_xs () =
8184   generate_header CStyle LGPLv2plus;
8185
8186   pr "\
8187 #include \"EXTERN.h\"
8188 #include \"perl.h\"
8189 #include \"XSUB.h\"
8190
8191 #include <guestfs.h>
8192
8193 #ifndef PRId64
8194 #define PRId64 \"lld\"
8195 #endif
8196
8197 static SV *
8198 my_newSVll(long long val) {
8199 #ifdef USE_64_BIT_ALL
8200   return newSViv(val);
8201 #else
8202   char buf[100];
8203   int len;
8204   len = snprintf(buf, 100, \"%%\" PRId64, val);
8205   return newSVpv(buf, len);
8206 #endif
8207 }
8208
8209 #ifndef PRIu64
8210 #define PRIu64 \"llu\"
8211 #endif
8212
8213 static SV *
8214 my_newSVull(unsigned long long val) {
8215 #ifdef USE_64_BIT_ALL
8216   return newSVuv(val);
8217 #else
8218   char buf[100];
8219   int len;
8220   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8221   return newSVpv(buf, len);
8222 #endif
8223 }
8224
8225 /* http://www.perlmonks.org/?node_id=680842 */
8226 static char **
8227 XS_unpack_charPtrPtr (SV *arg) {
8228   char **ret;
8229   AV *av;
8230   I32 i;
8231
8232   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8233     croak (\"array reference expected\");
8234
8235   av = (AV *)SvRV (arg);
8236   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8237   if (!ret)
8238     croak (\"malloc failed\");
8239
8240   for (i = 0; i <= av_len (av); i++) {
8241     SV **elem = av_fetch (av, i, 0);
8242
8243     if (!elem || !*elem)
8244       croak (\"missing element in list\");
8245
8246     ret[i] = SvPV_nolen (*elem);
8247   }
8248
8249   ret[i] = NULL;
8250
8251   return ret;
8252 }
8253
8254 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8255
8256 PROTOTYPES: ENABLE
8257
8258 guestfs_h *
8259 _create ()
8260    CODE:
8261       RETVAL = guestfs_create ();
8262       if (!RETVAL)
8263         croak (\"could not create guestfs handle\");
8264       guestfs_set_error_handler (RETVAL, NULL, NULL);
8265  OUTPUT:
8266       RETVAL
8267
8268 void
8269 DESTROY (g)
8270       guestfs_h *g;
8271  PPCODE:
8272       guestfs_close (g);
8273
8274 ";
8275
8276   List.iter (
8277     fun (name, style, _, _, _, _, _) ->
8278       (match fst style with
8279        | RErr -> pr "void\n"
8280        | RInt _ -> pr "SV *\n"
8281        | RInt64 _ -> pr "SV *\n"
8282        | RBool _ -> pr "SV *\n"
8283        | RConstString _ -> pr "SV *\n"
8284        | RConstOptString _ -> pr "SV *\n"
8285        | RString _ -> pr "SV *\n"
8286        | RBufferOut _ -> pr "SV *\n"
8287        | RStringList _
8288        | RStruct _ | RStructList _
8289        | RHashtable _ ->
8290            pr "void\n" (* all lists returned implictly on the stack *)
8291       );
8292       (* Call and arguments. *)
8293       pr "%s " name;
8294       generate_c_call_args ~handle:"g" ~decl:true style;
8295       pr "\n";
8296       pr "      guestfs_h *g;\n";
8297       iteri (
8298         fun i ->
8299           function
8300           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8301               pr "      char *%s;\n" n
8302           | OptString n ->
8303               (* http://www.perlmonks.org/?node_id=554277
8304                * Note that the implicit handle argument means we have
8305                * to add 1 to the ST(x) operator.
8306                *)
8307               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8308           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8309           | Bool n -> pr "      int %s;\n" n
8310           | Int n -> pr "      int %s;\n" n
8311           | Int64 n -> pr "      int64_t %s;\n" n
8312       ) (snd style);
8313
8314       let do_cleanups () =
8315         List.iter (
8316           function
8317           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8318           | Bool _ | Int _ | Int64 _
8319           | FileIn _ | FileOut _ -> ()
8320           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8321         ) (snd style)
8322       in
8323
8324       (* Code. *)
8325       (match fst style with
8326        | RErr ->
8327            pr "PREINIT:\n";
8328            pr "      int r;\n";
8329            pr " PPCODE:\n";
8330            pr "      r = guestfs_%s " name;
8331            generate_c_call_args ~handle:"g" style;
8332            pr ";\n";
8333            do_cleanups ();
8334            pr "      if (r == -1)\n";
8335            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8336        | RInt n
8337        | RBool n ->
8338            pr "PREINIT:\n";
8339            pr "      int %s;\n" n;
8340            pr "   CODE:\n";
8341            pr "      %s = guestfs_%s " n name;
8342            generate_c_call_args ~handle:"g" style;
8343            pr ";\n";
8344            do_cleanups ();
8345            pr "      if (%s == -1)\n" n;
8346            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8347            pr "      RETVAL = newSViv (%s);\n" n;
8348            pr " OUTPUT:\n";
8349            pr "      RETVAL\n"
8350        | RInt64 n ->
8351            pr "PREINIT:\n";
8352            pr "      int64_t %s;\n" n;
8353            pr "   CODE:\n";
8354            pr "      %s = guestfs_%s " n name;
8355            generate_c_call_args ~handle:"g" style;
8356            pr ";\n";
8357            do_cleanups ();
8358            pr "      if (%s == -1)\n" n;
8359            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8360            pr "      RETVAL = my_newSVll (%s);\n" n;
8361            pr " OUTPUT:\n";
8362            pr "      RETVAL\n"
8363        | RConstString n ->
8364            pr "PREINIT:\n";
8365            pr "      const char *%s;\n" n;
8366            pr "   CODE:\n";
8367            pr "      %s = guestfs_%s " n name;
8368            generate_c_call_args ~handle:"g" style;
8369            pr ";\n";
8370            do_cleanups ();
8371            pr "      if (%s == NULL)\n" n;
8372            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8373            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8374            pr " OUTPUT:\n";
8375            pr "      RETVAL\n"
8376        | RConstOptString n ->
8377            pr "PREINIT:\n";
8378            pr "      const char *%s;\n" n;
8379            pr "   CODE:\n";
8380            pr "      %s = guestfs_%s " n name;
8381            generate_c_call_args ~handle:"g" style;
8382            pr ";\n";
8383            do_cleanups ();
8384            pr "      if (%s == NULL)\n" n;
8385            pr "        RETVAL = &PL_sv_undef;\n";
8386            pr "      else\n";
8387            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8388            pr " OUTPUT:\n";
8389            pr "      RETVAL\n"
8390        | RString n ->
8391            pr "PREINIT:\n";
8392            pr "      char *%s;\n" n;
8393            pr "   CODE:\n";
8394            pr "      %s = guestfs_%s " n name;
8395            generate_c_call_args ~handle:"g" style;
8396            pr ";\n";
8397            do_cleanups ();
8398            pr "      if (%s == NULL)\n" n;
8399            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8400            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8401            pr "      free (%s);\n" n;
8402            pr " OUTPUT:\n";
8403            pr "      RETVAL\n"
8404        | RStringList n | RHashtable n ->
8405            pr "PREINIT:\n";
8406            pr "      char **%s;\n" n;
8407            pr "      int i, n;\n";
8408            pr " PPCODE:\n";
8409            pr "      %s = guestfs_%s " n name;
8410            generate_c_call_args ~handle:"g" style;
8411            pr ";\n";
8412            do_cleanups ();
8413            pr "      if (%s == NULL)\n" n;
8414            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8415            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8416            pr "      EXTEND (SP, n);\n";
8417            pr "      for (i = 0; i < n; ++i) {\n";
8418            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8419            pr "        free (%s[i]);\n" n;
8420            pr "      }\n";
8421            pr "      free (%s);\n" n;
8422        | RStruct (n, typ) ->
8423            let cols = cols_of_struct typ in
8424            generate_perl_struct_code typ cols name style n do_cleanups
8425        | RStructList (n, typ) ->
8426            let cols = cols_of_struct typ in
8427            generate_perl_struct_list_code typ cols name style n do_cleanups
8428        | RBufferOut n ->
8429            pr "PREINIT:\n";
8430            pr "      char *%s;\n" n;
8431            pr "      size_t size;\n";
8432            pr "   CODE:\n";
8433            pr "      %s = guestfs_%s " n name;
8434            generate_c_call_args ~handle:"g" style;
8435            pr ";\n";
8436            do_cleanups ();
8437            pr "      if (%s == NULL)\n" n;
8438            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8439            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8440            pr "      free (%s);\n" n;
8441            pr " OUTPUT:\n";
8442            pr "      RETVAL\n"
8443       );
8444
8445       pr "\n"
8446   ) all_functions
8447
8448 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8449   pr "PREINIT:\n";
8450   pr "      struct guestfs_%s_list *%s;\n" typ n;
8451   pr "      int i;\n";
8452   pr "      HV *hv;\n";
8453   pr " PPCODE:\n";
8454   pr "      %s = guestfs_%s " n name;
8455   generate_c_call_args ~handle:"g" style;
8456   pr ";\n";
8457   do_cleanups ();
8458   pr "      if (%s == NULL)\n" n;
8459   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8460   pr "      EXTEND (SP, %s->len);\n" n;
8461   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8462   pr "        hv = newHV ();\n";
8463   List.iter (
8464     function
8465     | name, FString ->
8466         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8467           name (String.length name) n name
8468     | name, FUUID ->
8469         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8470           name (String.length name) n name
8471     | name, FBuffer ->
8472         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8473           name (String.length name) n name n name
8474     | name, (FBytes|FUInt64) ->
8475         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8476           name (String.length name) n name
8477     | name, FInt64 ->
8478         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8479           name (String.length name) n name
8480     | name, (FInt32|FUInt32) ->
8481         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8482           name (String.length name) n name
8483     | name, FChar ->
8484         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8485           name (String.length name) n name
8486     | name, FOptPercent ->
8487         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8488           name (String.length name) n name
8489   ) cols;
8490   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8491   pr "      }\n";
8492   pr "      guestfs_free_%s_list (%s);\n" typ n
8493
8494 and generate_perl_struct_code typ cols name style n do_cleanups =
8495   pr "PREINIT:\n";
8496   pr "      struct guestfs_%s *%s;\n" typ n;
8497   pr " PPCODE:\n";
8498   pr "      %s = guestfs_%s " n name;
8499   generate_c_call_args ~handle:"g" style;
8500   pr ";\n";
8501   do_cleanups ();
8502   pr "      if (%s == NULL)\n" n;
8503   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8504   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8505   List.iter (
8506     fun ((name, _) as col) ->
8507       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8508
8509       match col with
8510       | name, FString ->
8511           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8512             n name
8513       | name, FBuffer ->
8514           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8515             n name n name
8516       | name, FUUID ->
8517           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8518             n name
8519       | name, (FBytes|FUInt64) ->
8520           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8521             n name
8522       | name, FInt64 ->
8523           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8524             n name
8525       | name, (FInt32|FUInt32) ->
8526           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8527             n name
8528       | name, FChar ->
8529           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8530             n name
8531       | name, FOptPercent ->
8532           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8533             n name
8534   ) cols;
8535   pr "      free (%s);\n" n
8536
8537 (* Generate Sys/Guestfs.pm. *)
8538 and generate_perl_pm () =
8539   generate_header HashStyle LGPLv2plus;
8540
8541   pr "\
8542 =pod
8543
8544 =head1 NAME
8545
8546 Sys::Guestfs - Perl bindings for libguestfs
8547
8548 =head1 SYNOPSIS
8549
8550  use Sys::Guestfs;
8551
8552  my $h = Sys::Guestfs->new ();
8553  $h->add_drive ('guest.img');
8554  $h->launch ();
8555  $h->mount ('/dev/sda1', '/');
8556  $h->touch ('/hello');
8557  $h->sync ();
8558
8559 =head1 DESCRIPTION
8560
8561 The C<Sys::Guestfs> module provides a Perl XS binding to the
8562 libguestfs API for examining and modifying virtual machine
8563 disk images.
8564
8565 Amongst the things this is good for: making batch configuration
8566 changes to guests, getting disk used/free statistics (see also:
8567 virt-df), migrating between virtualization systems (see also:
8568 virt-p2v), performing partial backups, performing partial guest
8569 clones, cloning guests and changing registry/UUID/hostname info, and
8570 much else besides.
8571
8572 Libguestfs uses Linux kernel and qemu code, and can access any type of
8573 guest filesystem that Linux and qemu can, including but not limited
8574 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8575 schemes, qcow, qcow2, vmdk.
8576
8577 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8578 LVs, what filesystem is in each LV, etc.).  It can also run commands
8579 in the context of the guest.  Also you can access filesystems over
8580 FUSE.
8581
8582 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8583 functions for using libguestfs from Perl, including integration
8584 with libvirt.
8585
8586 =head1 ERRORS
8587
8588 All errors turn into calls to C<croak> (see L<Carp(3)>).
8589
8590 =head1 METHODS
8591
8592 =over 4
8593
8594 =cut
8595
8596 package Sys::Guestfs;
8597
8598 use strict;
8599 use warnings;
8600
8601 require XSLoader;
8602 XSLoader::load ('Sys::Guestfs');
8603
8604 =item $h = Sys::Guestfs->new ();
8605
8606 Create a new guestfs handle.
8607
8608 =cut
8609
8610 sub new {
8611   my $proto = shift;
8612   my $class = ref ($proto) || $proto;
8613
8614   my $self = Sys::Guestfs::_create ();
8615   bless $self, $class;
8616   return $self;
8617 }
8618
8619 ";
8620
8621   (* Actions.  We only need to print documentation for these as
8622    * they are pulled in from the XS code automatically.
8623    *)
8624   List.iter (
8625     fun (name, style, _, flags, _, _, longdesc) ->
8626       if not (List.mem NotInDocs flags) then (
8627         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8628         pr "=item ";
8629         generate_perl_prototype name style;
8630         pr "\n\n";
8631         pr "%s\n\n" longdesc;
8632         if List.mem ProtocolLimitWarning flags then
8633           pr "%s\n\n" protocol_limit_warning;
8634         if List.mem DangerWillRobinson flags then
8635           pr "%s\n\n" danger_will_robinson;
8636         match deprecation_notice flags with
8637         | None -> ()
8638         | Some txt -> pr "%s\n\n" txt
8639       )
8640   ) all_functions_sorted;
8641
8642   (* End of file. *)
8643   pr "\
8644 =cut
8645
8646 1;
8647
8648 =back
8649
8650 =head1 COPYRIGHT
8651
8652 Copyright (C) %s Red Hat Inc.
8653
8654 =head1 LICENSE
8655
8656 Please see the file COPYING.LIB for the full license.
8657
8658 =head1 SEE ALSO
8659
8660 L<guestfs(3)>,
8661 L<guestfish(1)>,
8662 L<http://libguestfs.org>,
8663 L<Sys::Guestfs::Lib(3)>.
8664
8665 =cut
8666 " copyright_years
8667
8668 and generate_perl_prototype name style =
8669   (match fst style with
8670    | RErr -> ()
8671    | RBool n
8672    | RInt n
8673    | RInt64 n
8674    | RConstString n
8675    | RConstOptString n
8676    | RString n
8677    | RBufferOut n -> pr "$%s = " n
8678    | RStruct (n,_)
8679    | RHashtable n -> pr "%%%s = " n
8680    | RStringList n
8681    | RStructList (n,_) -> pr "@%s = " n
8682   );
8683   pr "$h->%s (" name;
8684   let comma = ref false in
8685   List.iter (
8686     fun arg ->
8687       if !comma then pr ", ";
8688       comma := true;
8689       match arg with
8690       | Pathname n | Device n | Dev_or_Path n | String n
8691       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8692           pr "$%s" n
8693       | StringList n | DeviceList n ->
8694           pr "\\@%s" n
8695   ) (snd style);
8696   pr ");"
8697
8698 (* Generate Python C module. *)
8699 and generate_python_c () =
8700   generate_header CStyle LGPLv2plus;
8701
8702   pr "\
8703 #include <Python.h>
8704
8705 #include <stdio.h>
8706 #include <stdlib.h>
8707 #include <assert.h>
8708
8709 #include \"guestfs.h\"
8710
8711 typedef struct {
8712   PyObject_HEAD
8713   guestfs_h *g;
8714 } Pyguestfs_Object;
8715
8716 static guestfs_h *
8717 get_handle (PyObject *obj)
8718 {
8719   assert (obj);
8720   assert (obj != Py_None);
8721   return ((Pyguestfs_Object *) obj)->g;
8722 }
8723
8724 static PyObject *
8725 put_handle (guestfs_h *g)
8726 {
8727   assert (g);
8728   return
8729     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8730 }
8731
8732 /* This list should be freed (but not the strings) after use. */
8733 static char **
8734 get_string_list (PyObject *obj)
8735 {
8736   int i, len;
8737   char **r;
8738
8739   assert (obj);
8740
8741   if (!PyList_Check (obj)) {
8742     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8743     return NULL;
8744   }
8745
8746   len = PyList_Size (obj);
8747   r = malloc (sizeof (char *) * (len+1));
8748   if (r == NULL) {
8749     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8750     return NULL;
8751   }
8752
8753   for (i = 0; i < len; ++i)
8754     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8755   r[len] = NULL;
8756
8757   return r;
8758 }
8759
8760 static PyObject *
8761 put_string_list (char * const * const argv)
8762 {
8763   PyObject *list;
8764   int argc, i;
8765
8766   for (argc = 0; argv[argc] != NULL; ++argc)
8767     ;
8768
8769   list = PyList_New (argc);
8770   for (i = 0; i < argc; ++i)
8771     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8772
8773   return list;
8774 }
8775
8776 static PyObject *
8777 put_table (char * const * const argv)
8778 {
8779   PyObject *list, *item;
8780   int argc, i;
8781
8782   for (argc = 0; argv[argc] != NULL; ++argc)
8783     ;
8784
8785   list = PyList_New (argc >> 1);
8786   for (i = 0; i < argc; i += 2) {
8787     item = PyTuple_New (2);
8788     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8789     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8790     PyList_SetItem (list, i >> 1, item);
8791   }
8792
8793   return list;
8794 }
8795
8796 static void
8797 free_strings (char **argv)
8798 {
8799   int argc;
8800
8801   for (argc = 0; argv[argc] != NULL; ++argc)
8802     free (argv[argc]);
8803   free (argv);
8804 }
8805
8806 static PyObject *
8807 py_guestfs_create (PyObject *self, PyObject *args)
8808 {
8809   guestfs_h *g;
8810
8811   g = guestfs_create ();
8812   if (g == NULL) {
8813     PyErr_SetString (PyExc_RuntimeError,
8814                      \"guestfs.create: failed to allocate handle\");
8815     return NULL;
8816   }
8817   guestfs_set_error_handler (g, NULL, NULL);
8818   return put_handle (g);
8819 }
8820
8821 static PyObject *
8822 py_guestfs_close (PyObject *self, PyObject *args)
8823 {
8824   PyObject *py_g;
8825   guestfs_h *g;
8826
8827   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8828     return NULL;
8829   g = get_handle (py_g);
8830
8831   guestfs_close (g);
8832
8833   Py_INCREF (Py_None);
8834   return Py_None;
8835 }
8836
8837 ";
8838
8839   let emit_put_list_function typ =
8840     pr "static PyObject *\n";
8841     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8842     pr "{\n";
8843     pr "  PyObject *list;\n";
8844     pr "  int i;\n";
8845     pr "\n";
8846     pr "  list = PyList_New (%ss->len);\n" typ;
8847     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8848     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8849     pr "  return list;\n";
8850     pr "};\n";
8851     pr "\n"
8852   in
8853
8854   (* Structures, turned into Python dictionaries. *)
8855   List.iter (
8856     fun (typ, cols) ->
8857       pr "static PyObject *\n";
8858       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8859       pr "{\n";
8860       pr "  PyObject *dict;\n";
8861       pr "\n";
8862       pr "  dict = PyDict_New ();\n";
8863       List.iter (
8864         function
8865         | name, FString ->
8866             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8867             pr "                        PyString_FromString (%s->%s));\n"
8868               typ name
8869         | name, FBuffer ->
8870             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8871             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8872               typ name typ name
8873         | name, FUUID ->
8874             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8875             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8876               typ name
8877         | name, (FBytes|FUInt64) ->
8878             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8879             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8880               typ name
8881         | name, FInt64 ->
8882             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8883             pr "                        PyLong_FromLongLong (%s->%s));\n"
8884               typ name
8885         | name, FUInt32 ->
8886             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8887             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8888               typ name
8889         | name, FInt32 ->
8890             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8891             pr "                        PyLong_FromLong (%s->%s));\n"
8892               typ name
8893         | name, FOptPercent ->
8894             pr "  if (%s->%s >= 0)\n" typ name;
8895             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8896             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8897               typ name;
8898             pr "  else {\n";
8899             pr "    Py_INCREF (Py_None);\n";
8900             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8901             pr "  }\n"
8902         | name, FChar ->
8903             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8904             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8905       ) cols;
8906       pr "  return dict;\n";
8907       pr "};\n";
8908       pr "\n";
8909
8910   ) structs;
8911
8912   (* Emit a put_TYPE_list function definition only if that function is used. *)
8913   List.iter (
8914     function
8915     | typ, (RStructListOnly | RStructAndList) ->
8916         (* generate the function for typ *)
8917         emit_put_list_function typ
8918     | typ, _ -> () (* empty *)
8919   ) (rstructs_used_by all_functions);
8920
8921   (* Python wrapper functions. *)
8922   List.iter (
8923     fun (name, style, _, _, _, _, _) ->
8924       pr "static PyObject *\n";
8925       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8926       pr "{\n";
8927
8928       pr "  PyObject *py_g;\n";
8929       pr "  guestfs_h *g;\n";
8930       pr "  PyObject *py_r;\n";
8931
8932       let error_code =
8933         match fst style with
8934         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8935         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8936         | RConstString _ | RConstOptString _ ->
8937             pr "  const char *r;\n"; "NULL"
8938         | RString _ -> pr "  char *r;\n"; "NULL"
8939         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8940         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8941         | RStructList (_, typ) ->
8942             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8943         | RBufferOut _ ->
8944             pr "  char *r;\n";
8945             pr "  size_t size;\n";
8946             "NULL" in
8947
8948       List.iter (
8949         function
8950         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8951             pr "  const char *%s;\n" n
8952         | OptString n -> pr "  const char *%s;\n" n
8953         | StringList n | DeviceList n ->
8954             pr "  PyObject *py_%s;\n" n;
8955             pr "  char **%s;\n" n
8956         | Bool n -> pr "  int %s;\n" n
8957         | Int n -> pr "  int %s;\n" n
8958         | Int64 n -> pr "  long long %s;\n" n
8959       ) (snd style);
8960
8961       pr "\n";
8962
8963       (* Convert the parameters. *)
8964       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8965       List.iter (
8966         function
8967         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8968         | OptString _ -> pr "z"
8969         | StringList _ | DeviceList _ -> pr "O"
8970         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8971         | Int _ -> pr "i"
8972         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8973                              * emulate C's int/long/long long in Python?
8974                              *)
8975       ) (snd style);
8976       pr ":guestfs_%s\",\n" name;
8977       pr "                         &py_g";
8978       List.iter (
8979         function
8980         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8981         | OptString n -> pr ", &%s" n
8982         | StringList n | DeviceList n -> pr ", &py_%s" n
8983         | Bool n -> pr ", &%s" n
8984         | Int n -> pr ", &%s" n
8985         | Int64 n -> pr ", &%s" n
8986       ) (snd style);
8987
8988       pr "))\n";
8989       pr "    return NULL;\n";
8990
8991       pr "  g = get_handle (py_g);\n";
8992       List.iter (
8993         function
8994         | Pathname _ | Device _ | Dev_or_Path _ | String _
8995         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8996         | StringList n | DeviceList n ->
8997             pr "  %s = get_string_list (py_%s);\n" n n;
8998             pr "  if (!%s) return NULL;\n" n
8999       ) (snd style);
9000
9001       pr "\n";
9002
9003       pr "  r = guestfs_%s " name;
9004       generate_c_call_args ~handle:"g" style;
9005       pr ";\n";
9006
9007       List.iter (
9008         function
9009         | Pathname _ | Device _ | Dev_or_Path _ | String _
9010         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9011         | StringList n | DeviceList n ->
9012             pr "  free (%s);\n" n
9013       ) (snd style);
9014
9015       pr "  if (r == %s) {\n" error_code;
9016       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9017       pr "    return NULL;\n";
9018       pr "  }\n";
9019       pr "\n";
9020
9021       (match fst style with
9022        | RErr ->
9023            pr "  Py_INCREF (Py_None);\n";
9024            pr "  py_r = Py_None;\n"
9025        | RInt _
9026        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9027        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9028        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9029        | RConstOptString _ ->
9030            pr "  if (r)\n";
9031            pr "    py_r = PyString_FromString (r);\n";
9032            pr "  else {\n";
9033            pr "    Py_INCREF (Py_None);\n";
9034            pr "    py_r = Py_None;\n";
9035            pr "  }\n"
9036        | RString _ ->
9037            pr "  py_r = PyString_FromString (r);\n";
9038            pr "  free (r);\n"
9039        | RStringList _ ->
9040            pr "  py_r = put_string_list (r);\n";
9041            pr "  free_strings (r);\n"
9042        | RStruct (_, typ) ->
9043            pr "  py_r = put_%s (r);\n" typ;
9044            pr "  guestfs_free_%s (r);\n" typ
9045        | RStructList (_, typ) ->
9046            pr "  py_r = put_%s_list (r);\n" typ;
9047            pr "  guestfs_free_%s_list (r);\n" typ
9048        | RHashtable n ->
9049            pr "  py_r = put_table (r);\n";
9050            pr "  free_strings (r);\n"
9051        | RBufferOut _ ->
9052            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9053            pr "  free (r);\n"
9054       );
9055
9056       pr "  return py_r;\n";
9057       pr "}\n";
9058       pr "\n"
9059   ) all_functions;
9060
9061   (* Table of functions. *)
9062   pr "static PyMethodDef methods[] = {\n";
9063   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9064   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9065   List.iter (
9066     fun (name, _, _, _, _, _, _) ->
9067       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9068         name name
9069   ) all_functions;
9070   pr "  { NULL, NULL, 0, NULL }\n";
9071   pr "};\n";
9072   pr "\n";
9073
9074   (* Init function. *)
9075   pr "\
9076 void
9077 initlibguestfsmod (void)
9078 {
9079   static int initialized = 0;
9080
9081   if (initialized) return;
9082   Py_InitModule ((char *) \"libguestfsmod\", methods);
9083   initialized = 1;
9084 }
9085 "
9086
9087 (* Generate Python module. *)
9088 and generate_python_py () =
9089   generate_header HashStyle LGPLv2plus;
9090
9091   pr "\
9092 u\"\"\"Python bindings for libguestfs
9093
9094 import guestfs
9095 g = guestfs.GuestFS ()
9096 g.add_drive (\"guest.img\")
9097 g.launch ()
9098 parts = g.list_partitions ()
9099
9100 The guestfs module provides a Python binding to the libguestfs API
9101 for examining and modifying virtual machine disk images.
9102
9103 Amongst the things this is good for: making batch configuration
9104 changes to guests, getting disk used/free statistics (see also:
9105 virt-df), migrating between virtualization systems (see also:
9106 virt-p2v), performing partial backups, performing partial guest
9107 clones, cloning guests and changing registry/UUID/hostname info, and
9108 much else besides.
9109
9110 Libguestfs uses Linux kernel and qemu code, and can access any type of
9111 guest filesystem that Linux and qemu can, including but not limited
9112 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9113 schemes, qcow, qcow2, vmdk.
9114
9115 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9116 LVs, what filesystem is in each LV, etc.).  It can also run commands
9117 in the context of the guest.  Also you can access filesystems over
9118 FUSE.
9119
9120 Errors which happen while using the API are turned into Python
9121 RuntimeError exceptions.
9122
9123 To create a guestfs handle you usually have to perform the following
9124 sequence of calls:
9125
9126 # Create the handle, call add_drive at least once, and possibly
9127 # several times if the guest has multiple block devices:
9128 g = guestfs.GuestFS ()
9129 g.add_drive (\"guest.img\")
9130
9131 # Launch the qemu subprocess and wait for it to become ready:
9132 g.launch ()
9133
9134 # Now you can issue commands, for example:
9135 logvols = g.lvs ()
9136
9137 \"\"\"
9138
9139 import libguestfsmod
9140
9141 class GuestFS:
9142     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9143
9144     def __init__ (self):
9145         \"\"\"Create a new libguestfs handle.\"\"\"
9146         self._o = libguestfsmod.create ()
9147
9148     def __del__ (self):
9149         libguestfsmod.close (self._o)
9150
9151 ";
9152
9153   List.iter (
9154     fun (name, style, _, flags, _, _, longdesc) ->
9155       pr "    def %s " name;
9156       generate_py_call_args ~handle:"self" (snd style);
9157       pr ":\n";
9158
9159       if not (List.mem NotInDocs flags) then (
9160         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9161         let doc =
9162           match fst style with
9163           | RErr | RInt _ | RInt64 _ | RBool _
9164           | RConstOptString _ | RConstString _
9165           | RString _ | RBufferOut _ -> doc
9166           | RStringList _ ->
9167               doc ^ "\n\nThis function returns a list of strings."
9168           | RStruct (_, typ) ->
9169               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9170           | RStructList (_, typ) ->
9171               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9172           | RHashtable _ ->
9173               doc ^ "\n\nThis function returns a dictionary." in
9174         let doc =
9175           if List.mem ProtocolLimitWarning flags then
9176             doc ^ "\n\n" ^ protocol_limit_warning
9177           else doc in
9178         let doc =
9179           if List.mem DangerWillRobinson flags then
9180             doc ^ "\n\n" ^ danger_will_robinson
9181           else doc in
9182         let doc =
9183           match deprecation_notice flags with
9184           | None -> doc
9185           | Some txt -> doc ^ "\n\n" ^ txt in
9186         let doc = pod2text ~width:60 name doc in
9187         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9188         let doc = String.concat "\n        " doc in
9189         pr "        u\"\"\"%s\"\"\"\n" doc;
9190       );
9191       pr "        return libguestfsmod.%s " name;
9192       generate_py_call_args ~handle:"self._o" (snd style);
9193       pr "\n";
9194       pr "\n";
9195   ) all_functions
9196
9197 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9198 and generate_py_call_args ~handle args =
9199   pr "(%s" handle;
9200   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9201   pr ")"
9202
9203 (* Useful if you need the longdesc POD text as plain text.  Returns a
9204  * list of lines.
9205  *
9206  * Because this is very slow (the slowest part of autogeneration),
9207  * we memoize the results.
9208  *)
9209 and pod2text ~width name longdesc =
9210   let key = width, name, longdesc in
9211   try Hashtbl.find pod2text_memo key
9212   with Not_found ->
9213     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9214     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9215     close_out chan;
9216     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9217     let chan = open_process_in cmd in
9218     let lines = ref [] in
9219     let rec loop i =
9220       let line = input_line chan in
9221       if i = 1 then             (* discard the first line of output *)
9222         loop (i+1)
9223       else (
9224         let line = triml line in
9225         lines := line :: !lines;
9226         loop (i+1)
9227       ) in
9228     let lines = try loop 1 with End_of_file -> List.rev !lines in
9229     unlink filename;
9230     (match close_process_in chan with
9231      | WEXITED 0 -> ()
9232      | WEXITED i ->
9233          failwithf "pod2text: process exited with non-zero status (%d)" i
9234      | WSIGNALED i | WSTOPPED i ->
9235          failwithf "pod2text: process signalled or stopped by signal %d" i
9236     );
9237     Hashtbl.add pod2text_memo key lines;
9238     pod2text_memo_updated ();
9239     lines
9240
9241 (* Generate ruby bindings. *)
9242 and generate_ruby_c () =
9243   generate_header CStyle LGPLv2plus;
9244
9245   pr "\
9246 #include <stdio.h>
9247 #include <stdlib.h>
9248
9249 #include <ruby.h>
9250
9251 #include \"guestfs.h\"
9252
9253 #include \"extconf.h\"
9254
9255 /* For Ruby < 1.9 */
9256 #ifndef RARRAY_LEN
9257 #define RARRAY_LEN(r) (RARRAY((r))->len)
9258 #endif
9259
9260 static VALUE m_guestfs;                 /* guestfs module */
9261 static VALUE c_guestfs;                 /* guestfs_h handle */
9262 static VALUE e_Error;                   /* used for all errors */
9263
9264 static void ruby_guestfs_free (void *p)
9265 {
9266   if (!p) return;
9267   guestfs_close ((guestfs_h *) p);
9268 }
9269
9270 static VALUE ruby_guestfs_create (VALUE m)
9271 {
9272   guestfs_h *g;
9273
9274   g = guestfs_create ();
9275   if (!g)
9276     rb_raise (e_Error, \"failed to create guestfs handle\");
9277
9278   /* Don't print error messages to stderr by default. */
9279   guestfs_set_error_handler (g, NULL, NULL);
9280
9281   /* Wrap it, and make sure the close function is called when the
9282    * handle goes away.
9283    */
9284   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9285 }
9286
9287 static VALUE ruby_guestfs_close (VALUE gv)
9288 {
9289   guestfs_h *g;
9290   Data_Get_Struct (gv, guestfs_h, g);
9291
9292   ruby_guestfs_free (g);
9293   DATA_PTR (gv) = NULL;
9294
9295   return Qnil;
9296 }
9297
9298 ";
9299
9300   List.iter (
9301     fun (name, style, _, _, _, _, _) ->
9302       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9303       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9304       pr ")\n";
9305       pr "{\n";
9306       pr "  guestfs_h *g;\n";
9307       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9308       pr "  if (!g)\n";
9309       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9310         name;
9311       pr "\n";
9312
9313       List.iter (
9314         function
9315         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9316             pr "  Check_Type (%sv, T_STRING);\n" n;
9317             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9318             pr "  if (!%s)\n" n;
9319             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9320             pr "              \"%s\", \"%s\");\n" n name
9321         | OptString n ->
9322             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9323         | StringList n | DeviceList n ->
9324             pr "  char **%s;\n" n;
9325             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9326             pr "  {\n";
9327             pr "    int i, len;\n";
9328             pr "    len = RARRAY_LEN (%sv);\n" n;
9329             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9330               n;
9331             pr "    for (i = 0; i < len; ++i) {\n";
9332             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9333             pr "      %s[i] = StringValueCStr (v);\n" n;
9334             pr "    }\n";
9335             pr "    %s[len] = NULL;\n" n;
9336             pr "  }\n";
9337         | Bool n ->
9338             pr "  int %s = RTEST (%sv);\n" n n
9339         | Int n ->
9340             pr "  int %s = NUM2INT (%sv);\n" n n
9341         | Int64 n ->
9342             pr "  long long %s = NUM2LL (%sv);\n" n n
9343       ) (snd style);
9344       pr "\n";
9345
9346       let error_code =
9347         match fst style with
9348         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9349         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9350         | RConstString _ | RConstOptString _ ->
9351             pr "  const char *r;\n"; "NULL"
9352         | RString _ -> pr "  char *r;\n"; "NULL"
9353         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9354         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9355         | RStructList (_, typ) ->
9356             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9357         | RBufferOut _ ->
9358             pr "  char *r;\n";
9359             pr "  size_t size;\n";
9360             "NULL" in
9361       pr "\n";
9362
9363       pr "  r = guestfs_%s " name;
9364       generate_c_call_args ~handle:"g" style;
9365       pr ";\n";
9366
9367       List.iter (
9368         function
9369         | Pathname _ | Device _ | Dev_or_Path _ | String _
9370         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9371         | StringList n | DeviceList n ->
9372             pr "  free (%s);\n" n
9373       ) (snd style);
9374
9375       pr "  if (r == %s)\n" error_code;
9376       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9377       pr "\n";
9378
9379       (match fst style with
9380        | RErr ->
9381            pr "  return Qnil;\n"
9382        | RInt _ | RBool _ ->
9383            pr "  return INT2NUM (r);\n"
9384        | RInt64 _ ->
9385            pr "  return ULL2NUM (r);\n"
9386        | RConstString _ ->
9387            pr "  return rb_str_new2 (r);\n";
9388        | RConstOptString _ ->
9389            pr "  if (r)\n";
9390            pr "    return rb_str_new2 (r);\n";
9391            pr "  else\n";
9392            pr "    return Qnil;\n";
9393        | RString _ ->
9394            pr "  VALUE rv = rb_str_new2 (r);\n";
9395            pr "  free (r);\n";
9396            pr "  return rv;\n";
9397        | RStringList _ ->
9398            pr "  int i, len = 0;\n";
9399            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9400            pr "  VALUE rv = rb_ary_new2 (len);\n";
9401            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9402            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9403            pr "    free (r[i]);\n";
9404            pr "  }\n";
9405            pr "  free (r);\n";
9406            pr "  return rv;\n"
9407        | RStruct (_, typ) ->
9408            let cols = cols_of_struct typ in
9409            generate_ruby_struct_code typ cols
9410        | RStructList (_, typ) ->
9411            let cols = cols_of_struct typ in
9412            generate_ruby_struct_list_code typ cols
9413        | RHashtable _ ->
9414            pr "  VALUE rv = rb_hash_new ();\n";
9415            pr "  int i;\n";
9416            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9417            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9418            pr "    free (r[i]);\n";
9419            pr "    free (r[i+1]);\n";
9420            pr "  }\n";
9421            pr "  free (r);\n";
9422            pr "  return rv;\n"
9423        | RBufferOut _ ->
9424            pr "  VALUE rv = rb_str_new (r, size);\n";
9425            pr "  free (r);\n";
9426            pr "  return rv;\n";
9427       );
9428
9429       pr "}\n";
9430       pr "\n"
9431   ) all_functions;
9432
9433   pr "\
9434 /* Initialize the module. */
9435 void Init__guestfs ()
9436 {
9437   m_guestfs = rb_define_module (\"Guestfs\");
9438   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9439   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9440
9441   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9442   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9443
9444 ";
9445   (* Define the rest of the methods. *)
9446   List.iter (
9447     fun (name, style, _, _, _, _, _) ->
9448       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9449       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9450   ) all_functions;
9451
9452   pr "}\n"
9453
9454 (* Ruby code to return a struct. *)
9455 and generate_ruby_struct_code typ cols =
9456   pr "  VALUE rv = rb_hash_new ();\n";
9457   List.iter (
9458     function
9459     | name, FString ->
9460         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9461     | name, FBuffer ->
9462         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9463     | name, FUUID ->
9464         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9465     | name, (FBytes|FUInt64) ->
9466         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9467     | name, FInt64 ->
9468         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9469     | name, FUInt32 ->
9470         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9471     | name, FInt32 ->
9472         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9473     | name, FOptPercent ->
9474         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9475     | name, FChar -> (* XXX wrong? *)
9476         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9477   ) cols;
9478   pr "  guestfs_free_%s (r);\n" typ;
9479   pr "  return rv;\n"
9480
9481 (* Ruby code to return a struct list. *)
9482 and generate_ruby_struct_list_code typ cols =
9483   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9484   pr "  int i;\n";
9485   pr "  for (i = 0; i < r->len; ++i) {\n";
9486   pr "    VALUE hv = rb_hash_new ();\n";
9487   List.iter (
9488     function
9489     | name, FString ->
9490         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9491     | name, FBuffer ->
9492         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
9493     | name, FUUID ->
9494         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9495     | name, (FBytes|FUInt64) ->
9496         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9497     | name, FInt64 ->
9498         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9499     | name, FUInt32 ->
9500         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9501     | name, FInt32 ->
9502         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9503     | name, FOptPercent ->
9504         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9505     | name, FChar -> (* XXX wrong? *)
9506         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9507   ) cols;
9508   pr "    rb_ary_push (rv, hv);\n";
9509   pr "  }\n";
9510   pr "  guestfs_free_%s_list (r);\n" typ;
9511   pr "  return rv;\n"
9512
9513 (* Generate Java bindings GuestFS.java file. *)
9514 and generate_java_java () =
9515   generate_header CStyle LGPLv2plus;
9516
9517   pr "\
9518 package com.redhat.et.libguestfs;
9519
9520 import java.util.HashMap;
9521 import com.redhat.et.libguestfs.LibGuestFSException;
9522 import com.redhat.et.libguestfs.PV;
9523 import com.redhat.et.libguestfs.VG;
9524 import com.redhat.et.libguestfs.LV;
9525 import com.redhat.et.libguestfs.Stat;
9526 import com.redhat.et.libguestfs.StatVFS;
9527 import com.redhat.et.libguestfs.IntBool;
9528 import com.redhat.et.libguestfs.Dirent;
9529
9530 /**
9531  * The GuestFS object is a libguestfs handle.
9532  *
9533  * @author rjones
9534  */
9535 public class GuestFS {
9536   // Load the native code.
9537   static {
9538     System.loadLibrary (\"guestfs_jni\");
9539   }
9540
9541   /**
9542    * The native guestfs_h pointer.
9543    */
9544   long g;
9545
9546   /**
9547    * Create a libguestfs handle.
9548    *
9549    * @throws LibGuestFSException
9550    */
9551   public GuestFS () throws LibGuestFSException
9552   {
9553     g = _create ();
9554   }
9555   private native long _create () throws LibGuestFSException;
9556
9557   /**
9558    * Close a libguestfs handle.
9559    *
9560    * You can also leave handles to be collected by the garbage
9561    * collector, but this method ensures that the resources used
9562    * by the handle are freed up immediately.  If you call any
9563    * other methods after closing the handle, you will get an
9564    * exception.
9565    *
9566    * @throws LibGuestFSException
9567    */
9568   public void close () throws LibGuestFSException
9569   {
9570     if (g != 0)
9571       _close (g);
9572     g = 0;
9573   }
9574   private native void _close (long g) throws LibGuestFSException;
9575
9576   public void finalize () throws LibGuestFSException
9577   {
9578     close ();
9579   }
9580
9581 ";
9582
9583   List.iter (
9584     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9585       if not (List.mem NotInDocs flags); then (
9586         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9587         let doc =
9588           if List.mem ProtocolLimitWarning flags then
9589             doc ^ "\n\n" ^ protocol_limit_warning
9590           else doc in
9591         let doc =
9592           if List.mem DangerWillRobinson flags then
9593             doc ^ "\n\n" ^ danger_will_robinson
9594           else doc in
9595         let doc =
9596           match deprecation_notice flags with
9597           | None -> doc
9598           | Some txt -> doc ^ "\n\n" ^ txt in
9599         let doc = pod2text ~width:60 name doc in
9600         let doc = List.map (            (* RHBZ#501883 *)
9601           function
9602           | "" -> "<p>"
9603           | nonempty -> nonempty
9604         ) doc in
9605         let doc = String.concat "\n   * " doc in
9606
9607         pr "  /**\n";
9608         pr "   * %s\n" shortdesc;
9609         pr "   * <p>\n";
9610         pr "   * %s\n" doc;
9611         pr "   * @throws LibGuestFSException\n";
9612         pr "   */\n";
9613         pr "  ";
9614       );
9615       generate_java_prototype ~public:true ~semicolon:false name style;
9616       pr "\n";
9617       pr "  {\n";
9618       pr "    if (g == 0)\n";
9619       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9620         name;
9621       pr "    ";
9622       if fst style <> RErr then pr "return ";
9623       pr "_%s " name;
9624       generate_java_call_args ~handle:"g" (snd style);
9625       pr ";\n";
9626       pr "  }\n";
9627       pr "  ";
9628       generate_java_prototype ~privat:true ~native:true name style;
9629       pr "\n";
9630       pr "\n";
9631   ) all_functions;
9632
9633   pr "}\n"
9634
9635 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9636 and generate_java_call_args ~handle args =
9637   pr "(%s" handle;
9638   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9639   pr ")"
9640
9641 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9642     ?(semicolon=true) name style =
9643   if privat then pr "private ";
9644   if public then pr "public ";
9645   if native then pr "native ";
9646
9647   (* return type *)
9648   (match fst style with
9649    | RErr -> pr "void ";
9650    | RInt _ -> pr "int ";
9651    | RInt64 _ -> pr "long ";
9652    | RBool _ -> pr "boolean ";
9653    | RConstString _ | RConstOptString _ | RString _
9654    | RBufferOut _ -> pr "String ";
9655    | RStringList _ -> pr "String[] ";
9656    | RStruct (_, typ) ->
9657        let name = java_name_of_struct typ in
9658        pr "%s " name;
9659    | RStructList (_, typ) ->
9660        let name = java_name_of_struct typ in
9661        pr "%s[] " name;
9662    | RHashtable _ -> pr "HashMap<String,String> ";
9663   );
9664
9665   if native then pr "_%s " name else pr "%s " name;
9666   pr "(";
9667   let needs_comma = ref false in
9668   if native then (
9669     pr "long g";
9670     needs_comma := true
9671   );
9672
9673   (* args *)
9674   List.iter (
9675     fun arg ->
9676       if !needs_comma then pr ", ";
9677       needs_comma := true;
9678
9679       match arg with
9680       | Pathname n
9681       | Device n | Dev_or_Path n
9682       | String n
9683       | OptString n
9684       | FileIn n
9685       | FileOut n ->
9686           pr "String %s" n
9687       | StringList n | DeviceList n ->
9688           pr "String[] %s" n
9689       | Bool n ->
9690           pr "boolean %s" n
9691       | Int n ->
9692           pr "int %s" n
9693       | Int64 n ->
9694           pr "long %s" n
9695   ) (snd style);
9696
9697   pr ")\n";
9698   pr "    throws LibGuestFSException";
9699   if semicolon then pr ";"
9700
9701 and generate_java_struct jtyp cols () =
9702   generate_header CStyle LGPLv2plus;
9703
9704   pr "\
9705 package com.redhat.et.libguestfs;
9706
9707 /**
9708  * Libguestfs %s structure.
9709  *
9710  * @author rjones
9711  * @see GuestFS
9712  */
9713 public class %s {
9714 " jtyp jtyp;
9715
9716   List.iter (
9717     function
9718     | name, FString
9719     | name, FUUID
9720     | name, FBuffer -> pr "  public String %s;\n" name
9721     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9722     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9723     | name, FChar -> pr "  public char %s;\n" name
9724     | name, FOptPercent ->
9725         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9726         pr "  public float %s;\n" name
9727   ) cols;
9728
9729   pr "}\n"
9730
9731 and generate_java_c () =
9732   generate_header CStyle LGPLv2plus;
9733
9734   pr "\
9735 #include <stdio.h>
9736 #include <stdlib.h>
9737 #include <string.h>
9738
9739 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9740 #include \"guestfs.h\"
9741
9742 /* Note that this function returns.  The exception is not thrown
9743  * until after the wrapper function returns.
9744  */
9745 static void
9746 throw_exception (JNIEnv *env, const char *msg)
9747 {
9748   jclass cl;
9749   cl = (*env)->FindClass (env,
9750                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9751   (*env)->ThrowNew (env, cl, msg);
9752 }
9753
9754 JNIEXPORT jlong JNICALL
9755 Java_com_redhat_et_libguestfs_GuestFS__1create
9756   (JNIEnv *env, jobject obj)
9757 {
9758   guestfs_h *g;
9759
9760   g = guestfs_create ();
9761   if (g == NULL) {
9762     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9763     return 0;
9764   }
9765   guestfs_set_error_handler (g, NULL, NULL);
9766   return (jlong) (long) g;
9767 }
9768
9769 JNIEXPORT void JNICALL
9770 Java_com_redhat_et_libguestfs_GuestFS__1close
9771   (JNIEnv *env, jobject obj, jlong jg)
9772 {
9773   guestfs_h *g = (guestfs_h *) (long) jg;
9774   guestfs_close (g);
9775 }
9776
9777 ";
9778
9779   List.iter (
9780     fun (name, style, _, _, _, _, _) ->
9781       pr "JNIEXPORT ";
9782       (match fst style with
9783        | RErr -> pr "void ";
9784        | RInt _ -> pr "jint ";
9785        | RInt64 _ -> pr "jlong ";
9786        | RBool _ -> pr "jboolean ";
9787        | RConstString _ | RConstOptString _ | RString _
9788        | RBufferOut _ -> pr "jstring ";
9789        | RStruct _ | RHashtable _ ->
9790            pr "jobject ";
9791        | RStringList _ | RStructList _ ->
9792            pr "jobjectArray ";
9793       );
9794       pr "JNICALL\n";
9795       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9796       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9797       pr "\n";
9798       pr "  (JNIEnv *env, jobject obj, jlong jg";
9799       List.iter (
9800         function
9801         | Pathname n
9802         | Device n | Dev_or_Path n
9803         | String n
9804         | OptString n
9805         | FileIn n
9806         | FileOut n ->
9807             pr ", jstring j%s" n
9808         | StringList n | DeviceList n ->
9809             pr ", jobjectArray j%s" n
9810         | Bool n ->
9811             pr ", jboolean j%s" n
9812         | Int n ->
9813             pr ", jint j%s" n
9814         | Int64 n ->
9815             pr ", jlong j%s" n
9816       ) (snd style);
9817       pr ")\n";
9818       pr "{\n";
9819       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9820       let error_code, no_ret =
9821         match fst style with
9822         | RErr -> pr "  int r;\n"; "-1", ""
9823         | RBool _
9824         | RInt _ -> pr "  int r;\n"; "-1", "0"
9825         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9826         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9827         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9828         | RString _ ->
9829             pr "  jstring jr;\n";
9830             pr "  char *r;\n"; "NULL", "NULL"
9831         | RStringList _ ->
9832             pr "  jobjectArray jr;\n";
9833             pr "  int r_len;\n";
9834             pr "  jclass cl;\n";
9835             pr "  jstring jstr;\n";
9836             pr "  char **r;\n"; "NULL", "NULL"
9837         | RStruct (_, typ) ->
9838             pr "  jobject jr;\n";
9839             pr "  jclass cl;\n";
9840             pr "  jfieldID fl;\n";
9841             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9842         | RStructList (_, typ) ->
9843             pr "  jobjectArray jr;\n";
9844             pr "  jclass cl;\n";
9845             pr "  jfieldID fl;\n";
9846             pr "  jobject jfl;\n";
9847             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9848         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9849         | RBufferOut _ ->
9850             pr "  jstring jr;\n";
9851             pr "  char *r;\n";
9852             pr "  size_t size;\n";
9853             "NULL", "NULL" in
9854       List.iter (
9855         function
9856         | Pathname n
9857         | Device n | Dev_or_Path n
9858         | String n
9859         | OptString n
9860         | FileIn n
9861         | FileOut n ->
9862             pr "  const char *%s;\n" n
9863         | StringList n | DeviceList n ->
9864             pr "  int %s_len;\n" n;
9865             pr "  const char **%s;\n" n
9866         | Bool n
9867         | Int n ->
9868             pr "  int %s;\n" n
9869         | Int64 n ->
9870             pr "  int64_t %s;\n" n
9871       ) (snd style);
9872
9873       let needs_i =
9874         (match fst style with
9875          | RStringList _ | RStructList _ -> true
9876          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9877          | RConstOptString _
9878          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9879           List.exists (function
9880                        | StringList _ -> true
9881                        | DeviceList _ -> true
9882                        | _ -> false) (snd style) in
9883       if needs_i then
9884         pr "  int i;\n";
9885
9886       pr "\n";
9887
9888       (* Get the parameters. *)
9889       List.iter (
9890         function
9891         | Pathname n
9892         | Device n | Dev_or_Path n
9893         | String n
9894         | FileIn n
9895         | FileOut n ->
9896             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9897         | OptString n ->
9898             (* This is completely undocumented, but Java null becomes
9899              * a NULL parameter.
9900              *)
9901             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9902         | StringList n | DeviceList n ->
9903             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9904             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9905             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9906             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9907               n;
9908             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9909             pr "  }\n";
9910             pr "  %s[%s_len] = NULL;\n" n n;
9911         | Bool n
9912         | Int n
9913         | Int64 n ->
9914             pr "  %s = j%s;\n" n n
9915       ) (snd style);
9916
9917       (* Make the call. *)
9918       pr "  r = guestfs_%s " name;
9919       generate_c_call_args ~handle:"g" style;
9920       pr ";\n";
9921
9922       (* Release the parameters. *)
9923       List.iter (
9924         function
9925         | Pathname n
9926         | Device n | Dev_or_Path n
9927         | String n
9928         | FileIn n
9929         | FileOut n ->
9930             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9931         | OptString n ->
9932             pr "  if (j%s)\n" n;
9933             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9934         | StringList n | DeviceList n ->
9935             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9936             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9937               n;
9938             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9939             pr "  }\n";
9940             pr "  free (%s);\n" n
9941         | Bool n
9942         | Int n
9943         | Int64 n -> ()
9944       ) (snd style);
9945
9946       (* Check for errors. *)
9947       pr "  if (r == %s) {\n" error_code;
9948       pr "    throw_exception (env, guestfs_last_error (g));\n";
9949       pr "    return %s;\n" no_ret;
9950       pr "  }\n";
9951
9952       (* Return value. *)
9953       (match fst style with
9954        | RErr -> ()
9955        | RInt _ -> pr "  return (jint) r;\n"
9956        | RBool _ -> pr "  return (jboolean) r;\n"
9957        | RInt64 _ -> pr "  return (jlong) r;\n"
9958        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9959        | RConstOptString _ ->
9960            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9961        | RString _ ->
9962            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9963            pr "  free (r);\n";
9964            pr "  return jr;\n"
9965        | RStringList _ ->
9966            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9967            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9968            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9969            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9970            pr "  for (i = 0; i < r_len; ++i) {\n";
9971            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9972            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9973            pr "    free (r[i]);\n";
9974            pr "  }\n";
9975            pr "  free (r);\n";
9976            pr "  return jr;\n"
9977        | RStruct (_, typ) ->
9978            let jtyp = java_name_of_struct typ in
9979            let cols = cols_of_struct typ in
9980            generate_java_struct_return typ jtyp cols
9981        | RStructList (_, typ) ->
9982            let jtyp = java_name_of_struct typ in
9983            let cols = cols_of_struct typ in
9984            generate_java_struct_list_return typ jtyp cols
9985        | RHashtable _ ->
9986            (* XXX *)
9987            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9988            pr "  return NULL;\n"
9989        | RBufferOut _ ->
9990            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9991            pr "  free (r);\n";
9992            pr "  return jr;\n"
9993       );
9994
9995       pr "}\n";
9996       pr "\n"
9997   ) all_functions
9998
9999 and generate_java_struct_return typ jtyp cols =
10000   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10001   pr "  jr = (*env)->AllocObject (env, cl);\n";
10002   List.iter (
10003     function
10004     | name, FString ->
10005         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10006         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10007     | name, FUUID ->
10008         pr "  {\n";
10009         pr "    char s[33];\n";
10010         pr "    memcpy (s, r->%s, 32);\n" name;
10011         pr "    s[32] = 0;\n";
10012         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10013         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10014         pr "  }\n";
10015     | name, FBuffer ->
10016         pr "  {\n";
10017         pr "    int len = r->%s_len;\n" name;
10018         pr "    char s[len+1];\n";
10019         pr "    memcpy (s, r->%s, len);\n" name;
10020         pr "    s[len] = 0;\n";
10021         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10022         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10023         pr "  }\n";
10024     | name, (FBytes|FUInt64|FInt64) ->
10025         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10026         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10027     | name, (FUInt32|FInt32) ->
10028         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10029         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10030     | name, FOptPercent ->
10031         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10032         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10033     | name, FChar ->
10034         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10035         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10036   ) cols;
10037   pr "  free (r);\n";
10038   pr "  return jr;\n"
10039
10040 and generate_java_struct_list_return typ jtyp cols =
10041   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10042   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10043   pr "  for (i = 0; i < r->len; ++i) {\n";
10044   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10045   List.iter (
10046     function
10047     | name, FString ->
10048         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10049         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10050     | name, FUUID ->
10051         pr "    {\n";
10052         pr "      char s[33];\n";
10053         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10054         pr "      s[32] = 0;\n";
10055         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10056         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10057         pr "    }\n";
10058     | name, FBuffer ->
10059         pr "    {\n";
10060         pr "      int len = r->val[i].%s_len;\n" name;
10061         pr "      char s[len+1];\n";
10062         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10063         pr "      s[len] = 0;\n";
10064         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10065         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10066         pr "    }\n";
10067     | name, (FBytes|FUInt64|FInt64) ->
10068         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10069         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10070     | name, (FUInt32|FInt32) ->
10071         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10072         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10073     | name, FOptPercent ->
10074         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10075         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10076     | name, FChar ->
10077         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10078         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10079   ) cols;
10080   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10081   pr "  }\n";
10082   pr "  guestfs_free_%s_list (r);\n" typ;
10083   pr "  return jr;\n"
10084
10085 and generate_java_makefile_inc () =
10086   generate_header HashStyle GPLv2plus;
10087
10088   pr "java_built_sources = \\\n";
10089   List.iter (
10090     fun (typ, jtyp) ->
10091         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10092   ) java_structs;
10093   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10094
10095 and generate_haskell_hs () =
10096   generate_header HaskellStyle LGPLv2plus;
10097
10098   (* XXX We only know how to generate partial FFI for Haskell
10099    * at the moment.  Please help out!
10100    *)
10101   let can_generate style =
10102     match style with
10103     | RErr, _
10104     | RInt _, _
10105     | RInt64 _, _ -> true
10106     | RBool _, _
10107     | RConstString _, _
10108     | RConstOptString _, _
10109     | RString _, _
10110     | RStringList _, _
10111     | RStruct _, _
10112     | RStructList _, _
10113     | RHashtable _, _
10114     | RBufferOut _, _ -> false in
10115
10116   pr "\
10117 {-# INCLUDE <guestfs.h> #-}
10118 {-# LANGUAGE ForeignFunctionInterface #-}
10119
10120 module Guestfs (
10121   create";
10122
10123   (* List out the names of the actions we want to export. *)
10124   List.iter (
10125     fun (name, style, _, _, _, _, _) ->
10126       if can_generate style then pr ",\n  %s" name
10127   ) all_functions;
10128
10129   pr "
10130   ) where
10131
10132 -- Unfortunately some symbols duplicate ones already present
10133 -- in Prelude.  We don't know which, so we hard-code a list
10134 -- here.
10135 import Prelude hiding (truncate)
10136
10137 import Foreign
10138 import Foreign.C
10139 import Foreign.C.Types
10140 import IO
10141 import Control.Exception
10142 import Data.Typeable
10143
10144 data GuestfsS = GuestfsS            -- represents the opaque C struct
10145 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10146 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10147
10148 -- XXX define properly later XXX
10149 data PV = PV
10150 data VG = VG
10151 data LV = LV
10152 data IntBool = IntBool
10153 data Stat = Stat
10154 data StatVFS = StatVFS
10155 data Hashtable = Hashtable
10156
10157 foreign import ccall unsafe \"guestfs_create\" c_create
10158   :: IO GuestfsP
10159 foreign import ccall unsafe \"&guestfs_close\" c_close
10160   :: FunPtr (GuestfsP -> IO ())
10161 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10162   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10163
10164 create :: IO GuestfsH
10165 create = do
10166   p <- c_create
10167   c_set_error_handler p nullPtr nullPtr
10168   h <- newForeignPtr c_close p
10169   return h
10170
10171 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10172   :: GuestfsP -> IO CString
10173
10174 -- last_error :: GuestfsH -> IO (Maybe String)
10175 -- last_error h = do
10176 --   str <- withForeignPtr h (\\p -> c_last_error p)
10177 --   maybePeek peekCString str
10178
10179 last_error :: GuestfsH -> IO (String)
10180 last_error h = do
10181   str <- withForeignPtr h (\\p -> c_last_error p)
10182   if (str == nullPtr)
10183     then return \"no error\"
10184     else peekCString str
10185
10186 ";
10187
10188   (* Generate wrappers for each foreign function. *)
10189   List.iter (
10190     fun (name, style, _, _, _, _, _) ->
10191       if can_generate style then (
10192         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10193         pr "  :: ";
10194         generate_haskell_prototype ~handle:"GuestfsP" style;
10195         pr "\n";
10196         pr "\n";
10197         pr "%s :: " name;
10198         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10199         pr "\n";
10200         pr "%s %s = do\n" name
10201           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10202         pr "  r <- ";
10203         (* Convert pointer arguments using with* functions. *)
10204         List.iter (
10205           function
10206           | FileIn n
10207           | FileOut n
10208           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10209           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10210           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10211           | Bool _ | Int _ | Int64 _ -> ()
10212         ) (snd style);
10213         (* Convert integer arguments. *)
10214         let args =
10215           List.map (
10216             function
10217             | Bool n -> sprintf "(fromBool %s)" n
10218             | Int n -> sprintf "(fromIntegral %s)" n
10219             | Int64 n -> sprintf "(fromIntegral %s)" n
10220             | FileIn n | FileOut n
10221             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10222           ) (snd style) in
10223         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10224           (String.concat " " ("p" :: args));
10225         (match fst style with
10226          | RErr | RInt _ | RInt64 _ | RBool _ ->
10227              pr "  if (r == -1)\n";
10228              pr "    then do\n";
10229              pr "      err <- last_error h\n";
10230              pr "      fail err\n";
10231          | RConstString _ | RConstOptString _ | RString _
10232          | RStringList _ | RStruct _
10233          | RStructList _ | RHashtable _ | RBufferOut _ ->
10234              pr "  if (r == nullPtr)\n";
10235              pr "    then do\n";
10236              pr "      err <- last_error h\n";
10237              pr "      fail err\n";
10238         );
10239         (match fst style with
10240          | RErr ->
10241              pr "    else return ()\n"
10242          | RInt _ ->
10243              pr "    else return (fromIntegral r)\n"
10244          | RInt64 _ ->
10245              pr "    else return (fromIntegral r)\n"
10246          | RBool _ ->
10247              pr "    else return (toBool r)\n"
10248          | RConstString _
10249          | RConstOptString _
10250          | RString _
10251          | RStringList _
10252          | RStruct _
10253          | RStructList _
10254          | RHashtable _
10255          | RBufferOut _ ->
10256              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10257         );
10258         pr "\n";
10259       )
10260   ) all_functions
10261
10262 and generate_haskell_prototype ~handle ?(hs = false) style =
10263   pr "%s -> " handle;
10264   let string = if hs then "String" else "CString" in
10265   let int = if hs then "Int" else "CInt" in
10266   let bool = if hs then "Bool" else "CInt" in
10267   let int64 = if hs then "Integer" else "Int64" in
10268   List.iter (
10269     fun arg ->
10270       (match arg with
10271        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10272        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10273        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10274        | Bool _ -> pr "%s" bool
10275        | Int _ -> pr "%s" int
10276        | Int64 _ -> pr "%s" int
10277        | FileIn _ -> pr "%s" string
10278        | FileOut _ -> pr "%s" string
10279       );
10280       pr " -> ";
10281   ) (snd style);
10282   pr "IO (";
10283   (match fst style with
10284    | RErr -> if not hs then pr "CInt"
10285    | RInt _ -> pr "%s" int
10286    | RInt64 _ -> pr "%s" int64
10287    | RBool _ -> pr "%s" bool
10288    | RConstString _ -> pr "%s" string
10289    | RConstOptString _ -> pr "Maybe %s" string
10290    | RString _ -> pr "%s" string
10291    | RStringList _ -> pr "[%s]" string
10292    | RStruct (_, typ) ->
10293        let name = java_name_of_struct typ in
10294        pr "%s" name
10295    | RStructList (_, typ) ->
10296        let name = java_name_of_struct typ in
10297        pr "[%s]" name
10298    | RHashtable _ -> pr "Hashtable"
10299    | RBufferOut _ -> pr "%s" string
10300   );
10301   pr ")"
10302
10303 and generate_csharp () =
10304   generate_header CPlusPlusStyle LGPLv2plus;
10305
10306   (* XXX Make this configurable by the C# assembly users. *)
10307   let library = "libguestfs.so.0" in
10308
10309   pr "\
10310 // These C# bindings are highly experimental at present.
10311 //
10312 // Firstly they only work on Linux (ie. Mono).  In order to get them
10313 // to work on Windows (ie. .Net) you would need to port the library
10314 // itself to Windows first.
10315 //
10316 // The second issue is that some calls are known to be incorrect and
10317 // can cause Mono to segfault.  Particularly: calls which pass or
10318 // return string[], or return any structure value.  This is because
10319 // we haven't worked out the correct way to do this from C#.
10320 //
10321 // The third issue is that when compiling you get a lot of warnings.
10322 // We are not sure whether the warnings are important or not.
10323 //
10324 // Fourthly we do not routinely build or test these bindings as part
10325 // of the make && make check cycle, which means that regressions might
10326 // go unnoticed.
10327 //
10328 // Suggestions and patches are welcome.
10329
10330 // To compile:
10331 //
10332 // gmcs Libguestfs.cs
10333 // mono Libguestfs.exe
10334 //
10335 // (You'll probably want to add a Test class / static main function
10336 // otherwise this won't do anything useful).
10337
10338 using System;
10339 using System.IO;
10340 using System.Runtime.InteropServices;
10341 using System.Runtime.Serialization;
10342 using System.Collections;
10343
10344 namespace Guestfs
10345 {
10346   class Error : System.ApplicationException
10347   {
10348     public Error (string message) : base (message) {}
10349     protected Error (SerializationInfo info, StreamingContext context) {}
10350   }
10351
10352   class Guestfs
10353   {
10354     IntPtr _handle;
10355
10356     [DllImport (\"%s\")]
10357     static extern IntPtr guestfs_create ();
10358
10359     public Guestfs ()
10360     {
10361       _handle = guestfs_create ();
10362       if (_handle == IntPtr.Zero)
10363         throw new Error (\"could not create guestfs handle\");
10364     }
10365
10366     [DllImport (\"%s\")]
10367     static extern void guestfs_close (IntPtr h);
10368
10369     ~Guestfs ()
10370     {
10371       guestfs_close (_handle);
10372     }
10373
10374     [DllImport (\"%s\")]
10375     static extern string guestfs_last_error (IntPtr h);
10376
10377 " library library library;
10378
10379   (* Generate C# structure bindings.  We prefix struct names with
10380    * underscore because C# cannot have conflicting struct names and
10381    * method names (eg. "class stat" and "stat").
10382    *)
10383   List.iter (
10384     fun (typ, cols) ->
10385       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10386       pr "    public class _%s {\n" typ;
10387       List.iter (
10388         function
10389         | name, FChar -> pr "      char %s;\n" name
10390         | name, FString -> pr "      string %s;\n" name
10391         | name, FBuffer ->
10392             pr "      uint %s_len;\n" name;
10393             pr "      string %s;\n" name
10394         | name, FUUID ->
10395             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10396             pr "      string %s;\n" name
10397         | name, FUInt32 -> pr "      uint %s;\n" name
10398         | name, FInt32 -> pr "      int %s;\n" name
10399         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10400         | name, FInt64 -> pr "      long %s;\n" name
10401         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10402       ) cols;
10403       pr "    }\n";
10404       pr "\n"
10405   ) structs;
10406
10407   (* Generate C# function bindings. *)
10408   List.iter (
10409     fun (name, style, _, _, _, shortdesc, _) ->
10410       let rec csharp_return_type () =
10411         match fst style with
10412         | RErr -> "void"
10413         | RBool n -> "bool"
10414         | RInt n -> "int"
10415         | RInt64 n -> "long"
10416         | RConstString n
10417         | RConstOptString n
10418         | RString n
10419         | RBufferOut n -> "string"
10420         | RStruct (_,n) -> "_" ^ n
10421         | RHashtable n -> "Hashtable"
10422         | RStringList n -> "string[]"
10423         | RStructList (_,n) -> sprintf "_%s[]" n
10424
10425       and c_return_type () =
10426         match fst style with
10427         | RErr
10428         | RBool _
10429         | RInt _ -> "int"
10430         | RInt64 _ -> "long"
10431         | RConstString _
10432         | RConstOptString _
10433         | RString _
10434         | RBufferOut _ -> "string"
10435         | RStruct (_,n) -> "_" ^ n
10436         | RHashtable _
10437         | RStringList _ -> "string[]"
10438         | RStructList (_,n) -> sprintf "_%s[]" n
10439
10440       and c_error_comparison () =
10441         match fst style with
10442         | RErr
10443         | RBool _
10444         | RInt _
10445         | RInt64 _ -> "== -1"
10446         | RConstString _
10447         | RConstOptString _
10448         | RString _
10449         | RBufferOut _
10450         | RStruct (_,_)
10451         | RHashtable _
10452         | RStringList _
10453         | RStructList (_,_) -> "== null"
10454
10455       and generate_extern_prototype () =
10456         pr "    static extern %s guestfs_%s (IntPtr h"
10457           (c_return_type ()) name;
10458         List.iter (
10459           function
10460           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10461           | FileIn n | FileOut n ->
10462               pr ", [In] string %s" n
10463           | StringList n | DeviceList n ->
10464               pr ", [In] string[] %s" n
10465           | Bool n ->
10466               pr ", bool %s" n
10467           | Int n ->
10468               pr ", int %s" n
10469           | Int64 n ->
10470               pr ", long %s" n
10471         ) (snd style);
10472         pr ");\n"
10473
10474       and generate_public_prototype () =
10475         pr "    public %s %s (" (csharp_return_type ()) name;
10476         let comma = ref false in
10477         let next () =
10478           if !comma then pr ", ";
10479           comma := true
10480         in
10481         List.iter (
10482           function
10483           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10484           | FileIn n | FileOut n ->
10485               next (); pr "string %s" n
10486           | StringList n | DeviceList n ->
10487               next (); pr "string[] %s" n
10488           | Bool n ->
10489               next (); pr "bool %s" n
10490           | Int n ->
10491               next (); pr "int %s" n
10492           | Int64 n ->
10493               next (); pr "long %s" n
10494         ) (snd style);
10495         pr ")\n"
10496
10497       and generate_call () =
10498         pr "guestfs_%s (_handle" name;
10499         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10500         pr ");\n";
10501       in
10502
10503       pr "    [DllImport (\"%s\")]\n" library;
10504       generate_extern_prototype ();
10505       pr "\n";
10506       pr "    /// <summary>\n";
10507       pr "    /// %s\n" shortdesc;
10508       pr "    /// </summary>\n";
10509       generate_public_prototype ();
10510       pr "    {\n";
10511       pr "      %s r;\n" (c_return_type ());
10512       pr "      r = ";
10513       generate_call ();
10514       pr "      if (r %s)\n" (c_error_comparison ());
10515       pr "        throw new Error (guestfs_last_error (_handle));\n";
10516       (match fst style with
10517        | RErr -> ()
10518        | RBool _ ->
10519            pr "      return r != 0 ? true : false;\n"
10520        | RHashtable _ ->
10521            pr "      Hashtable rr = new Hashtable ();\n";
10522            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10523            pr "        rr.Add (r[i], r[i+1]);\n";
10524            pr "      return rr;\n"
10525        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10526        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10527        | RStructList _ ->
10528            pr "      return r;\n"
10529       );
10530       pr "    }\n";
10531       pr "\n";
10532   ) all_functions_sorted;
10533
10534   pr "  }
10535 }
10536 "
10537
10538 and generate_bindtests () =
10539   generate_header CStyle LGPLv2plus;
10540
10541   pr "\
10542 #include <stdio.h>
10543 #include <stdlib.h>
10544 #include <inttypes.h>
10545 #include <string.h>
10546
10547 #include \"guestfs.h\"
10548 #include \"guestfs-internal.h\"
10549 #include \"guestfs-internal-actions.h\"
10550 #include \"guestfs_protocol.h\"
10551
10552 #define error guestfs_error
10553 #define safe_calloc guestfs_safe_calloc
10554 #define safe_malloc guestfs_safe_malloc
10555
10556 static void
10557 print_strings (char *const *argv)
10558 {
10559   int argc;
10560
10561   printf (\"[\");
10562   for (argc = 0; argv[argc] != NULL; ++argc) {
10563     if (argc > 0) printf (\", \");
10564     printf (\"\\\"%%s\\\"\", argv[argc]);
10565   }
10566   printf (\"]\\n\");
10567 }
10568
10569 /* The test0 function prints its parameters to stdout. */
10570 ";
10571
10572   let test0, tests =
10573     match test_functions with
10574     | [] -> assert false
10575     | test0 :: tests -> test0, tests in
10576
10577   let () =
10578     let (name, style, _, _, _, _, _) = test0 in
10579     generate_prototype ~extern:false ~semicolon:false ~newline:true
10580       ~handle:"g" ~prefix:"guestfs__" name style;
10581     pr "{\n";
10582     List.iter (
10583       function
10584       | Pathname n
10585       | Device n | Dev_or_Path n
10586       | String n
10587       | FileIn n
10588       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10589       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10590       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10591       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10592       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10593       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10594     ) (snd style);
10595     pr "  /* Java changes stdout line buffering so we need this: */\n";
10596     pr "  fflush (stdout);\n";
10597     pr "  return 0;\n";
10598     pr "}\n";
10599     pr "\n" in
10600
10601   List.iter (
10602     fun (name, style, _, _, _, _, _) ->
10603       if String.sub name (String.length name - 3) 3 <> "err" then (
10604         pr "/* Test normal return. */\n";
10605         generate_prototype ~extern:false ~semicolon:false ~newline:true
10606           ~handle:"g" ~prefix:"guestfs__" name style;
10607         pr "{\n";
10608         (match fst style with
10609          | RErr ->
10610              pr "  return 0;\n"
10611          | RInt _ ->
10612              pr "  int r;\n";
10613              pr "  sscanf (val, \"%%d\", &r);\n";
10614              pr "  return r;\n"
10615          | RInt64 _ ->
10616              pr "  int64_t r;\n";
10617              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10618              pr "  return r;\n"
10619          | RBool _ ->
10620              pr "  return STREQ (val, \"true\");\n"
10621          | RConstString _
10622          | RConstOptString _ ->
10623              (* Can't return the input string here.  Return a static
10624               * string so we ensure we get a segfault if the caller
10625               * tries to free it.
10626               *)
10627              pr "  return \"static string\";\n"
10628          | RString _ ->
10629              pr "  return strdup (val);\n"
10630          | RStringList _ ->
10631              pr "  char **strs;\n";
10632              pr "  int n, i;\n";
10633              pr "  sscanf (val, \"%%d\", &n);\n";
10634              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10635              pr "  for (i = 0; i < n; ++i) {\n";
10636              pr "    strs[i] = safe_malloc (g, 16);\n";
10637              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10638              pr "  }\n";
10639              pr "  strs[n] = NULL;\n";
10640              pr "  return strs;\n"
10641          | RStruct (_, typ) ->
10642              pr "  struct guestfs_%s *r;\n" typ;
10643              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10644              pr "  return r;\n"
10645          | RStructList (_, typ) ->
10646              pr "  struct guestfs_%s_list *r;\n" typ;
10647              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10648              pr "  sscanf (val, \"%%d\", &r->len);\n";
10649              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10650              pr "  return r;\n"
10651          | RHashtable _ ->
10652              pr "  char **strs;\n";
10653              pr "  int n, i;\n";
10654              pr "  sscanf (val, \"%%d\", &n);\n";
10655              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10656              pr "  for (i = 0; i < n; ++i) {\n";
10657              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10658              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10659              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10660              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10661              pr "  }\n";
10662              pr "  strs[n*2] = NULL;\n";
10663              pr "  return strs;\n"
10664          | RBufferOut _ ->
10665              pr "  return strdup (val);\n"
10666         );
10667         pr "}\n";
10668         pr "\n"
10669       ) else (
10670         pr "/* Test error return. */\n";
10671         generate_prototype ~extern:false ~semicolon:false ~newline:true
10672           ~handle:"g" ~prefix:"guestfs__" name style;
10673         pr "{\n";
10674         pr "  error (g, \"error\");\n";
10675         (match fst style with
10676          | RErr | RInt _ | RInt64 _ | RBool _ ->
10677              pr "  return -1;\n"
10678          | RConstString _ | RConstOptString _
10679          | RString _ | RStringList _ | RStruct _
10680          | RStructList _
10681          | RHashtable _
10682          | RBufferOut _ ->
10683              pr "  return NULL;\n"
10684         );
10685         pr "}\n";
10686         pr "\n"
10687       )
10688   ) tests
10689
10690 and generate_ocaml_bindtests () =
10691   generate_header OCamlStyle GPLv2plus;
10692
10693   pr "\
10694 let () =
10695   let g = Guestfs.create () in
10696 ";
10697
10698   let mkargs args =
10699     String.concat " " (
10700       List.map (
10701         function
10702         | CallString s -> "\"" ^ s ^ "\""
10703         | CallOptString None -> "None"
10704         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10705         | CallStringList xs ->
10706             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10707         | CallInt i when i >= 0 -> string_of_int i
10708         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10709         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10710         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10711         | CallBool b -> string_of_bool b
10712       ) args
10713     )
10714   in
10715
10716   generate_lang_bindtests (
10717     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10718   );
10719
10720   pr "print_endline \"EOF\"\n"
10721
10722 and generate_perl_bindtests () =
10723   pr "#!/usr/bin/perl -w\n";
10724   generate_header HashStyle GPLv2plus;
10725
10726   pr "\
10727 use strict;
10728
10729 use Sys::Guestfs;
10730
10731 my $g = Sys::Guestfs->new ();
10732 ";
10733
10734   let mkargs args =
10735     String.concat ", " (
10736       List.map (
10737         function
10738         | CallString s -> "\"" ^ s ^ "\""
10739         | CallOptString None -> "undef"
10740         | CallOptString (Some s) -> sprintf "\"%s\"" s
10741         | CallStringList xs ->
10742             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10743         | CallInt i -> string_of_int i
10744         | CallInt64 i -> Int64.to_string i
10745         | CallBool b -> if b then "1" else "0"
10746       ) args
10747     )
10748   in
10749
10750   generate_lang_bindtests (
10751     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10752   );
10753
10754   pr "print \"EOF\\n\"\n"
10755
10756 and generate_python_bindtests () =
10757   generate_header HashStyle GPLv2plus;
10758
10759   pr "\
10760 import guestfs
10761
10762 g = guestfs.GuestFS ()
10763 ";
10764
10765   let mkargs args =
10766     String.concat ", " (
10767       List.map (
10768         function
10769         | CallString s -> "\"" ^ s ^ "\""
10770         | CallOptString None -> "None"
10771         | CallOptString (Some s) -> sprintf "\"%s\"" s
10772         | CallStringList xs ->
10773             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10774         | CallInt i -> string_of_int i
10775         | CallInt64 i -> Int64.to_string i
10776         | CallBool b -> if b then "1" else "0"
10777       ) args
10778     )
10779   in
10780
10781   generate_lang_bindtests (
10782     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10783   );
10784
10785   pr "print \"EOF\"\n"
10786
10787 and generate_ruby_bindtests () =
10788   generate_header HashStyle GPLv2plus;
10789
10790   pr "\
10791 require 'guestfs'
10792
10793 g = Guestfs::create()
10794 ";
10795
10796   let mkargs args =
10797     String.concat ", " (
10798       List.map (
10799         function
10800         | CallString s -> "\"" ^ s ^ "\""
10801         | CallOptString None -> "nil"
10802         | CallOptString (Some s) -> sprintf "\"%s\"" s
10803         | CallStringList xs ->
10804             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10805         | CallInt i -> string_of_int i
10806         | CallInt64 i -> Int64.to_string i
10807         | CallBool b -> string_of_bool b
10808       ) args
10809     )
10810   in
10811
10812   generate_lang_bindtests (
10813     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10814   );
10815
10816   pr "print \"EOF\\n\"\n"
10817
10818 and generate_java_bindtests () =
10819   generate_header CStyle GPLv2plus;
10820
10821   pr "\
10822 import com.redhat.et.libguestfs.*;
10823
10824 public class Bindtests {
10825     public static void main (String[] argv)
10826     {
10827         try {
10828             GuestFS g = new GuestFS ();
10829 ";
10830
10831   let mkargs args =
10832     String.concat ", " (
10833       List.map (
10834         function
10835         | CallString s -> "\"" ^ s ^ "\""
10836         | CallOptString None -> "null"
10837         | CallOptString (Some s) -> sprintf "\"%s\"" s
10838         | CallStringList xs ->
10839             "new String[]{" ^
10840               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10841         | CallInt i -> string_of_int i
10842         | CallInt64 i -> Int64.to_string i
10843         | CallBool b -> string_of_bool b
10844       ) args
10845     )
10846   in
10847
10848   generate_lang_bindtests (
10849     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10850   );
10851
10852   pr "
10853             System.out.println (\"EOF\");
10854         }
10855         catch (Exception exn) {
10856             System.err.println (exn);
10857             System.exit (1);
10858         }
10859     }
10860 }
10861 "
10862
10863 and generate_haskell_bindtests () =
10864   generate_header HaskellStyle GPLv2plus;
10865
10866   pr "\
10867 module Bindtests where
10868 import qualified Guestfs
10869
10870 main = do
10871   g <- Guestfs.create
10872 ";
10873
10874   let mkargs args =
10875     String.concat " " (
10876       List.map (
10877         function
10878         | CallString s -> "\"" ^ s ^ "\""
10879         | CallOptString None -> "Nothing"
10880         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10881         | CallStringList xs ->
10882             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10883         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10884         | CallInt i -> string_of_int i
10885         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10886         | CallInt64 i -> Int64.to_string i
10887         | CallBool true -> "True"
10888         | CallBool false -> "False"
10889       ) args
10890     )
10891   in
10892
10893   generate_lang_bindtests (
10894     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10895   );
10896
10897   pr "  putStrLn \"EOF\"\n"
10898
10899 (* Language-independent bindings tests - we do it this way to
10900  * ensure there is parity in testing bindings across all languages.
10901  *)
10902 and generate_lang_bindtests call =
10903   call "test0" [CallString "abc"; CallOptString (Some "def");
10904                 CallStringList []; CallBool false;
10905                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10906   call "test0" [CallString "abc"; CallOptString None;
10907                 CallStringList []; CallBool false;
10908                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10909   call "test0" [CallString ""; CallOptString (Some "def");
10910                 CallStringList []; CallBool false;
10911                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10912   call "test0" [CallString ""; CallOptString (Some "");
10913                 CallStringList []; CallBool false;
10914                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10915   call "test0" [CallString "abc"; CallOptString (Some "def");
10916                 CallStringList ["1"]; CallBool false;
10917                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10918   call "test0" [CallString "abc"; CallOptString (Some "def");
10919                 CallStringList ["1"; "2"]; CallBool false;
10920                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10921   call "test0" [CallString "abc"; CallOptString (Some "def");
10922                 CallStringList ["1"]; CallBool true;
10923                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10924   call "test0" [CallString "abc"; CallOptString (Some "def");
10925                 CallStringList ["1"]; CallBool false;
10926                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10927   call "test0" [CallString "abc"; CallOptString (Some "def");
10928                 CallStringList ["1"]; CallBool false;
10929                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10930   call "test0" [CallString "abc"; CallOptString (Some "def");
10931                 CallStringList ["1"]; CallBool false;
10932                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10933   call "test0" [CallString "abc"; CallOptString (Some "def");
10934                 CallStringList ["1"]; CallBool false;
10935                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10936   call "test0" [CallString "abc"; CallOptString (Some "def");
10937                 CallStringList ["1"]; CallBool false;
10938                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10939   call "test0" [CallString "abc"; CallOptString (Some "def");
10940                 CallStringList ["1"]; CallBool false;
10941                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10942
10943 (* XXX Add here tests of the return and error functions. *)
10944
10945 (* Code to generator bindings for virt-inspector.  Currently only
10946  * implemented for OCaml code (for virt-p2v 2.0).
10947  *)
10948 let rng_input = "inspector/virt-inspector.rng"
10949
10950 (* Read the input file and parse it into internal structures.  This is
10951  * by no means a complete RELAX NG parser, but is just enough to be
10952  * able to parse the specific input file.
10953  *)
10954 type rng =
10955   | Element of string * rng list        (* <element name=name/> *)
10956   | Attribute of string * rng list        (* <attribute name=name/> *)
10957   | Interleave of rng list                (* <interleave/> *)
10958   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10959   | OneOrMore of rng                        (* <oneOrMore/> *)
10960   | Optional of rng                        (* <optional/> *)
10961   | Choice of string list                (* <choice><value/>*</choice> *)
10962   | Value of string                        (* <value>str</value> *)
10963   | Text                                (* <text/> *)
10964
10965 let rec string_of_rng = function
10966   | Element (name, xs) ->
10967       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10968   | Attribute (name, xs) ->
10969       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10970   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10971   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10972   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10973   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10974   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10975   | Value value -> "Value \"" ^ value ^ "\""
10976   | Text -> "Text"
10977
10978 and string_of_rng_list xs =
10979   String.concat ", " (List.map string_of_rng xs)
10980
10981 let rec parse_rng ?defines context = function
10982   | [] -> []
10983   | Xml.Element ("element", ["name", name], children) :: rest ->
10984       Element (name, parse_rng ?defines context children)
10985       :: parse_rng ?defines context rest
10986   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10987       Attribute (name, parse_rng ?defines context children)
10988       :: parse_rng ?defines context rest
10989   | Xml.Element ("interleave", [], children) :: rest ->
10990       Interleave (parse_rng ?defines context children)
10991       :: parse_rng ?defines context rest
10992   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10993       let rng = parse_rng ?defines context [child] in
10994       (match rng with
10995        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10996        | _ ->
10997            failwithf "%s: <zeroOrMore> contains more than one child element"
10998              context
10999       )
11000   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11001       let rng = parse_rng ?defines context [child] in
11002       (match rng with
11003        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11004        | _ ->
11005            failwithf "%s: <oneOrMore> contains more than one child element"
11006              context
11007       )
11008   | Xml.Element ("optional", [], [child]) :: rest ->
11009       let rng = parse_rng ?defines context [child] in
11010       (match rng with
11011        | [child] -> Optional child :: parse_rng ?defines context rest
11012        | _ ->
11013            failwithf "%s: <optional> contains more than one child element"
11014              context
11015       )
11016   | Xml.Element ("choice", [], children) :: rest ->
11017       let values = List.map (
11018         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11019         | _ ->
11020             failwithf "%s: can't handle anything except <value> in <choice>"
11021               context
11022       ) children in
11023       Choice values
11024       :: parse_rng ?defines context rest
11025   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11026       Value value :: parse_rng ?defines context rest
11027   | Xml.Element ("text", [], []) :: rest ->
11028       Text :: parse_rng ?defines context rest
11029   | Xml.Element ("ref", ["name", name], []) :: rest ->
11030       (* Look up the reference.  Because of limitations in this parser,
11031        * we can't handle arbitrarily nested <ref> yet.  You can only
11032        * use <ref> from inside <start>.
11033        *)
11034       (match defines with
11035        | None ->
11036            failwithf "%s: contains <ref>, but no refs are defined yet" context
11037        | Some map ->
11038            let rng = StringMap.find name map in
11039            rng @ parse_rng ?defines context rest
11040       )
11041   | x :: _ ->
11042       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11043
11044 let grammar =
11045   let xml = Xml.parse_file rng_input in
11046   match xml with
11047   | Xml.Element ("grammar", _,
11048                  Xml.Element ("start", _, gram) :: defines) ->
11049       (* The <define/> elements are referenced in the <start> section,
11050        * so build a map of those first.
11051        *)
11052       let defines = List.fold_left (
11053         fun map ->
11054           function Xml.Element ("define", ["name", name], defn) ->
11055             StringMap.add name defn map
11056           | _ ->
11057               failwithf "%s: expected <define name=name/>" rng_input
11058       ) StringMap.empty defines in
11059       let defines = StringMap.mapi parse_rng defines in
11060
11061       (* Parse the <start> clause, passing the defines. *)
11062       parse_rng ~defines "<start>" gram
11063   | _ ->
11064       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11065         rng_input
11066
11067 let name_of_field = function
11068   | Element (name, _) | Attribute (name, _)
11069   | ZeroOrMore (Element (name, _))
11070   | OneOrMore (Element (name, _))
11071   | Optional (Element (name, _)) -> name
11072   | Optional (Attribute (name, _)) -> name
11073   | Text -> (* an unnamed field in an element *)
11074       "data"
11075   | rng ->
11076       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11077
11078 (* At the moment this function only generates OCaml types.  However we
11079  * should parameterize it later so it can generate types/structs in a
11080  * variety of languages.
11081  *)
11082 let generate_types xs =
11083   (* A simple type is one that can be printed out directly, eg.
11084    * "string option".  A complex type is one which has a name and has
11085    * to be defined via another toplevel definition, eg. a struct.
11086    *
11087    * generate_type generates code for either simple or complex types.
11088    * In the simple case, it returns the string ("string option").  In
11089    * the complex case, it returns the name ("mountpoint").  In the
11090    * complex case it has to print out the definition before returning,
11091    * so it should only be called when we are at the beginning of a
11092    * new line (BOL context).
11093    *)
11094   let rec generate_type = function
11095     | Text ->                                (* string *)
11096         "string", true
11097     | Choice values ->                        (* [`val1|`val2|...] *)
11098         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11099     | ZeroOrMore rng ->                        (* <rng> list *)
11100         let t, is_simple = generate_type rng in
11101         t ^ " list (* 0 or more *)", is_simple
11102     | OneOrMore rng ->                        (* <rng> list *)
11103         let t, is_simple = generate_type rng in
11104         t ^ " list (* 1 or more *)", is_simple
11105                                         (* virt-inspector hack: bool *)
11106     | Optional (Attribute (name, [Value "1"])) ->
11107         "bool", true
11108     | Optional rng ->                        (* <rng> list *)
11109         let t, is_simple = generate_type rng in
11110         t ^ " option", is_simple
11111                                         (* type name = { fields ... } *)
11112     | Element (name, fields) when is_attrs_interleave fields ->
11113         generate_type_struct name (get_attrs_interleave fields)
11114     | Element (name, [field])                (* type name = field *)
11115     | Attribute (name, [field]) ->
11116         let t, is_simple = generate_type field in
11117         if is_simple then (t, true)
11118         else (
11119           pr "type %s = %s\n" name t;
11120           name, false
11121         )
11122     | Element (name, fields) ->              (* type name = { fields ... } *)
11123         generate_type_struct name fields
11124     | rng ->
11125         failwithf "generate_type failed at: %s" (string_of_rng rng)
11126
11127   and is_attrs_interleave = function
11128     | [Interleave _] -> true
11129     | Attribute _ :: fields -> is_attrs_interleave fields
11130     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11131     | _ -> false
11132
11133   and get_attrs_interleave = function
11134     | [Interleave fields] -> fields
11135     | ((Attribute _) as field) :: fields
11136     | ((Optional (Attribute _)) as field) :: fields ->
11137         field :: get_attrs_interleave fields
11138     | _ -> assert false
11139
11140   and generate_types xs =
11141     List.iter (fun x -> ignore (generate_type x)) xs
11142
11143   and generate_type_struct name fields =
11144     (* Calculate the types of the fields first.  We have to do this
11145      * before printing anything so we are still in BOL context.
11146      *)
11147     let types = List.map fst (List.map generate_type fields) in
11148
11149     (* Special case of a struct containing just a string and another
11150      * field.  Turn it into an assoc list.
11151      *)
11152     match types with
11153     | ["string"; other] ->
11154         let fname1, fname2 =
11155           match fields with
11156           | [f1; f2] -> name_of_field f1, name_of_field f2
11157           | _ -> assert false in
11158         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11159         name, false
11160
11161     | types ->
11162         pr "type %s = {\n" name;
11163         List.iter (
11164           fun (field, ftype) ->
11165             let fname = name_of_field field in
11166             pr "  %s_%s : %s;\n" name fname ftype
11167         ) (List.combine fields types);
11168         pr "}\n";
11169         (* Return the name of this type, and
11170          * false because it's not a simple type.
11171          *)
11172         name, false
11173   in
11174
11175   generate_types xs
11176
11177 let generate_parsers xs =
11178   (* As for generate_type above, generate_parser makes a parser for
11179    * some type, and returns the name of the parser it has generated.
11180    * Because it (may) need to print something, it should always be
11181    * called in BOL context.
11182    *)
11183   let rec generate_parser = function
11184     | Text ->                                (* string *)
11185         "string_child_or_empty"
11186     | Choice values ->                        (* [`val1|`val2|...] *)
11187         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11188           (String.concat "|"
11189              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11190     | ZeroOrMore rng ->                        (* <rng> list *)
11191         let pa = generate_parser rng in
11192         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11193     | OneOrMore rng ->                        (* <rng> list *)
11194         let pa = generate_parser rng in
11195         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11196                                         (* virt-inspector hack: bool *)
11197     | Optional (Attribute (name, [Value "1"])) ->
11198         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11199     | Optional rng ->                        (* <rng> list *)
11200         let pa = generate_parser rng in
11201         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11202                                         (* type name = { fields ... } *)
11203     | Element (name, fields) when is_attrs_interleave fields ->
11204         generate_parser_struct name (get_attrs_interleave fields)
11205     | Element (name, [field]) ->        (* type name = field *)
11206         let pa = generate_parser field in
11207         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11208         pr "let %s =\n" parser_name;
11209         pr "  %s\n" pa;
11210         pr "let parse_%s = %s\n" name parser_name;
11211         parser_name
11212     | Attribute (name, [field]) ->
11213         let pa = generate_parser field in
11214         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11215         pr "let %s =\n" parser_name;
11216         pr "  %s\n" pa;
11217         pr "let parse_%s = %s\n" name parser_name;
11218         parser_name
11219     | Element (name, fields) ->              (* type name = { fields ... } *)
11220         generate_parser_struct name ([], fields)
11221     | rng ->
11222         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11223
11224   and is_attrs_interleave = function
11225     | [Interleave _] -> true
11226     | Attribute _ :: fields -> is_attrs_interleave fields
11227     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11228     | _ -> false
11229
11230   and get_attrs_interleave = function
11231     | [Interleave fields] -> [], fields
11232     | ((Attribute _) as field) :: fields
11233     | ((Optional (Attribute _)) as field) :: fields ->
11234         let attrs, interleaves = get_attrs_interleave fields in
11235         (field :: attrs), interleaves
11236     | _ -> assert false
11237
11238   and generate_parsers xs =
11239     List.iter (fun x -> ignore (generate_parser x)) xs
11240
11241   and generate_parser_struct name (attrs, interleaves) =
11242     (* Generate parsers for the fields first.  We have to do this
11243      * before printing anything so we are still in BOL context.
11244      *)
11245     let fields = attrs @ interleaves in
11246     let pas = List.map generate_parser fields in
11247
11248     (* Generate an intermediate tuple from all the fields first.
11249      * If the type is just a string + another field, then we will
11250      * return this directly, otherwise it is turned into a record.
11251      *
11252      * RELAX NG note: This code treats <interleave> and plain lists of
11253      * fields the same.  In other words, it doesn't bother enforcing
11254      * any ordering of fields in the XML.
11255      *)
11256     pr "let parse_%s x =\n" name;
11257     pr "  let t = (\n    ";
11258     let comma = ref false in
11259     List.iter (
11260       fun x ->
11261         if !comma then pr ",\n    ";
11262         comma := true;
11263         match x with
11264         | Optional (Attribute (fname, [field])), pa ->
11265             pr "%s x" pa
11266         | Optional (Element (fname, [field])), pa ->
11267             pr "%s (optional_child %S x)" pa fname
11268         | Attribute (fname, [Text]), _ ->
11269             pr "attribute %S x" fname
11270         | (ZeroOrMore _ | OneOrMore _), pa ->
11271             pr "%s x" pa
11272         | Text, pa ->
11273             pr "%s x" pa
11274         | (field, pa) ->
11275             let fname = name_of_field field in
11276             pr "%s (child %S x)" pa fname
11277     ) (List.combine fields pas);
11278     pr "\n  ) in\n";
11279
11280     (match fields with
11281      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11282          pr "  t\n"
11283
11284      | _ ->
11285          pr "  (Obj.magic t : %s)\n" name
11286 (*
11287          List.iter (
11288            function
11289            | (Optional (Attribute (fname, [field])), pa) ->
11290                pr "  %s_%s =\n" name fname;
11291                pr "    %s x;\n" pa
11292            | (Optional (Element (fname, [field])), pa) ->
11293                pr "  %s_%s =\n" name fname;
11294                pr "    (let x = optional_child %S x in\n" fname;
11295                pr "     %s x);\n" pa
11296            | (field, pa) ->
11297                let fname = name_of_field field in
11298                pr "  %s_%s =\n" name fname;
11299                pr "    (let x = child %S x in\n" fname;
11300                pr "     %s x);\n" pa
11301          ) (List.combine fields pas);
11302          pr "}\n"
11303 *)
11304     );
11305     sprintf "parse_%s" name
11306   in
11307
11308   generate_parsers xs
11309
11310 (* Generate ocaml/guestfs_inspector.mli. *)
11311 let generate_ocaml_inspector_mli () =
11312   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11313
11314   pr "\
11315 (** This is an OCaml language binding to the external [virt-inspector]
11316     program.
11317
11318     For more information, please read the man page [virt-inspector(1)].
11319 *)
11320
11321 ";
11322
11323   generate_types grammar;
11324   pr "(** The nested information returned from the {!inspect} function. *)\n";
11325   pr "\n";
11326
11327   pr "\
11328 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11329 (** To inspect a libvirt domain called [name], pass a singleton
11330     list: [inspect [name]].  When using libvirt only, you may
11331     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11332
11333     To inspect a disk image or images, pass a list of the filenames
11334     of the disk images: [inspect filenames]
11335
11336     This function inspects the given guest or disk images and
11337     returns a list of operating system(s) found and a large amount
11338     of information about them.  In the vast majority of cases,
11339     a virtual machine only contains a single operating system.
11340
11341     If the optional [~xml] parameter is given, then this function
11342     skips running the external virt-inspector program and just
11343     parses the given XML directly (which is expected to be XML
11344     produced from a previous run of virt-inspector).  The list of
11345     names and connect URI are ignored in this case.
11346
11347     This function can throw a wide variety of exceptions, for example
11348     if the external virt-inspector program cannot be found, or if
11349     it doesn't generate valid XML.
11350 *)
11351 "
11352
11353 (* Generate ocaml/guestfs_inspector.ml. *)
11354 let generate_ocaml_inspector_ml () =
11355   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11356
11357   pr "open Unix\n";
11358   pr "\n";
11359
11360   generate_types grammar;
11361   pr "\n";
11362
11363   pr "\
11364 (* Misc functions which are used by the parser code below. *)
11365 let first_child = function
11366   | Xml.Element (_, _, c::_) -> c
11367   | Xml.Element (name, _, []) ->
11368       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11369   | Xml.PCData str ->
11370       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11371
11372 let string_child_or_empty = function
11373   | Xml.Element (_, _, [Xml.PCData s]) -> s
11374   | Xml.Element (_, _, []) -> \"\"
11375   | Xml.Element (x, _, _) ->
11376       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11377                 x ^ \" instead\")
11378   | Xml.PCData str ->
11379       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11380
11381 let optional_child name xml =
11382   let children = Xml.children xml in
11383   try
11384     Some (List.find (function
11385                      | Xml.Element (n, _, _) when n = name -> true
11386                      | _ -> false) children)
11387   with
11388     Not_found -> None
11389
11390 let child name xml =
11391   match optional_child name xml with
11392   | Some c -> c
11393   | None ->
11394       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11395
11396 let attribute name xml =
11397   try Xml.attrib xml name
11398   with Xml.No_attribute _ ->
11399     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11400
11401 ";
11402
11403   generate_parsers grammar;
11404   pr "\n";
11405
11406   pr "\
11407 (* Run external virt-inspector, then use parser to parse the XML. *)
11408 let inspect ?connect ?xml names =
11409   let xml =
11410     match xml with
11411     | None ->
11412         if names = [] then invalid_arg \"inspect: no names given\";
11413         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11414           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11415           names in
11416         let cmd = List.map Filename.quote cmd in
11417         let cmd = String.concat \" \" cmd in
11418         let chan = open_process_in cmd in
11419         let xml = Xml.parse_in chan in
11420         (match close_process_in chan with
11421          | WEXITED 0 -> ()
11422          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11423          | WSIGNALED i | WSTOPPED i ->
11424              failwith (\"external virt-inspector command died or stopped on sig \" ^
11425                        string_of_int i)
11426         );
11427         xml
11428     | Some doc ->
11429         Xml.parse_string doc in
11430   parse_operatingsystems xml
11431 "
11432
11433 (* This is used to generate the src/MAX_PROC_NR file which
11434  * contains the maximum procedure number, a surrogate for the
11435  * ABI version number.  See src/Makefile.am for the details.
11436  *)
11437 and generate_max_proc_nr () =
11438   let proc_nrs = List.map (
11439     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11440   ) daemon_functions in
11441
11442   let max_proc_nr = List.fold_left max 0 proc_nrs in
11443
11444   pr "%d\n" max_proc_nr
11445
11446 let output_to filename k =
11447   let filename_new = filename ^ ".new" in
11448   chan := open_out filename_new;
11449   k ();
11450   close_out !chan;
11451   chan := Pervasives.stdout;
11452
11453   (* Is the new file different from the current file? *)
11454   if Sys.file_exists filename && files_equal filename filename_new then
11455     unlink filename_new                 (* same, so skip it *)
11456   else (
11457     (* different, overwrite old one *)
11458     (try chmod filename 0o644 with Unix_error _ -> ());
11459     rename filename_new filename;
11460     chmod filename 0o444;
11461     printf "written %s\n%!" filename;
11462   )
11463
11464 let perror msg = function
11465   | Unix_error (err, _, _) ->
11466       eprintf "%s: %s\n" msg (error_message err)
11467   | exn ->
11468       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11469
11470 (* Main program. *)
11471 let () =
11472   let lock_fd =
11473     try openfile "HACKING" [O_RDWR] 0
11474     with
11475     | Unix_error (ENOENT, _, _) ->
11476         eprintf "\
11477 You are probably running this from the wrong directory.
11478 Run it from the top source directory using the command
11479   src/generator.ml
11480 ";
11481         exit 1
11482     | exn ->
11483         perror "open: HACKING" exn;
11484         exit 1 in
11485
11486   (* Acquire a lock so parallel builds won't try to run the generator
11487    * twice at the same time.  Subsequent builds will wait for the first
11488    * one to finish.  Note the lock is released implicitly when the
11489    * program exits.
11490    *)
11491   (try lockf lock_fd F_LOCK 1
11492    with exn ->
11493      perror "lock: HACKING" exn;
11494      exit 1);
11495
11496   check_functions ();
11497
11498   output_to "src/guestfs_protocol.x" generate_xdr;
11499   output_to "src/guestfs-structs.h" generate_structs_h;
11500   output_to "src/guestfs-actions.h" generate_actions_h;
11501   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11502   output_to "src/guestfs-actions.c" generate_client_actions;
11503   output_to "src/guestfs-bindtests.c" generate_bindtests;
11504   output_to "src/guestfs-structs.pod" generate_structs_pod;
11505   output_to "src/guestfs-actions.pod" generate_actions_pod;
11506   output_to "src/guestfs-availability.pod" generate_availability_pod;
11507   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11508   output_to "src/libguestfs.syms" generate_linker_script;
11509   output_to "daemon/actions.h" generate_daemon_actions_h;
11510   output_to "daemon/stubs.c" generate_daemon_actions;
11511   output_to "daemon/names.c" generate_daemon_names;
11512   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11513   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11514   output_to "capitests/tests.c" generate_tests;
11515   output_to "fish/cmds.c" generate_fish_cmds;
11516   output_to "fish/completion.c" generate_fish_completion;
11517   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11518   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11519   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11520   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11521   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11522   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11523   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11524   output_to "perl/Guestfs.xs" generate_perl_xs;
11525   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11526   output_to "perl/bindtests.pl" generate_perl_bindtests;
11527   output_to "python/guestfs-py.c" generate_python_c;
11528   output_to "python/guestfs.py" generate_python_py;
11529   output_to "python/bindtests.py" generate_python_bindtests;
11530   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11531   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11532   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11533
11534   List.iter (
11535     fun (typ, jtyp) ->
11536       let cols = cols_of_struct typ in
11537       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11538       output_to filename (generate_java_struct jtyp cols);
11539   ) java_structs;
11540
11541   output_to "java/Makefile.inc" generate_java_makefile_inc;
11542   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11543   output_to "java/Bindtests.java" generate_java_bindtests;
11544   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11545   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11546   output_to "csharp/Libguestfs.cs" generate_csharp;
11547
11548   (* Always generate this file last, and unconditionally.  It's used
11549    * by the Makefile to know when we must re-run the generator.
11550    *)
11551   let chan = open_out "src/stamp-generator" in
11552   fprintf chan "1\n";
11553   close_out chan;
11554
11555   printf "generated %d lines of code\n" !lines