Document that guestfs_mount implies -o sync and performance problem (RHBZ#587582).
[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 B<Important note:>
957 When you use this call, the filesystem options C<sync> and C<noatime>
958 are set implicitly.  This was originally done because we thought it
959 would improve reliability, but it turns out that I<-o sync> has a
960 very large negative performance impact and negligible effect on
961 reliability.  Therefore we recommend that you avoid using
962 C<guestfs_mount> in any code that needs performance, and instead
963 use C<guestfs_mount_options> (use an empty string for the first
964 parameter if you don't want any options).");
965
966   ("sync", (RErr, []), 2, [],
967    [ InitEmpty, Always, TestRun [["sync"]]],
968    "sync disks, writes are flushed through to the disk image",
969    "\
970 This syncs the disk, so that any writes are flushed through to the
971 underlying disk image.
972
973 You should always call this if you have modified a disk image, before
974 closing the handle.");
975
976   ("touch", (RErr, [Pathname "path"]), 3, [],
977    [InitBasicFS, Always, TestOutputTrue (
978       [["touch"; "/new"];
979        ["exists"; "/new"]])],
980    "update file timestamps or create a new file",
981    "\
982 Touch acts like the L<touch(1)> command.  It can be used to
983 update the timestamps on a file, or, if the file does not exist,
984 to create a new zero-length file.");
985
986   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
987    [InitISOFS, Always, TestOutput (
988       [["cat"; "/known-2"]], "abcdef\n")],
989    "list the contents of a file",
990    "\
991 Return the contents of the file named C<path>.
992
993 Note that this function cannot correctly handle binary files
994 (specifically, files containing C<\\0> character which is treated
995 as end of string).  For those you need to use the C<guestfs_read_file>
996 or C<guestfs_download> functions which have a more complex interface.");
997
998   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
999    [], (* XXX Tricky to test because it depends on the exact format
1000         * of the 'ls -l' command, which changes between F10 and F11.
1001         *)
1002    "list the files in a directory (long format)",
1003    "\
1004 List the files in C<directory> (relative to the root directory,
1005 there is no cwd) in the format of 'ls -la'.
1006
1007 This command is mostly useful for interactive sessions.  It
1008 is I<not> intended that you try to parse the output string.");
1009
1010   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1011    [InitBasicFS, Always, TestOutputList (
1012       [["touch"; "/new"];
1013        ["touch"; "/newer"];
1014        ["touch"; "/newest"];
1015        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1016    "list the files in a directory",
1017    "\
1018 List the files in C<directory> (relative to the root directory,
1019 there is no cwd).  The '.' and '..' entries are not returned, but
1020 hidden files are shown.
1021
1022 This command is mostly useful for interactive sessions.  Programs
1023 should probably use C<guestfs_readdir> instead.");
1024
1025   ("list_devices", (RStringList "devices", []), 7, [],
1026    [InitEmpty, Always, TestOutputListOfDevices (
1027       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1028    "list the block devices",
1029    "\
1030 List all the block devices.
1031
1032 The full block device names are returned, eg. C</dev/sda>");
1033
1034   ("list_partitions", (RStringList "partitions", []), 8, [],
1035    [InitBasicFS, Always, TestOutputListOfDevices (
1036       [["list_partitions"]], ["/dev/sda1"]);
1037     InitEmpty, Always, TestOutputListOfDevices (
1038       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1039        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1040    "list the partitions",
1041    "\
1042 List all the partitions detected on all block devices.
1043
1044 The full partition device names are returned, eg. C</dev/sda1>
1045
1046 This does not return logical volumes.  For that you will need to
1047 call C<guestfs_lvs>.");
1048
1049   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1050    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1051       [["pvs"]], ["/dev/sda1"]);
1052     InitEmpty, Always, TestOutputListOfDevices (
1053       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1054        ["pvcreate"; "/dev/sda1"];
1055        ["pvcreate"; "/dev/sda2"];
1056        ["pvcreate"; "/dev/sda3"];
1057        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1058    "list the LVM physical volumes (PVs)",
1059    "\
1060 List all the physical volumes detected.  This is the equivalent
1061 of the L<pvs(8)> command.
1062
1063 This returns a list of just the device names that contain
1064 PVs (eg. C</dev/sda2>).
1065
1066 See also C<guestfs_pvs_full>.");
1067
1068   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1069    [InitBasicFSonLVM, Always, TestOutputList (
1070       [["vgs"]], ["VG"]);
1071     InitEmpty, Always, TestOutputList (
1072       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1073        ["pvcreate"; "/dev/sda1"];
1074        ["pvcreate"; "/dev/sda2"];
1075        ["pvcreate"; "/dev/sda3"];
1076        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1077        ["vgcreate"; "VG2"; "/dev/sda3"];
1078        ["vgs"]], ["VG1"; "VG2"])],
1079    "list the LVM volume groups (VGs)",
1080    "\
1081 List all the volumes groups detected.  This is the equivalent
1082 of the L<vgs(8)> command.
1083
1084 This returns a list of just the volume group names that were
1085 detected (eg. C<VolGroup00>).
1086
1087 See also C<guestfs_vgs_full>.");
1088
1089   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1090    [InitBasicFSonLVM, Always, TestOutputList (
1091       [["lvs"]], ["/dev/VG/LV"]);
1092     InitEmpty, Always, TestOutputList (
1093       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1094        ["pvcreate"; "/dev/sda1"];
1095        ["pvcreate"; "/dev/sda2"];
1096        ["pvcreate"; "/dev/sda3"];
1097        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1098        ["vgcreate"; "VG2"; "/dev/sda3"];
1099        ["lvcreate"; "LV1"; "VG1"; "50"];
1100        ["lvcreate"; "LV2"; "VG1"; "50"];
1101        ["lvcreate"; "LV3"; "VG2"; "50"];
1102        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1103    "list the LVM logical volumes (LVs)",
1104    "\
1105 List all the logical volumes detected.  This is the equivalent
1106 of the L<lvs(8)> command.
1107
1108 This returns a list of the logical volume device names
1109 (eg. C</dev/VolGroup00/LogVol00>).
1110
1111 See also C<guestfs_lvs_full>.");
1112
1113   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM physical volumes (PVs)",
1116    "\
1117 List all the physical volumes detected.  This is the equivalent
1118 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM volume groups (VGs)",
1123    "\
1124 List all the volumes groups detected.  This is the equivalent
1125 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1128    [], (* XXX how to test? *)
1129    "list the LVM logical volumes (LVs)",
1130    "\
1131 List all the logical volumes detected.  This is the equivalent
1132 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1133
1134   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1135    [InitISOFS, Always, TestOutputList (
1136       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1137     InitISOFS, Always, TestOutputList (
1138       [["read_lines"; "/empty"]], [])],
1139    "read file as lines",
1140    "\
1141 Return the contents of the file named C<path>.
1142
1143 The file contents are returned as a list of lines.  Trailing
1144 C<LF> and C<CRLF> character sequences are I<not> returned.
1145
1146 Note that this function cannot correctly handle binary files
1147 (specifically, files containing C<\\0> character which is treated
1148 as end of line).  For those you need to use the C<guestfs_read_file>
1149 function which has a more complex interface.");
1150
1151   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1152    [], (* XXX Augeas code needs tests. *)
1153    "create a new Augeas handle",
1154    "\
1155 Create a new Augeas handle for editing configuration files.
1156 If there was any previous Augeas handle associated with this
1157 guestfs session, then it is closed.
1158
1159 You must call this before using any other C<guestfs_aug_*>
1160 commands.
1161
1162 C<root> is the filesystem root.  C<root> must not be NULL,
1163 use C</> instead.
1164
1165 The flags are the same as the flags defined in
1166 E<lt>augeas.hE<gt>, the logical I<or> of the following
1167 integers:
1168
1169 =over 4
1170
1171 =item C<AUG_SAVE_BACKUP> = 1
1172
1173 Keep the original file with a C<.augsave> extension.
1174
1175 =item C<AUG_SAVE_NEWFILE> = 2
1176
1177 Save changes into a file with extension C<.augnew>, and
1178 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1179
1180 =item C<AUG_TYPE_CHECK> = 4
1181
1182 Typecheck lenses (can be expensive).
1183
1184 =item C<AUG_NO_STDINC> = 8
1185
1186 Do not use standard load path for modules.
1187
1188 =item C<AUG_SAVE_NOOP> = 16
1189
1190 Make save a no-op, just record what would have been changed.
1191
1192 =item C<AUG_NO_LOAD> = 32
1193
1194 Do not load the tree in C<guestfs_aug_init>.
1195
1196 =back
1197
1198 To close the handle, you can call C<guestfs_aug_close>.
1199
1200 To find out more about Augeas, see L<http://augeas.net/>.");
1201
1202   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1203    [], (* XXX Augeas code needs tests. *)
1204    "close the current Augeas handle",
1205    "\
1206 Close the current Augeas handle and free up any resources
1207 used by it.  After calling this, you have to call
1208 C<guestfs_aug_init> again before you can use any other
1209 Augeas functions.");
1210
1211   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1212    [], (* XXX Augeas code needs tests. *)
1213    "define an Augeas variable",
1214    "\
1215 Defines an Augeas variable C<name> whose value is the result
1216 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1217 undefined.
1218
1219 On success this returns the number of nodes in C<expr>, or
1220 C<0> if C<expr> evaluates to something which is not a nodeset.");
1221
1222   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1223    [], (* XXX Augeas code needs tests. *)
1224    "define an Augeas node",
1225    "\
1226 Defines a variable C<name> whose value is the result of
1227 evaluating C<expr>.
1228
1229 If C<expr> evaluates to an empty nodeset, a node is created,
1230 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1231 C<name> will be the nodeset containing that single node.
1232
1233 On success this returns a pair containing the
1234 number of nodes in the nodeset, and a boolean flag
1235 if a node was created.");
1236
1237   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "look up the value of an Augeas path",
1240    "\
1241 Look up the value associated with C<path>.  If C<path>
1242 matches exactly one node, the C<value> is returned.");
1243
1244   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1245    [], (* XXX Augeas code needs tests. *)
1246    "set Augeas path to value",
1247    "\
1248 Set the value associated with C<path> to C<value>.");
1249
1250   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1251    [], (* XXX Augeas code needs tests. *)
1252    "insert a sibling Augeas node",
1253    "\
1254 Create a new sibling C<label> for C<path>, inserting it into
1255 the tree before or after C<path> (depending on the boolean
1256 flag C<before>).
1257
1258 C<path> must match exactly one existing node in the tree, and
1259 C<label> must be a label, ie. not contain C</>, C<*> or end
1260 with a bracketed index C<[N]>.");
1261
1262   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1263    [], (* XXX Augeas code needs tests. *)
1264    "remove an Augeas path",
1265    "\
1266 Remove C<path> and all of its children.
1267
1268 On success this returns the number of entries which were removed.");
1269
1270   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "move Augeas node",
1273    "\
1274 Move the node C<src> to C<dest>.  C<src> must match exactly
1275 one node.  C<dest> is overwritten if it exists.");
1276
1277   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1278    [], (* XXX Augeas code needs tests. *)
1279    "return Augeas nodes which match augpath",
1280    "\
1281 Returns a list of paths which match the path expression C<path>.
1282 The returned paths are sufficiently qualified so that they match
1283 exactly one node in the current tree.");
1284
1285   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1286    [], (* XXX Augeas code needs tests. *)
1287    "write all pending Augeas changes to disk",
1288    "\
1289 This writes all pending changes to disk.
1290
1291 The flags which were passed to C<guestfs_aug_init> affect exactly
1292 how files are saved.");
1293
1294   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "load files into the tree",
1297    "\
1298 Load files into the tree.
1299
1300 See C<aug_load> in the Augeas documentation for the full gory
1301 details.");
1302
1303   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1304    [], (* XXX Augeas code needs tests. *)
1305    "list Augeas nodes under augpath",
1306    "\
1307 This is just a shortcut for listing C<guestfs_aug_match>
1308 C<path/*> and sorting the resulting nodes into alphabetical order.");
1309
1310   ("rm", (RErr, [Pathname "path"]), 29, [],
1311    [InitBasicFS, Always, TestRun
1312       [["touch"; "/new"];
1313        ["rm"; "/new"]];
1314     InitBasicFS, Always, TestLastFail
1315       [["rm"; "/new"]];
1316     InitBasicFS, Always, TestLastFail
1317       [["mkdir"; "/new"];
1318        ["rm"; "/new"]]],
1319    "remove a file",
1320    "\
1321 Remove the single file C<path>.");
1322
1323   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1324    [InitBasicFS, Always, TestRun
1325       [["mkdir"; "/new"];
1326        ["rmdir"; "/new"]];
1327     InitBasicFS, Always, TestLastFail
1328       [["rmdir"; "/new"]];
1329     InitBasicFS, Always, TestLastFail
1330       [["touch"; "/new"];
1331        ["rmdir"; "/new"]]],
1332    "remove a directory",
1333    "\
1334 Remove the single directory C<path>.");
1335
1336   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1337    [InitBasicFS, Always, TestOutputFalse
1338       [["mkdir"; "/new"];
1339        ["mkdir"; "/new/foo"];
1340        ["touch"; "/new/foo/bar"];
1341        ["rm_rf"; "/new"];
1342        ["exists"; "/new"]]],
1343    "remove a file or directory recursively",
1344    "\
1345 Remove the file or directory C<path>, recursively removing the
1346 contents if its a directory.  This is like the C<rm -rf> shell
1347 command.");
1348
1349   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1350    [InitBasicFS, Always, TestOutputTrue
1351       [["mkdir"; "/new"];
1352        ["is_dir"; "/new"]];
1353     InitBasicFS, Always, TestLastFail
1354       [["mkdir"; "/new/foo/bar"]]],
1355    "create a directory",
1356    "\
1357 Create a directory named C<path>.");
1358
1359   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1360    [InitBasicFS, Always, TestOutputTrue
1361       [["mkdir_p"; "/new/foo/bar"];
1362        ["is_dir"; "/new/foo/bar"]];
1363     InitBasicFS, Always, TestOutputTrue
1364       [["mkdir_p"; "/new/foo/bar"];
1365        ["is_dir"; "/new/foo"]];
1366     InitBasicFS, Always, TestOutputTrue
1367       [["mkdir_p"; "/new/foo/bar"];
1368        ["is_dir"; "/new"]];
1369     (* Regression tests for RHBZ#503133: *)
1370     InitBasicFS, Always, TestRun
1371       [["mkdir"; "/new"];
1372        ["mkdir_p"; "/new"]];
1373     InitBasicFS, Always, TestLastFail
1374       [["touch"; "/new"];
1375        ["mkdir_p"; "/new"]]],
1376    "create a directory and parents",
1377    "\
1378 Create a directory named C<path>, creating any parent directories
1379 as necessary.  This is like the C<mkdir -p> shell command.");
1380
1381   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1382    [], (* XXX Need stat command to test *)
1383    "change file mode",
1384    "\
1385 Change the mode (permissions) of C<path> to C<mode>.  Only
1386 numeric modes are supported.
1387
1388 I<Note>: When using this command from guestfish, C<mode>
1389 by default would be decimal, unless you prefix it with
1390 C<0> to get octal, ie. use C<0700> not C<700>.
1391
1392 The mode actually set is affected by the umask.");
1393
1394   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1395    [], (* XXX Need stat command to test *)
1396    "change file owner and group",
1397    "\
1398 Change the file owner to C<owner> and group to C<group>.
1399
1400 Only numeric uid and gid are supported.  If you want to use
1401 names, you will need to locate and parse the password file
1402 yourself (Augeas support makes this relatively easy).");
1403
1404   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1405    [InitISOFS, Always, TestOutputTrue (
1406       [["exists"; "/empty"]]);
1407     InitISOFS, Always, TestOutputTrue (
1408       [["exists"; "/directory"]])],
1409    "test if file or directory exists",
1410    "\
1411 This returns C<true> if and only if there is a file, directory
1412 (or anything) with the given C<path> name.
1413
1414 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1415
1416   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1417    [InitISOFS, Always, TestOutputTrue (
1418       [["is_file"; "/known-1"]]);
1419     InitISOFS, Always, TestOutputFalse (
1420       [["is_file"; "/directory"]])],
1421    "test if file exists",
1422    "\
1423 This returns C<true> if and only if there is a file
1424 with the given C<path> name.  Note that it returns false for
1425 other objects like directories.
1426
1427 See also C<guestfs_stat>.");
1428
1429   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1430    [InitISOFS, Always, TestOutputFalse (
1431       [["is_dir"; "/known-3"]]);
1432     InitISOFS, Always, TestOutputTrue (
1433       [["is_dir"; "/directory"]])],
1434    "test if file exists",
1435    "\
1436 This returns C<true> if and only if there is a directory
1437 with the given C<path> name.  Note that it returns false for
1438 other objects like files.
1439
1440 See also C<guestfs_stat>.");
1441
1442   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1443    [InitEmpty, Always, TestOutputListOfDevices (
1444       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1445        ["pvcreate"; "/dev/sda1"];
1446        ["pvcreate"; "/dev/sda2"];
1447        ["pvcreate"; "/dev/sda3"];
1448        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1449    "create an LVM physical volume",
1450    "\
1451 This creates an LVM physical volume on the named C<device>,
1452 where C<device> should usually be a partition name such
1453 as C</dev/sda1>.");
1454
1455   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1456    [InitEmpty, Always, TestOutputList (
1457       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1458        ["pvcreate"; "/dev/sda1"];
1459        ["pvcreate"; "/dev/sda2"];
1460        ["pvcreate"; "/dev/sda3"];
1461        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1462        ["vgcreate"; "VG2"; "/dev/sda3"];
1463        ["vgs"]], ["VG1"; "VG2"])],
1464    "create an LVM volume group",
1465    "\
1466 This creates an LVM volume group called C<volgroup>
1467 from the non-empty list of physical volumes C<physvols>.");
1468
1469   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1470    [InitEmpty, Always, TestOutputList (
1471       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1472        ["pvcreate"; "/dev/sda1"];
1473        ["pvcreate"; "/dev/sda2"];
1474        ["pvcreate"; "/dev/sda3"];
1475        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1476        ["vgcreate"; "VG2"; "/dev/sda3"];
1477        ["lvcreate"; "LV1"; "VG1"; "50"];
1478        ["lvcreate"; "LV2"; "VG1"; "50"];
1479        ["lvcreate"; "LV3"; "VG2"; "50"];
1480        ["lvcreate"; "LV4"; "VG2"; "50"];
1481        ["lvcreate"; "LV5"; "VG2"; "50"];
1482        ["lvs"]],
1483       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1484        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1485    "create an LVM logical volume",
1486    "\
1487 This creates an LVM logical volume called C<logvol>
1488 on the volume group C<volgroup>, with C<size> megabytes.");
1489
1490   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1491    [InitEmpty, Always, TestOutput (
1492       [["part_disk"; "/dev/sda"; "mbr"];
1493        ["mkfs"; "ext2"; "/dev/sda1"];
1494        ["mount_options"; ""; "/dev/sda1"; "/"];
1495        ["write_file"; "/new"; "new file contents"; "0"];
1496        ["cat"; "/new"]], "new file contents")],
1497    "make a filesystem",
1498    "\
1499 This creates a filesystem on C<device> (usually a partition
1500 or LVM logical volume).  The filesystem type is C<fstype>, for
1501 example C<ext3>.");
1502
1503   ("sfdisk", (RErr, [Device "device";
1504                      Int "cyls"; Int "heads"; Int "sectors";
1505                      StringList "lines"]), 43, [DangerWillRobinson],
1506    [],
1507    "create partitions on a block device",
1508    "\
1509 This is a direct interface to the L<sfdisk(8)> program for creating
1510 partitions on block devices.
1511
1512 C<device> should be a block device, for example C</dev/sda>.
1513
1514 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1515 and sectors on the device, which are passed directly to sfdisk as
1516 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1517 of these, then the corresponding parameter is omitted.  Usually for
1518 'large' disks, you can just pass C<0> for these, but for small
1519 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1520 out the right geometry and you will need to tell it.
1521
1522 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1523 information refer to the L<sfdisk(8)> manpage.
1524
1525 To create a single partition occupying the whole disk, you would
1526 pass C<lines> as a single element list, when the single element being
1527 the string C<,> (comma).
1528
1529 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1530 C<guestfs_part_init>");
1531
1532   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1533    [InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; "new file contents"; "0"];
1535        ["cat"; "/new"]], "new file contents");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1538        ["cat"; "/new"]], "\nnew file contents\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n\n"; "0"];
1541        ["cat"; "/new"]], "\n\n");
1542     InitBasicFS, Always, TestOutput (
1543       [["write_file"; "/new"; ""; "0"];
1544        ["cat"; "/new"]], "");
1545     InitBasicFS, Always, TestOutput (
1546       [["write_file"; "/new"; "\n\n\n"; "0"];
1547        ["cat"; "/new"]], "\n\n\n");
1548     InitBasicFS, Always, TestOutput (
1549       [["write_file"; "/new"; "\n"; "0"];
1550        ["cat"; "/new"]], "\n")],
1551    "create a file",
1552    "\
1553 This call creates a file called C<path>.  The contents of the
1554 file is the string C<content> (which can contain any 8 bit data),
1555 with length C<size>.
1556
1557 As a special case, if C<size> is C<0>
1558 then the length is calculated using C<strlen> (so in this case
1559 the content cannot contain embedded ASCII NULs).
1560
1561 I<NB.> Owing to a bug, writing content containing ASCII NUL
1562 characters does I<not> work, even if the length is specified.
1563 We hope to resolve this bug in a future version.  In the meantime
1564 use C<guestfs_upload>.");
1565
1566   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1567    [InitEmpty, Always, TestOutputListOfDevices (
1568       [["part_disk"; "/dev/sda"; "mbr"];
1569        ["mkfs"; "ext2"; "/dev/sda1"];
1570        ["mount_options"; ""; "/dev/sda1"; "/"];
1571        ["mounts"]], ["/dev/sda1"]);
1572     InitEmpty, Always, TestOutputList (
1573       [["part_disk"; "/dev/sda"; "mbr"];
1574        ["mkfs"; "ext2"; "/dev/sda1"];
1575        ["mount_options"; ""; "/dev/sda1"; "/"];
1576        ["umount"; "/"];
1577        ["mounts"]], [])],
1578    "unmount a filesystem",
1579    "\
1580 This unmounts the given filesystem.  The filesystem may be
1581 specified either by its mountpoint (path) or the device which
1582 contains the filesystem.");
1583
1584   ("mounts", (RStringList "devices", []), 46, [],
1585    [InitBasicFS, Always, TestOutputListOfDevices (
1586       [["mounts"]], ["/dev/sda1"])],
1587    "show mounted filesystems",
1588    "\
1589 This returns the list of currently mounted filesystems.  It returns
1590 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1591
1592 Some internal mounts are not shown.
1593
1594 See also: C<guestfs_mountpoints>");
1595
1596   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1597    [InitBasicFS, Always, TestOutputList (
1598       [["umount_all"];
1599        ["mounts"]], []);
1600     (* check that umount_all can unmount nested mounts correctly: *)
1601     InitEmpty, Always, TestOutputList (
1602       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1603        ["mkfs"; "ext2"; "/dev/sda1"];
1604        ["mkfs"; "ext2"; "/dev/sda2"];
1605        ["mkfs"; "ext2"; "/dev/sda3"];
1606        ["mount_options"; ""; "/dev/sda1"; "/"];
1607        ["mkdir"; "/mp1"];
1608        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1609        ["mkdir"; "/mp1/mp2"];
1610        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1611        ["mkdir"; "/mp1/mp2/mp3"];
1612        ["umount_all"];
1613        ["mounts"]], [])],
1614    "unmount all filesystems",
1615    "\
1616 This unmounts all mounted filesystems.
1617
1618 Some internal mounts are not unmounted by this call.");
1619
1620   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1621    [],
1622    "remove all LVM LVs, VGs and PVs",
1623    "\
1624 This command removes all LVM logical volumes, volume groups
1625 and physical volumes.");
1626
1627   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1628    [InitISOFS, Always, TestOutput (
1629       [["file"; "/empty"]], "empty");
1630     InitISOFS, Always, TestOutput (
1631       [["file"; "/known-1"]], "ASCII text");
1632     InitISOFS, Always, TestLastFail (
1633       [["file"; "/notexists"]])],
1634    "determine file type",
1635    "\
1636 This call uses the standard L<file(1)> command to determine
1637 the type or contents of the file.  This also works on devices,
1638 for example to find out whether a partition contains a filesystem.
1639
1640 This call will also transparently look inside various types
1641 of compressed file.
1642
1643 The exact command which runs is C<file -zbsL path>.  Note in
1644 particular that the filename is not prepended to the output
1645 (the C<-b> option).");
1646
1647   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1648    [InitBasicFS, Always, TestOutput (
1649       [["upload"; "test-command"; "/test-command"];
1650        ["chmod"; "0o755"; "/test-command"];
1651        ["command"; "/test-command 1"]], "Result1");
1652     InitBasicFS, Always, TestOutput (
1653       [["upload"; "test-command"; "/test-command"];
1654        ["chmod"; "0o755"; "/test-command"];
1655        ["command"; "/test-command 2"]], "Result2\n");
1656     InitBasicFS, Always, TestOutput (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command"; "/test-command 3"]], "\nResult3");
1660     InitBasicFS, Always, TestOutput (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command"; "/test-command 4"]], "\nResult4\n");
1664     InitBasicFS, Always, TestOutput (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command"; "/test-command 5"]], "\nResult5\n\n");
1668     InitBasicFS, Always, TestOutput (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1672     InitBasicFS, Always, TestOutput (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command"; "/test-command 7"]], "");
1676     InitBasicFS, Always, TestOutput (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command"; "/test-command 8"]], "\n");
1680     InitBasicFS, Always, TestOutput (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command"; "/test-command 9"]], "\n\n");
1684     InitBasicFS, Always, TestOutput (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1688     InitBasicFS, Always, TestOutput (
1689       [["upload"; "test-command"; "/test-command"];
1690        ["chmod"; "0o755"; "/test-command"];
1691        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1692     InitBasicFS, Always, TestLastFail (
1693       [["upload"; "test-command"; "/test-command"];
1694        ["chmod"; "0o755"; "/test-command"];
1695        ["command"; "/test-command"]])],
1696    "run a command from the guest filesystem",
1697    "\
1698 This call runs a command from the guest filesystem.  The
1699 filesystem must be mounted, and must contain a compatible
1700 operating system (ie. something Linux, with the same
1701 or compatible processor architecture).
1702
1703 The single parameter is an argv-style list of arguments.
1704 The first element is the name of the program to run.
1705 Subsequent elements are parameters.  The list must be
1706 non-empty (ie. must contain a program name).  Note that
1707 the command runs directly, and is I<not> invoked via
1708 the shell (see C<guestfs_sh>).
1709
1710 The return value is anything printed to I<stdout> by
1711 the command.
1712
1713 If the command returns a non-zero exit status, then
1714 this function returns an error message.  The error message
1715 string is the content of I<stderr> from the command.
1716
1717 The C<$PATH> environment variable will contain at least
1718 C</usr/bin> and C</bin>.  If you require a program from
1719 another location, you should provide the full path in the
1720 first parameter.
1721
1722 Shared libraries and data files required by the program
1723 must be available on filesystems which are mounted in the
1724 correct places.  It is the caller's responsibility to ensure
1725 all filesystems that are needed are mounted at the right
1726 locations.");
1727
1728   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1729    [InitBasicFS, Always, TestOutputList (
1730       [["upload"; "test-command"; "/test-command"];
1731        ["chmod"; "0o755"; "/test-command"];
1732        ["command_lines"; "/test-command 1"]], ["Result1"]);
1733     InitBasicFS, Always, TestOutputList (
1734       [["upload"; "test-command"; "/test-command"];
1735        ["chmod"; "0o755"; "/test-command"];
1736        ["command_lines"; "/test-command 2"]], ["Result2"]);
1737     InitBasicFS, Always, TestOutputList (
1738       [["upload"; "test-command"; "/test-command"];
1739        ["chmod"; "0o755"; "/test-command"];
1740        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1741     InitBasicFS, Always, TestOutputList (
1742       [["upload"; "test-command"; "/test-command"];
1743        ["chmod"; "0o755"; "/test-command"];
1744        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1745     InitBasicFS, Always, TestOutputList (
1746       [["upload"; "test-command"; "/test-command"];
1747        ["chmod"; "0o755"; "/test-command"];
1748        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1749     InitBasicFS, Always, TestOutputList (
1750       [["upload"; "test-command"; "/test-command"];
1751        ["chmod"; "0o755"; "/test-command"];
1752        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1753     InitBasicFS, Always, TestOutputList (
1754       [["upload"; "test-command"; "/test-command"];
1755        ["chmod"; "0o755"; "/test-command"];
1756        ["command_lines"; "/test-command 7"]], []);
1757     InitBasicFS, Always, TestOutputList (
1758       [["upload"; "test-command"; "/test-command"];
1759        ["chmod"; "0o755"; "/test-command"];
1760        ["command_lines"; "/test-command 8"]], [""]);
1761     InitBasicFS, Always, TestOutputList (
1762       [["upload"; "test-command"; "/test-command"];
1763        ["chmod"; "0o755"; "/test-command"];
1764        ["command_lines"; "/test-command 9"]], ["";""]);
1765     InitBasicFS, Always, TestOutputList (
1766       [["upload"; "test-command"; "/test-command"];
1767        ["chmod"; "0o755"; "/test-command"];
1768        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1769     InitBasicFS, Always, TestOutputList (
1770       [["upload"; "test-command"; "/test-command"];
1771        ["chmod"; "0o755"; "/test-command"];
1772        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1773    "run a command, returning lines",
1774    "\
1775 This is the same as C<guestfs_command>, but splits the
1776 result into a list of lines.
1777
1778 See also: C<guestfs_sh_lines>");
1779
1780   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as the C<stat(2)> system call.");
1788
1789   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1790    [InitISOFS, Always, TestOutputStruct (
1791       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1792    "get file information for a symbolic link",
1793    "\
1794 Returns file information for the given C<path>.
1795
1796 This is the same as C<guestfs_stat> except that if C<path>
1797 is a symbolic link, then the link is stat-ed, not the file it
1798 refers to.
1799
1800 This is the same as the C<lstat(2)> system call.");
1801
1802   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1803    [InitISOFS, Always, TestOutputStruct (
1804       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1805    "get file system statistics",
1806    "\
1807 Returns file system statistics for any mounted file system.
1808 C<path> should be a file or directory in the mounted file system
1809 (typically it is the mount point itself, but it doesn't need to be).
1810
1811 This is the same as the C<statvfs(2)> system call.");
1812
1813   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1814    [], (* XXX test *)
1815    "get ext2/ext3/ext4 superblock details",
1816    "\
1817 This returns the contents of the ext2, ext3 or ext4 filesystem
1818 superblock on C<device>.
1819
1820 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1821 manpage for more details.  The list of fields returned isn't
1822 clearly defined, and depends on both the version of C<tune2fs>
1823 that libguestfs was built against, and the filesystem itself.");
1824
1825   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1826    [InitEmpty, Always, TestOutputTrue (
1827       [["blockdev_setro"; "/dev/sda"];
1828        ["blockdev_getro"; "/dev/sda"]])],
1829    "set block device to read-only",
1830    "\
1831 Sets the block device named C<device> to read-only.
1832
1833 This uses the L<blockdev(8)> command.");
1834
1835   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1836    [InitEmpty, Always, TestOutputFalse (
1837       [["blockdev_setrw"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "set block device to read-write",
1840    "\
1841 Sets the block device named C<device> to read-write.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1846    [InitEmpty, Always, TestOutputTrue (
1847       [["blockdev_setro"; "/dev/sda"];
1848        ["blockdev_getro"; "/dev/sda"]])],
1849    "is block device set to read-only",
1850    "\
1851 Returns a boolean indicating if the block device is read-only
1852 (true if read-only, false if not).
1853
1854 This uses the L<blockdev(8)> command.");
1855
1856   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1857    [InitEmpty, Always, TestOutputInt (
1858       [["blockdev_getss"; "/dev/sda"]], 512)],
1859    "get sectorsize of block device",
1860    "\
1861 This returns the size of sectors on a block device.
1862 Usually 512, but can be larger for modern devices.
1863
1864 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1865 for that).
1866
1867 This uses the L<blockdev(8)> command.");
1868
1869   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1870    [InitEmpty, Always, TestOutputInt (
1871       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1872    "get blocksize of block device",
1873    "\
1874 This returns the block size of a device.
1875
1876 (Note this is different from both I<size in blocks> and
1877 I<filesystem block size>).
1878
1879 This uses the L<blockdev(8)> command.");
1880
1881   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1882    [], (* XXX test *)
1883    "set blocksize of block device",
1884    "\
1885 This sets the block size of a device.
1886
1887 (Note this is different from both I<size in blocks> and
1888 I<filesystem block size>).
1889
1890 This uses the L<blockdev(8)> command.");
1891
1892   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1893    [InitEmpty, Always, TestOutputInt (
1894       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1895    "get total size of device in 512-byte sectors",
1896    "\
1897 This returns the size of the device in units of 512-byte sectors
1898 (even if the sectorsize isn't 512 bytes ... weird).
1899
1900 See also C<guestfs_blockdev_getss> for the real sector size of
1901 the device, and C<guestfs_blockdev_getsize64> for the more
1902 useful I<size in bytes>.
1903
1904 This uses the L<blockdev(8)> command.");
1905
1906   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1907    [InitEmpty, Always, TestOutputInt (
1908       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1909    "get total size of device in bytes",
1910    "\
1911 This returns the size of the device in bytes.
1912
1913 See also C<guestfs_blockdev_getsz>.
1914
1915 This uses the L<blockdev(8)> command.");
1916
1917   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1918    [InitEmpty, Always, TestRun
1919       [["blockdev_flushbufs"; "/dev/sda"]]],
1920    "flush device buffers",
1921    "\
1922 This tells the kernel to flush internal buffers associated
1923 with C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1928    [InitEmpty, Always, TestRun
1929       [["blockdev_rereadpt"; "/dev/sda"]]],
1930    "reread partition table",
1931    "\
1932 Reread the partition table on C<device>.
1933
1934 This uses the L<blockdev(8)> command.");
1935
1936   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1937    [InitBasicFS, Always, TestOutput (
1938       (* Pick a file from cwd which isn't likely to change. *)
1939       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1940        ["checksum"; "md5"; "/COPYING.LIB"]],
1941       Digest.to_hex (Digest.file "COPYING.LIB"))],
1942    "upload a file from the local machine",
1943    "\
1944 Upload local file C<filename> to C<remotefilename> on the
1945 filesystem.
1946
1947 C<filename> can also be a named pipe.
1948
1949 See also C<guestfs_download>.");
1950
1951   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1952    [InitBasicFS, Always, TestOutput (
1953       (* Pick a file from cwd which isn't likely to change. *)
1954       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1955        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1956        ["upload"; "testdownload.tmp"; "/upload"];
1957        ["checksum"; "md5"; "/upload"]],
1958       Digest.to_hex (Digest.file "COPYING.LIB"))],
1959    "download a file to the local machine",
1960    "\
1961 Download file C<remotefilename> and save it as C<filename>
1962 on the local machine.
1963
1964 C<filename> can also be a named pipe.
1965
1966 See also C<guestfs_upload>, C<guestfs_cat>.");
1967
1968   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1969    [InitISOFS, Always, TestOutput (
1970       [["checksum"; "crc"; "/known-3"]], "2891671662");
1971     InitISOFS, Always, TestLastFail (
1972       [["checksum"; "crc"; "/notexists"]]);
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1977     InitISOFS, Always, TestOutput (
1978       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1979     InitISOFS, Always, TestOutput (
1980       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1981     InitISOFS, Always, TestOutput (
1982       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1985    "compute MD5, SHAx or CRC checksum of file",
1986    "\
1987 This call computes the MD5, SHAx or CRC checksum of the
1988 file named C<path>.
1989
1990 The type of checksum to compute is given by the C<csumtype>
1991 parameter which must have one of the following values:
1992
1993 =over 4
1994
1995 =item C<crc>
1996
1997 Compute the cyclic redundancy check (CRC) specified by POSIX
1998 for the C<cksum> command.
1999
2000 =item C<md5>
2001
2002 Compute the MD5 hash (using the C<md5sum> program).
2003
2004 =item C<sha1>
2005
2006 Compute the SHA1 hash (using the C<sha1sum> program).
2007
2008 =item C<sha224>
2009
2010 Compute the SHA224 hash (using the C<sha224sum> program).
2011
2012 =item C<sha256>
2013
2014 Compute the SHA256 hash (using the C<sha256sum> program).
2015
2016 =item C<sha384>
2017
2018 Compute the SHA384 hash (using the C<sha384sum> program).
2019
2020 =item C<sha512>
2021
2022 Compute the SHA512 hash (using the C<sha512sum> program).
2023
2024 =back
2025
2026 The checksum is returned as a printable string.");
2027
2028   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2029    [InitBasicFS, Always, TestOutput (
2030       [["tar_in"; "../images/helloworld.tar"; "/"];
2031        ["cat"; "/hello"]], "hello\n")],
2032    "unpack tarfile to directory",
2033    "\
2034 This command uploads and unpacks local file C<tarfile> (an
2035 I<uncompressed> tar file) into C<directory>.
2036
2037 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2038
2039   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2040    [],
2041    "pack directory into tarfile",
2042    "\
2043 This command packs the contents of C<directory> and downloads
2044 it to local file C<tarfile>.
2045
2046 To download a compressed tarball, use C<guestfs_tgz_out>.");
2047
2048   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2049    [InitBasicFS, Always, TestOutput (
2050       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2051        ["cat"; "/hello"]], "hello\n")],
2052    "unpack compressed tarball to directory",
2053    "\
2054 This command uploads and unpacks local file C<tarball> (a
2055 I<gzip compressed> tar file) into C<directory>.
2056
2057 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2058
2059   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2060    [],
2061    "pack directory into compressed tarball",
2062    "\
2063 This command packs the contents of C<directory> and downloads
2064 it to local file C<tarball>.
2065
2066 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2067
2068   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2069    [InitBasicFS, Always, TestLastFail (
2070       [["umount"; "/"];
2071        ["mount_ro"; "/dev/sda1"; "/"];
2072        ["touch"; "/new"]]);
2073     InitBasicFS, Always, TestOutput (
2074       [["write_file"; "/new"; "data"; "0"];
2075        ["umount"; "/"];
2076        ["mount_ro"; "/dev/sda1"; "/"];
2077        ["cat"; "/new"]], "data")],
2078    "mount a guest disk, read-only",
2079    "\
2080 This is the same as the C<guestfs_mount> command, but it
2081 mounts the filesystem with the read-only (I<-o ro>) flag.");
2082
2083   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2084    [],
2085    "mount a guest disk with mount options",
2086    "\
2087 This is the same as the C<guestfs_mount> command, but it
2088 allows you to set the mount options as for the
2089 L<mount(8)> I<-o> flag.
2090
2091 If the C<options> parameter is an empty string, then
2092 no options are passed (all options default to whatever
2093 the filesystem uses).");
2094
2095   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2096    [],
2097    "mount a guest disk with mount options and vfstype",
2098    "\
2099 This is the same as the C<guestfs_mount> command, but it
2100 allows you to set both the mount options and the vfstype
2101 as for the L<mount(8)> I<-o> and I<-t> flags.");
2102
2103   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2104    [],
2105    "debugging and internals",
2106    "\
2107 The C<guestfs_debug> command exposes some internals of
2108 C<guestfsd> (the guestfs daemon) that runs inside the
2109 qemu subprocess.
2110
2111 There is no comprehensive help for this command.  You have
2112 to look at the file C<daemon/debug.c> in the libguestfs source
2113 to find out what you can do.");
2114
2115   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2116    [InitEmpty, Always, TestOutputList (
2117       [["part_disk"; "/dev/sda"; "mbr"];
2118        ["pvcreate"; "/dev/sda1"];
2119        ["vgcreate"; "VG"; "/dev/sda1"];
2120        ["lvcreate"; "LV1"; "VG"; "50"];
2121        ["lvcreate"; "LV2"; "VG"; "50"];
2122        ["lvremove"; "/dev/VG/LV1"];
2123        ["lvs"]], ["/dev/VG/LV2"]);
2124     InitEmpty, Always, TestOutputList (
2125       [["part_disk"; "/dev/sda"; "mbr"];
2126        ["pvcreate"; "/dev/sda1"];
2127        ["vgcreate"; "VG"; "/dev/sda1"];
2128        ["lvcreate"; "LV1"; "VG"; "50"];
2129        ["lvcreate"; "LV2"; "VG"; "50"];
2130        ["lvremove"; "/dev/VG"];
2131        ["lvs"]], []);
2132     InitEmpty, Always, TestOutputList (
2133       [["part_disk"; "/dev/sda"; "mbr"];
2134        ["pvcreate"; "/dev/sda1"];
2135        ["vgcreate"; "VG"; "/dev/sda1"];
2136        ["lvcreate"; "LV1"; "VG"; "50"];
2137        ["lvcreate"; "LV2"; "VG"; "50"];
2138        ["lvremove"; "/dev/VG"];
2139        ["vgs"]], ["VG"])],
2140    "remove an LVM logical volume",
2141    "\
2142 Remove an LVM logical volume C<device>, where C<device> is
2143 the path to the LV, such as C</dev/VG/LV>.
2144
2145 You can also remove all LVs in a volume group by specifying
2146 the VG name, C</dev/VG>.");
2147
2148   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2149    [InitEmpty, Always, TestOutputList (
2150       [["part_disk"; "/dev/sda"; "mbr"];
2151        ["pvcreate"; "/dev/sda1"];
2152        ["vgcreate"; "VG"; "/dev/sda1"];
2153        ["lvcreate"; "LV1"; "VG"; "50"];
2154        ["lvcreate"; "LV2"; "VG"; "50"];
2155        ["vgremove"; "VG"];
2156        ["lvs"]], []);
2157     InitEmpty, Always, TestOutputList (
2158       [["part_disk"; "/dev/sda"; "mbr"];
2159        ["pvcreate"; "/dev/sda1"];
2160        ["vgcreate"; "VG"; "/dev/sda1"];
2161        ["lvcreate"; "LV1"; "VG"; "50"];
2162        ["lvcreate"; "LV2"; "VG"; "50"];
2163        ["vgremove"; "VG"];
2164        ["vgs"]], [])],
2165    "remove an LVM volume group",
2166    "\
2167 Remove an LVM volume group C<vgname>, (for example C<VG>).
2168
2169 This also forcibly removes all logical volumes in the volume
2170 group (if any).");
2171
2172   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2173    [InitEmpty, Always, TestOutputListOfDevices (
2174       [["part_disk"; "/dev/sda"; "mbr"];
2175        ["pvcreate"; "/dev/sda1"];
2176        ["vgcreate"; "VG"; "/dev/sda1"];
2177        ["lvcreate"; "LV1"; "VG"; "50"];
2178        ["lvcreate"; "LV2"; "VG"; "50"];
2179        ["vgremove"; "VG"];
2180        ["pvremove"; "/dev/sda1"];
2181        ["lvs"]], []);
2182     InitEmpty, Always, TestOutputListOfDevices (
2183       [["part_disk"; "/dev/sda"; "mbr"];
2184        ["pvcreate"; "/dev/sda1"];
2185        ["vgcreate"; "VG"; "/dev/sda1"];
2186        ["lvcreate"; "LV1"; "VG"; "50"];
2187        ["lvcreate"; "LV2"; "VG"; "50"];
2188        ["vgremove"; "VG"];
2189        ["pvremove"; "/dev/sda1"];
2190        ["vgs"]], []);
2191     InitEmpty, Always, TestOutputListOfDevices (
2192       [["part_disk"; "/dev/sda"; "mbr"];
2193        ["pvcreate"; "/dev/sda1"];
2194        ["vgcreate"; "VG"; "/dev/sda1"];
2195        ["lvcreate"; "LV1"; "VG"; "50"];
2196        ["lvcreate"; "LV2"; "VG"; "50"];
2197        ["vgremove"; "VG"];
2198        ["pvremove"; "/dev/sda1"];
2199        ["pvs"]], [])],
2200    "remove an LVM physical volume",
2201    "\
2202 This wipes a physical volume C<device> so that LVM will no longer
2203 recognise it.
2204
2205 The implementation uses the C<pvremove> command which refuses to
2206 wipe physical volumes that contain any volume groups, so you have
2207 to remove those first.");
2208
2209   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2210    [InitBasicFS, Always, TestOutput (
2211       [["set_e2label"; "/dev/sda1"; "testlabel"];
2212        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2213    "set the ext2/3/4 filesystem label",
2214    "\
2215 This sets the ext2/3/4 filesystem label of the filesystem on
2216 C<device> to C<label>.  Filesystem labels are limited to
2217 16 characters.
2218
2219 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2220 to return the existing label on a filesystem.");
2221
2222   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2223    [],
2224    "get the ext2/3/4 filesystem label",
2225    "\
2226 This returns the ext2/3/4 filesystem label of the filesystem on
2227 C<device>.");
2228
2229   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2230    (let uuid = uuidgen () in
2231     [InitBasicFS, Always, TestOutput (
2232        [["set_e2uuid"; "/dev/sda1"; uuid];
2233         ["get_e2uuid"; "/dev/sda1"]], uuid);
2234      InitBasicFS, Always, TestOutput (
2235        [["set_e2uuid"; "/dev/sda1"; "clear"];
2236         ["get_e2uuid"; "/dev/sda1"]], "");
2237      (* We can't predict what UUIDs will be, so just check the commands run. *)
2238      InitBasicFS, Always, TestRun (
2239        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2240      InitBasicFS, Always, TestRun (
2241        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2242    "set the ext2/3/4 filesystem UUID",
2243    "\
2244 This sets the ext2/3/4 filesystem UUID of the filesystem on
2245 C<device> to C<uuid>.  The format of the UUID and alternatives
2246 such as C<clear>, C<random> and C<time> are described in the
2247 L<tune2fs(8)> manpage.
2248
2249 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2250 to return the existing UUID of a filesystem.");
2251
2252   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2253    [],
2254    "get the ext2/3/4 filesystem UUID",
2255    "\
2256 This returns the ext2/3/4 filesystem UUID of the filesystem on
2257 C<device>.");
2258
2259   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2260    [InitBasicFS, Always, TestOutputInt (
2261       [["umount"; "/dev/sda1"];
2262        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2263     InitBasicFS, Always, TestOutputInt (
2264       [["umount"; "/dev/sda1"];
2265        ["zero"; "/dev/sda1"];
2266        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2267    "run the filesystem checker",
2268    "\
2269 This runs the filesystem checker (fsck) on C<device> which
2270 should have filesystem type C<fstype>.
2271
2272 The returned integer is the status.  See L<fsck(8)> for the
2273 list of status codes from C<fsck>.
2274
2275 Notes:
2276
2277 =over 4
2278
2279 =item *
2280
2281 Multiple status codes can be summed together.
2282
2283 =item *
2284
2285 A non-zero return code can mean \"success\", for example if
2286 errors have been corrected on the filesystem.
2287
2288 =item *
2289
2290 Checking or repairing NTFS volumes is not supported
2291 (by linux-ntfs).
2292
2293 =back
2294
2295 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2296
2297   ("zero", (RErr, [Device "device"]), 85, [],
2298    [InitBasicFS, Always, TestOutput (
2299       [["umount"; "/dev/sda1"];
2300        ["zero"; "/dev/sda1"];
2301        ["file"; "/dev/sda1"]], "data")],
2302    "write zeroes to the device",
2303    "\
2304 This command writes zeroes over the first few blocks of C<device>.
2305
2306 How many blocks are zeroed isn't specified (but it's I<not> enough
2307 to securely wipe the device).  It should be sufficient to remove
2308 any partition tables, filesystem superblocks and so on.
2309
2310 See also: C<guestfs_scrub_device>.");
2311
2312   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2313    (* Test disabled because grub-install incompatible with virtio-blk driver.
2314     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2315     *)
2316    [InitBasicFS, Disabled, TestOutputTrue (
2317       [["grub_install"; "/"; "/dev/sda1"];
2318        ["is_dir"; "/boot"]])],
2319    "install GRUB",
2320    "\
2321 This command installs GRUB (the Grand Unified Bootloader) on
2322 C<device>, with the root directory being C<root>.");
2323
2324   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2325    [InitBasicFS, Always, TestOutput (
2326       [["write_file"; "/old"; "file content"; "0"];
2327        ["cp"; "/old"; "/new"];
2328        ["cat"; "/new"]], "file content");
2329     InitBasicFS, Always, TestOutputTrue (
2330       [["write_file"; "/old"; "file content"; "0"];
2331        ["cp"; "/old"; "/new"];
2332        ["is_file"; "/old"]]);
2333     InitBasicFS, Always, TestOutput (
2334       [["write_file"; "/old"; "file content"; "0"];
2335        ["mkdir"; "/dir"];
2336        ["cp"; "/old"; "/dir/new"];
2337        ["cat"; "/dir/new"]], "file content")],
2338    "copy a file",
2339    "\
2340 This copies a file from C<src> to C<dest> where C<dest> is
2341 either a destination filename or destination directory.");
2342
2343   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2344    [InitBasicFS, Always, TestOutput (
2345       [["mkdir"; "/olddir"];
2346        ["mkdir"; "/newdir"];
2347        ["write_file"; "/olddir/file"; "file content"; "0"];
2348        ["cp_a"; "/olddir"; "/newdir"];
2349        ["cat"; "/newdir/olddir/file"]], "file content")],
2350    "copy a file or directory recursively",
2351    "\
2352 This copies a file or directory from C<src> to C<dest>
2353 recursively using the C<cp -a> command.");
2354
2355   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2356    [InitBasicFS, Always, TestOutput (
2357       [["write_file"; "/old"; "file content"; "0"];
2358        ["mv"; "/old"; "/new"];
2359        ["cat"; "/new"]], "file content");
2360     InitBasicFS, Always, TestOutputFalse (
2361       [["write_file"; "/old"; "file content"; "0"];
2362        ["mv"; "/old"; "/new"];
2363        ["is_file"; "/old"]])],
2364    "move a file",
2365    "\
2366 This moves a file from C<src> to C<dest> where C<dest> is
2367 either a destination filename or destination directory.");
2368
2369   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2370    [InitEmpty, Always, TestRun (
2371       [["drop_caches"; "3"]])],
2372    "drop kernel page cache, dentries and inodes",
2373    "\
2374 This instructs the guest kernel to drop its page cache,
2375 and/or dentries and inode caches.  The parameter C<whattodrop>
2376 tells the kernel what precisely to drop, see
2377 L<http://linux-mm.org/Drop_Caches>
2378
2379 Setting C<whattodrop> to 3 should drop everything.
2380
2381 This automatically calls L<sync(2)> before the operation,
2382 so that the maximum guest memory is freed.");
2383
2384   ("dmesg", (RString "kmsgs", []), 91, [],
2385    [InitEmpty, Always, TestRun (
2386       [["dmesg"]])],
2387    "return kernel messages",
2388    "\
2389 This returns the kernel messages (C<dmesg> output) from
2390 the guest kernel.  This is sometimes useful for extended
2391 debugging of problems.
2392
2393 Another way to get the same information is to enable
2394 verbose messages with C<guestfs_set_verbose> or by setting
2395 the environment variable C<LIBGUESTFS_DEBUG=1> before
2396 running the program.");
2397
2398   ("ping_daemon", (RErr, []), 92, [],
2399    [InitEmpty, Always, TestRun (
2400       [["ping_daemon"]])],
2401    "ping the guest daemon",
2402    "\
2403 This is a test probe into the guestfs daemon running inside
2404 the qemu subprocess.  Calling this function checks that the
2405 daemon responds to the ping message, without affecting the daemon
2406 or attached block device(s) in any other way.");
2407
2408   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2409    [InitBasicFS, Always, TestOutputTrue (
2410       [["write_file"; "/file1"; "contents of a file"; "0"];
2411        ["cp"; "/file1"; "/file2"];
2412        ["equal"; "/file1"; "/file2"]]);
2413     InitBasicFS, Always, TestOutputFalse (
2414       [["write_file"; "/file1"; "contents of a file"; "0"];
2415        ["write_file"; "/file2"; "contents of another file"; "0"];
2416        ["equal"; "/file1"; "/file2"]]);
2417     InitBasicFS, Always, TestLastFail (
2418       [["equal"; "/file1"; "/file2"]])],
2419    "test if two files have equal contents",
2420    "\
2421 This compares the two files C<file1> and C<file2> and returns
2422 true if their content is exactly equal, or false otherwise.
2423
2424 The external L<cmp(1)> program is used for the comparison.");
2425
2426   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2427    [InitISOFS, Always, TestOutputList (
2428       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2429     InitISOFS, Always, TestOutputList (
2430       [["strings"; "/empty"]], [])],
2431    "print the printable strings in a file",
2432    "\
2433 This runs the L<strings(1)> command on a file and returns
2434 the list of printable strings found.");
2435
2436   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2437    [InitISOFS, Always, TestOutputList (
2438       [["strings_e"; "b"; "/known-5"]], []);
2439     InitBasicFS, Disabled, TestOutputList (
2440       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2441        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2442    "print the printable strings in a file",
2443    "\
2444 This is like the C<guestfs_strings> command, but allows you to
2445 specify the encoding.
2446
2447 See the L<strings(1)> manpage for the full list of encodings.
2448
2449 Commonly useful encodings are C<l> (lower case L) which will
2450 show strings inside Windows/x86 files.
2451
2452 The returned strings are transcoded to UTF-8.");
2453
2454   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2455    [InitISOFS, Always, TestOutput (
2456       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2457     (* Test for RHBZ#501888c2 regression which caused large hexdump
2458      * commands to segfault.
2459      *)
2460     InitISOFS, Always, TestRun (
2461       [["hexdump"; "/100krandom"]])],
2462    "dump a file in hexadecimal",
2463    "\
2464 This runs C<hexdump -C> on the given C<path>.  The result is
2465 the human-readable, canonical hex dump of the file.");
2466
2467   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2468    [InitNone, Always, TestOutput (
2469       [["part_disk"; "/dev/sda"; "mbr"];
2470        ["mkfs"; "ext3"; "/dev/sda1"];
2471        ["mount_options"; ""; "/dev/sda1"; "/"];
2472        ["write_file"; "/new"; "test file"; "0"];
2473        ["umount"; "/dev/sda1"];
2474        ["zerofree"; "/dev/sda1"];
2475        ["mount_options"; ""; "/dev/sda1"; "/"];
2476        ["cat"; "/new"]], "test file")],
2477    "zero unused inodes and disk blocks on ext2/3 filesystem",
2478    "\
2479 This runs the I<zerofree> program on C<device>.  This program
2480 claims to zero unused inodes and disk blocks on an ext2/3
2481 filesystem, thus making it possible to compress the filesystem
2482 more effectively.
2483
2484 You should B<not> run this program if the filesystem is
2485 mounted.
2486
2487 It is possible that using this program can damage the filesystem
2488 or data on the filesystem.");
2489
2490   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2491    [],
2492    "resize an LVM physical volume",
2493    "\
2494 This resizes (expands or shrinks) an existing LVM physical
2495 volume to match the new size of the underlying device.");
2496
2497   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2498                        Int "cyls"; Int "heads"; Int "sectors";
2499                        String "line"]), 99, [DangerWillRobinson],
2500    [],
2501    "modify a single partition on a block device",
2502    "\
2503 This runs L<sfdisk(8)> option to modify just the single
2504 partition C<n> (note: C<n> counts from 1).
2505
2506 For other parameters, see C<guestfs_sfdisk>.  You should usually
2507 pass C<0> for the cyls/heads/sectors parameters.
2508
2509 See also: C<guestfs_part_add>");
2510
2511   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2512    [],
2513    "display the partition table",
2514    "\
2515 This displays the partition table on C<device>, in the
2516 human-readable output of the L<sfdisk(8)> command.  It is
2517 not intended to be parsed.
2518
2519 See also: C<guestfs_part_list>");
2520
2521   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2522    [],
2523    "display the kernel geometry",
2524    "\
2525 This displays the kernel's idea of the geometry of C<device>.
2526
2527 The result is in human-readable format, and not designed to
2528 be parsed.");
2529
2530   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2531    [],
2532    "display the disk geometry from the partition table",
2533    "\
2534 This displays the disk geometry of C<device> read from the
2535 partition table.  Especially in the case where the underlying
2536 block device has been resized, this can be different from the
2537 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2538
2539 The result is in human-readable format, and not designed to
2540 be parsed.");
2541
2542   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2543    [],
2544    "activate or deactivate all volume groups",
2545    "\
2546 This command activates or (if C<activate> is false) deactivates
2547 all logical volumes in all volume groups.
2548 If activated, then they are made known to the
2549 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2550 then those devices disappear.
2551
2552 This command is the same as running C<vgchange -a y|n>");
2553
2554   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2555    [],
2556    "activate or deactivate some volume groups",
2557    "\
2558 This command activates or (if C<activate> is false) deactivates
2559 all logical volumes in the listed volume groups C<volgroups>.
2560 If activated, then they are made known to the
2561 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2562 then those devices disappear.
2563
2564 This command is the same as running C<vgchange -a y|n volgroups...>
2565
2566 Note that if C<volgroups> is an empty list then B<all> volume groups
2567 are activated or deactivated.");
2568
2569   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2570    [InitNone, Always, TestOutput (
2571       [["part_disk"; "/dev/sda"; "mbr"];
2572        ["pvcreate"; "/dev/sda1"];
2573        ["vgcreate"; "VG"; "/dev/sda1"];
2574        ["lvcreate"; "LV"; "VG"; "10"];
2575        ["mkfs"; "ext2"; "/dev/VG/LV"];
2576        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2577        ["write_file"; "/new"; "test content"; "0"];
2578        ["umount"; "/"];
2579        ["lvresize"; "/dev/VG/LV"; "20"];
2580        ["e2fsck_f"; "/dev/VG/LV"];
2581        ["resize2fs"; "/dev/VG/LV"];
2582        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2583        ["cat"; "/new"]], "test content");
2584     InitNone, Always, TestRun (
2585       (* Make an LV smaller to test RHBZ#587484. *)
2586       [["part_disk"; "/dev/sda"; "mbr"];
2587        ["pvcreate"; "/dev/sda1"];
2588        ["vgcreate"; "VG"; "/dev/sda1"];
2589        ["lvcreate"; "LV"; "VG"; "20"];
2590        ["lvresize"; "/dev/VG/LV"; "10"]])],
2591    "resize an LVM logical volume",
2592    "\
2593 This resizes (expands or shrinks) an existing LVM logical
2594 volume to C<mbytes>.  When reducing, data in the reduced part
2595 is lost.");
2596
2597   ("resize2fs", (RErr, [Device "device"]), 106, [],
2598    [], (* lvresize tests this *)
2599    "resize an ext2/ext3 filesystem",
2600    "\
2601 This resizes an ext2 or ext3 filesystem to match the size of
2602 the underlying device.
2603
2604 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2605 on the C<device> before calling this command.  For unknown reasons
2606 C<resize2fs> sometimes gives an error about this and sometimes not.
2607 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2608 calling this function.");
2609
2610   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2611    [InitBasicFS, Always, TestOutputList (
2612       [["find"; "/"]], ["lost+found"]);
2613     InitBasicFS, Always, TestOutputList (
2614       [["touch"; "/a"];
2615        ["mkdir"; "/b"];
2616        ["touch"; "/b/c"];
2617        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2618     InitBasicFS, Always, TestOutputList (
2619       [["mkdir_p"; "/a/b/c"];
2620        ["touch"; "/a/b/c/d"];
2621        ["find"; "/a/b/"]], ["c"; "c/d"])],
2622    "find all files and directories",
2623    "\
2624 This command lists out all files and directories, recursively,
2625 starting at C<directory>.  It is essentially equivalent to
2626 running the shell command C<find directory -print> but some
2627 post-processing happens on the output, described below.
2628
2629 This returns a list of strings I<without any prefix>.  Thus
2630 if the directory structure was:
2631
2632  /tmp/a
2633  /tmp/b
2634  /tmp/c/d
2635
2636 then the returned list from C<guestfs_find> C</tmp> would be
2637 4 elements:
2638
2639  a
2640  b
2641  c
2642  c/d
2643
2644 If C<directory> is not a directory, then this command returns
2645 an error.
2646
2647 The returned list is sorted.
2648
2649 See also C<guestfs_find0>.");
2650
2651   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2652    [], (* lvresize tests this *)
2653    "check an ext2/ext3 filesystem",
2654    "\
2655 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2656 filesystem checker on C<device>, noninteractively (C<-p>),
2657 even if the filesystem appears to be clean (C<-f>).
2658
2659 This command is only needed because of C<guestfs_resize2fs>
2660 (q.v.).  Normally you should use C<guestfs_fsck>.");
2661
2662   ("sleep", (RErr, [Int "secs"]), 109, [],
2663    [InitNone, Always, TestRun (
2664       [["sleep"; "1"]])],
2665    "sleep for some seconds",
2666    "\
2667 Sleep for C<secs> seconds.");
2668
2669   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2670    [InitNone, Always, TestOutputInt (
2671       [["part_disk"; "/dev/sda"; "mbr"];
2672        ["mkfs"; "ntfs"; "/dev/sda1"];
2673        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2674     InitNone, Always, TestOutputInt (
2675       [["part_disk"; "/dev/sda"; "mbr"];
2676        ["mkfs"; "ext2"; "/dev/sda1"];
2677        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2678    "probe NTFS volume",
2679    "\
2680 This command runs the L<ntfs-3g.probe(8)> command which probes
2681 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2682 be mounted read-write, and some cannot be mounted at all).
2683
2684 C<rw> is a boolean flag.  Set it to true if you want to test
2685 if the volume can be mounted read-write.  Set it to false if
2686 you want to test if the volume can be mounted read-only.
2687
2688 The return value is an integer which C<0> if the operation
2689 would succeed, or some non-zero value documented in the
2690 L<ntfs-3g.probe(8)> manual page.");
2691
2692   ("sh", (RString "output", [String "command"]), 111, [],
2693    [], (* XXX needs tests *)
2694    "run a command via the shell",
2695    "\
2696 This call runs a command from the guest filesystem via the
2697 guest's C</bin/sh>.
2698
2699 This is like C<guestfs_command>, but passes the command to:
2700
2701  /bin/sh -c \"command\"
2702
2703 Depending on the guest's shell, this usually results in
2704 wildcards being expanded, shell expressions being interpolated
2705 and so on.
2706
2707 All the provisos about C<guestfs_command> apply to this call.");
2708
2709   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2710    [], (* XXX needs tests *)
2711    "run a command via the shell returning lines",
2712    "\
2713 This is the same as C<guestfs_sh>, but splits the result
2714 into a list of lines.
2715
2716 See also: C<guestfs_command_lines>");
2717
2718   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2719    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2720     * code in stubs.c, since all valid glob patterns must start with "/".
2721     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2722     *)
2723    [InitBasicFS, Always, TestOutputList (
2724       [["mkdir_p"; "/a/b/c"];
2725        ["touch"; "/a/b/c/d"];
2726        ["touch"; "/a/b/c/e"];
2727        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2728     InitBasicFS, Always, TestOutputList (
2729       [["mkdir_p"; "/a/b/c"];
2730        ["touch"; "/a/b/c/d"];
2731        ["touch"; "/a/b/c/e"];
2732        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2733     InitBasicFS, Always, TestOutputList (
2734       [["mkdir_p"; "/a/b/c"];
2735        ["touch"; "/a/b/c/d"];
2736        ["touch"; "/a/b/c/e"];
2737        ["glob_expand"; "/a/*/x/*"]], [])],
2738    "expand a wildcard path",
2739    "\
2740 This command searches for all the pathnames matching
2741 C<pattern> according to the wildcard expansion rules
2742 used by the shell.
2743
2744 If no paths match, then this returns an empty list
2745 (note: not an error).
2746
2747 It is just a wrapper around the C L<glob(3)> function
2748 with flags C<GLOB_MARK|GLOB_BRACE>.
2749 See that manual page for more details.");
2750
2751   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2752    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2753       [["scrub_device"; "/dev/sdc"]])],
2754    "scrub (securely wipe) a device",
2755    "\
2756 This command writes patterns over C<device> to make data retrieval
2757 more difficult.
2758
2759 It is an interface to the L<scrub(1)> program.  See that
2760 manual page for more details.");
2761
2762   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2763    [InitBasicFS, Always, TestRun (
2764       [["write_file"; "/file"; "content"; "0"];
2765        ["scrub_file"; "/file"]])],
2766    "scrub (securely wipe) a file",
2767    "\
2768 This command writes patterns over a file to make data retrieval
2769 more difficult.
2770
2771 The file is I<removed> after scrubbing.
2772
2773 It is an interface to the L<scrub(1)> program.  See that
2774 manual page for more details.");
2775
2776   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2777    [], (* XXX needs testing *)
2778    "scrub (securely wipe) free space",
2779    "\
2780 This command creates the directory C<dir> and then fills it
2781 with files until the filesystem is full, and scrubs the files
2782 as for C<guestfs_scrub_file>, and deletes them.
2783 The intention is to scrub any free space on the partition
2784 containing C<dir>.
2785
2786 It is an interface to the L<scrub(1)> program.  See that
2787 manual page for more details.");
2788
2789   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2790    [InitBasicFS, Always, TestRun (
2791       [["mkdir"; "/tmp"];
2792        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2793    "create a temporary directory",
2794    "\
2795 This command creates a temporary directory.  The
2796 C<template> parameter should be a full pathname for the
2797 temporary directory name with the final six characters being
2798 \"XXXXXX\".
2799
2800 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2801 the second one being suitable for Windows filesystems.
2802
2803 The name of the temporary directory that was created
2804 is returned.
2805
2806 The temporary directory is created with mode 0700
2807 and is owned by root.
2808
2809 The caller is responsible for deleting the temporary
2810 directory and its contents after use.
2811
2812 See also: L<mkdtemp(3)>");
2813
2814   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2815    [InitISOFS, Always, TestOutputInt (
2816       [["wc_l"; "/10klines"]], 10000)],
2817    "count lines in a file",
2818    "\
2819 This command counts the lines in a file, using the
2820 C<wc -l> external command.");
2821
2822   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2823    [InitISOFS, Always, TestOutputInt (
2824       [["wc_w"; "/10klines"]], 10000)],
2825    "count words in a file",
2826    "\
2827 This command counts the words in a file, using the
2828 C<wc -w> external command.");
2829
2830   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2831    [InitISOFS, Always, TestOutputInt (
2832       [["wc_c"; "/100kallspaces"]], 102400)],
2833    "count characters in a file",
2834    "\
2835 This command counts the characters in a file, using the
2836 C<wc -c> external command.");
2837
2838   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2839    [InitISOFS, Always, TestOutputList (
2840       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2841    "return first 10 lines of a file",
2842    "\
2843 This command returns up to the first 10 lines of a file as
2844 a list of strings.");
2845
2846   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2847    [InitISOFS, Always, TestOutputList (
2848       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2849     InitISOFS, Always, TestOutputList (
2850       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2851     InitISOFS, Always, TestOutputList (
2852       [["head_n"; "0"; "/10klines"]], [])],
2853    "return first N lines of a file",
2854    "\
2855 If the parameter C<nrlines> is a positive number, this returns the first
2856 C<nrlines> lines of the file C<path>.
2857
2858 If the parameter C<nrlines> is a negative number, this returns lines
2859 from the file C<path>, excluding the last C<nrlines> lines.
2860
2861 If the parameter C<nrlines> is zero, this returns an empty list.");
2862
2863   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2864    [InitISOFS, Always, TestOutputList (
2865       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2866    "return last 10 lines of a file",
2867    "\
2868 This command returns up to the last 10 lines of a file as
2869 a list of strings.");
2870
2871   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2872    [InitISOFS, Always, TestOutputList (
2873       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2874     InitISOFS, Always, TestOutputList (
2875       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2876     InitISOFS, Always, TestOutputList (
2877       [["tail_n"; "0"; "/10klines"]], [])],
2878    "return last N lines of a file",
2879    "\
2880 If the parameter C<nrlines> is a positive number, this returns the last
2881 C<nrlines> lines of the file C<path>.
2882
2883 If the parameter C<nrlines> is a negative number, this returns lines
2884 from the file C<path>, starting with the C<-nrlines>th line.
2885
2886 If the parameter C<nrlines> is zero, this returns an empty list.");
2887
2888   ("df", (RString "output", []), 125, [],
2889    [], (* XXX Tricky to test because it depends on the exact format
2890         * of the 'df' command and other imponderables.
2891         *)
2892    "report file system disk space usage",
2893    "\
2894 This command runs the C<df> command to report disk space used.
2895
2896 This command is mostly useful for interactive sessions.  It
2897 is I<not> intended that you try to parse the output string.
2898 Use C<statvfs> from programs.");
2899
2900   ("df_h", (RString "output", []), 126, [],
2901    [], (* XXX Tricky to test because it depends on the exact format
2902         * of the 'df' command and other imponderables.
2903         *)
2904    "report file system disk space usage (human readable)",
2905    "\
2906 This command runs the C<df -h> command to report disk space used
2907 in human-readable format.
2908
2909 This command is mostly useful for interactive sessions.  It
2910 is I<not> intended that you try to parse the output string.
2911 Use C<statvfs> from programs.");
2912
2913   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2914    [InitISOFS, Always, TestOutputInt (
2915       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2916    "estimate file space usage",
2917    "\
2918 This command runs the C<du -s> command to estimate file space
2919 usage for C<path>.
2920
2921 C<path> can be a file or a directory.  If C<path> is a directory
2922 then the estimate includes the contents of the directory and all
2923 subdirectories (recursively).
2924
2925 The result is the estimated size in I<kilobytes>
2926 (ie. units of 1024 bytes).");
2927
2928   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2929    [InitISOFS, Always, TestOutputList (
2930       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2931    "list files in an initrd",
2932    "\
2933 This command lists out files contained in an initrd.
2934
2935 The files are listed without any initial C</> character.  The
2936 files are listed in the order they appear (not necessarily
2937 alphabetical).  Directory names are listed as separate items.
2938
2939 Old Linux kernels (2.4 and earlier) used a compressed ext2
2940 filesystem as initrd.  We I<only> support the newer initramfs
2941 format (compressed cpio files).");
2942
2943   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2944    [],
2945    "mount a file using the loop device",
2946    "\
2947 This command lets you mount C<file> (a filesystem image
2948 in a file) on a mount point.  It is entirely equivalent to
2949 the command C<mount -o loop file mountpoint>.");
2950
2951   ("mkswap", (RErr, [Device "device"]), 130, [],
2952    [InitEmpty, Always, TestRun (
2953       [["part_disk"; "/dev/sda"; "mbr"];
2954        ["mkswap"; "/dev/sda1"]])],
2955    "create a swap partition",
2956    "\
2957 Create a swap partition on C<device>.");
2958
2959   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2960    [InitEmpty, Always, TestRun (
2961       [["part_disk"; "/dev/sda"; "mbr"];
2962        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2963    "create a swap partition with a label",
2964    "\
2965 Create a swap partition on C<device> with label C<label>.
2966
2967 Note that you cannot attach a swap label to a block device
2968 (eg. C</dev/sda>), just to a partition.  This appears to be
2969 a limitation of the kernel or swap tools.");
2970
2971   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2972    (let uuid = uuidgen () in
2973     [InitEmpty, Always, TestRun (
2974        [["part_disk"; "/dev/sda"; "mbr"];
2975         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2976    "create a swap partition with an explicit UUID",
2977    "\
2978 Create a swap partition on C<device> with UUID C<uuid>.");
2979
2980   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2981    [InitBasicFS, Always, TestOutputStruct (
2982       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2983        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2984        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2985     InitBasicFS, Always, TestOutputStruct (
2986       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2987        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2988    "make block, character or FIFO devices",
2989    "\
2990 This call creates block or character special devices, or
2991 named pipes (FIFOs).
2992
2993 The C<mode> parameter should be the mode, using the standard
2994 constants.  C<devmajor> and C<devminor> are the
2995 device major and minor numbers, only used when creating block
2996 and character special devices.
2997
2998 Note that, just like L<mknod(2)>, the mode must be bitwise
2999 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3000 just creates a regular file).  These constants are
3001 available in the standard Linux header files, or you can use
3002 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3003 which are wrappers around this command which bitwise OR
3004 in the appropriate constant for you.
3005
3006 The mode actually set is affected by the umask.");
3007
3008   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3009    [InitBasicFS, Always, TestOutputStruct (
3010       [["mkfifo"; "0o777"; "/node"];
3011        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3012    "make FIFO (named pipe)",
3013    "\
3014 This call creates a FIFO (named pipe) called C<path> with
3015 mode C<mode>.  It is just a convenient wrapper around
3016 C<guestfs_mknod>.
3017
3018 The mode actually set is affected by the umask.");
3019
3020   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3021    [InitBasicFS, Always, TestOutputStruct (
3022       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3023        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3024    "make block device node",
3025    "\
3026 This call creates a block device node called C<path> with
3027 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3028 It is just a convenient wrapper around C<guestfs_mknod>.
3029
3030 The mode actually set is affected by the umask.");
3031
3032   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3033    [InitBasicFS, Always, TestOutputStruct (
3034       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3035        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3036    "make char device node",
3037    "\
3038 This call creates a char device node called C<path> with
3039 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3040 It is just a convenient wrapper around C<guestfs_mknod>.
3041
3042 The mode actually set is affected by the umask.");
3043
3044   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3045    [InitEmpty, Always, TestOutputInt (
3046       [["umask"; "0o22"]], 0o22)],
3047    "set file mode creation mask (umask)",
3048    "\
3049 This function sets the mask used for creating new files and
3050 device nodes to C<mask & 0777>.
3051
3052 Typical umask values would be C<022> which creates new files
3053 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3054 C<002> which creates new files with permissions like
3055 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3056
3057 The default umask is C<022>.  This is important because it
3058 means that directories and device nodes will be created with
3059 C<0644> or C<0755> mode even if you specify C<0777>.
3060
3061 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3062
3063 This call returns the previous umask.");
3064
3065   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3066    [],
3067    "read directories entries",
3068    "\
3069 This returns the list of directory entries in directory C<dir>.
3070
3071 All entries in the directory are returned, including C<.> and
3072 C<..>.  The entries are I<not> sorted, but returned in the same
3073 order as the underlying filesystem.
3074
3075 Also this call returns basic file type information about each
3076 file.  The C<ftyp> field will contain one of the following characters:
3077
3078 =over 4
3079
3080 =item 'b'
3081
3082 Block special
3083
3084 =item 'c'
3085
3086 Char special
3087
3088 =item 'd'
3089
3090 Directory
3091
3092 =item 'f'
3093
3094 FIFO (named pipe)
3095
3096 =item 'l'
3097
3098 Symbolic link
3099
3100 =item 'r'
3101
3102 Regular file
3103
3104 =item 's'
3105
3106 Socket
3107
3108 =item 'u'
3109
3110 Unknown file type
3111
3112 =item '?'
3113
3114 The L<readdir(3)> returned a C<d_type> field with an
3115 unexpected value
3116
3117 =back
3118
3119 This function is primarily intended for use by programs.  To
3120 get a simple list of names, use C<guestfs_ls>.  To get a printable
3121 directory for human consumption, use C<guestfs_ll>.");
3122
3123   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3124    [],
3125    "create partitions on a block device",
3126    "\
3127 This is a simplified interface to the C<guestfs_sfdisk>
3128 command, where partition sizes are specified in megabytes
3129 only (rounded to the nearest cylinder) and you don't need
3130 to specify the cyls, heads and sectors parameters which
3131 were rarely if ever used anyway.
3132
3133 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3134 and C<guestfs_part_disk>");
3135
3136   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3137    [],
3138    "determine file type inside a compressed file",
3139    "\
3140 This command runs C<file> after first decompressing C<path>
3141 using C<method>.
3142
3143 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3144
3145 Since 1.0.63, use C<guestfs_file> instead which can now
3146 process compressed files.");
3147
3148   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3149    [],
3150    "list extended attributes of a file or directory",
3151    "\
3152 This call lists the extended attributes of the file or directory
3153 C<path>.
3154
3155 At the system call level, this is a combination of the
3156 L<listxattr(2)> and L<getxattr(2)> calls.
3157
3158 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3159
3160   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3161    [],
3162    "list extended attributes of a file or directory",
3163    "\
3164 This is the same as C<guestfs_getxattrs>, but if C<path>
3165 is a symbolic link, then it returns the extended attributes
3166 of the link itself.");
3167
3168   ("setxattr", (RErr, [String "xattr";
3169                        String "val"; Int "vallen"; (* will be BufferIn *)
3170                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3171    [],
3172    "set extended attribute of a file or directory",
3173    "\
3174 This call sets the extended attribute named C<xattr>
3175 of the file C<path> to the value C<val> (of length C<vallen>).
3176 The value is arbitrary 8 bit data.
3177
3178 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3179
3180   ("lsetxattr", (RErr, [String "xattr";
3181                         String "val"; Int "vallen"; (* will be BufferIn *)
3182                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3183    [],
3184    "set extended attribute of a file or directory",
3185    "\
3186 This is the same as C<guestfs_setxattr>, but if C<path>
3187 is a symbolic link, then it sets an extended attribute
3188 of the link itself.");
3189
3190   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3191    [],
3192    "remove extended attribute of a file or directory",
3193    "\
3194 This call removes the extended attribute named C<xattr>
3195 of the file C<path>.
3196
3197 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3198
3199   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3200    [],
3201    "remove extended attribute of a file or directory",
3202    "\
3203 This is the same as C<guestfs_removexattr>, but if C<path>
3204 is a symbolic link, then it removes an extended attribute
3205 of the link itself.");
3206
3207   ("mountpoints", (RHashtable "mps", []), 147, [],
3208    [],
3209    "show mountpoints",
3210    "\
3211 This call is similar to C<guestfs_mounts>.  That call returns
3212 a list of devices.  This one returns a hash table (map) of
3213 device name to directory where the device is mounted.");
3214
3215   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3216    (* This is a special case: while you would expect a parameter
3217     * of type "Pathname", that doesn't work, because it implies
3218     * NEED_ROOT in the generated calling code in stubs.c, and
3219     * this function cannot use NEED_ROOT.
3220     *)
3221    [],
3222    "create a mountpoint",
3223    "\
3224 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3225 specialized calls that can be used to create extra mountpoints
3226 before mounting the first filesystem.
3227
3228 These calls are I<only> necessary in some very limited circumstances,
3229 mainly the case where you want to mount a mix of unrelated and/or
3230 read-only filesystems together.
3231
3232 For example, live CDs often contain a \"Russian doll\" nest of
3233 filesystems, an ISO outer layer, with a squashfs image inside, with
3234 an ext2/3 image inside that.  You can unpack this as follows
3235 in guestfish:
3236
3237  add-ro Fedora-11-i686-Live.iso
3238  run
3239  mkmountpoint /cd
3240  mkmountpoint /squash
3241  mkmountpoint /ext3
3242  mount /dev/sda /cd
3243  mount-loop /cd/LiveOS/squashfs.img /squash
3244  mount-loop /squash/LiveOS/ext3fs.img /ext3
3245
3246 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3247
3248   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3249    [],
3250    "remove a mountpoint",
3251    "\
3252 This calls removes a mountpoint that was previously created
3253 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3254 for full details.");
3255
3256   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3257    [InitISOFS, Always, TestOutputBuffer (
3258       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3259    "read a file",
3260    "\
3261 This calls returns the contents of the file C<path> as a
3262 buffer.
3263
3264 Unlike C<guestfs_cat>, this function can correctly
3265 handle files that contain embedded ASCII NUL characters.
3266 However unlike C<guestfs_download>, this function is limited
3267 in the total size of file that can be handled.");
3268
3269   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3270    [InitISOFS, Always, TestOutputList (
3271       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3272     InitISOFS, Always, TestOutputList (
3273       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3274    "return lines matching a pattern",
3275    "\
3276 This calls the external C<grep> program and returns the
3277 matching lines.");
3278
3279   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3280    [InitISOFS, Always, TestOutputList (
3281       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3282    "return lines matching a pattern",
3283    "\
3284 This calls the external C<egrep> program and returns the
3285 matching lines.");
3286
3287   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3288    [InitISOFS, Always, TestOutputList (
3289       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3290    "return lines matching a pattern",
3291    "\
3292 This calls the external C<fgrep> program and returns the
3293 matching lines.");
3294
3295   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3296    [InitISOFS, Always, TestOutputList (
3297       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3298    "return lines matching a pattern",
3299    "\
3300 This calls the external C<grep -i> program and returns the
3301 matching lines.");
3302
3303   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3304    [InitISOFS, Always, TestOutputList (
3305       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3306    "return lines matching a pattern",
3307    "\
3308 This calls the external C<egrep -i> program and returns the
3309 matching lines.");
3310
3311   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3312    [InitISOFS, Always, TestOutputList (
3313       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3314    "return lines matching a pattern",
3315    "\
3316 This calls the external C<fgrep -i> program and returns the
3317 matching lines.");
3318
3319   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3320    [InitISOFS, Always, TestOutputList (
3321       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3322    "return lines matching a pattern",
3323    "\
3324 This calls the external C<zgrep> program and returns the
3325 matching lines.");
3326
3327   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3328    [InitISOFS, Always, TestOutputList (
3329       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3330    "return lines matching a pattern",
3331    "\
3332 This calls the external C<zegrep> program and returns the
3333 matching lines.");
3334
3335   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3336    [InitISOFS, Always, TestOutputList (
3337       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3338    "return lines matching a pattern",
3339    "\
3340 This calls the external C<zfgrep> program and returns the
3341 matching lines.");
3342
3343   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3344    [InitISOFS, Always, TestOutputList (
3345       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3346    "return lines matching a pattern",
3347    "\
3348 This calls the external C<zgrep -i> program and returns the
3349 matching lines.");
3350
3351   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3352    [InitISOFS, Always, TestOutputList (
3353       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3354    "return lines matching a pattern",
3355    "\
3356 This calls the external C<zegrep -i> program and returns the
3357 matching lines.");
3358
3359   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3360    [InitISOFS, Always, TestOutputList (
3361       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3362    "return lines matching a pattern",
3363    "\
3364 This calls the external C<zfgrep -i> program and returns the
3365 matching lines.");
3366
3367   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3368    [InitISOFS, Always, TestOutput (
3369       [["realpath"; "/../directory"]], "/directory")],
3370    "canonicalized absolute pathname",
3371    "\
3372 Return the canonicalized absolute pathname of C<path>.  The
3373 returned path has no C<.>, C<..> or symbolic link path elements.");
3374
3375   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3376    [InitBasicFS, Always, TestOutputStruct (
3377       [["touch"; "/a"];
3378        ["ln"; "/a"; "/b"];
3379        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3380    "create a hard link",
3381    "\
3382 This command creates a hard link using the C<ln> command.");
3383
3384   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3385    [InitBasicFS, Always, TestOutputStruct (
3386       [["touch"; "/a"];
3387        ["touch"; "/b"];
3388        ["ln_f"; "/a"; "/b"];
3389        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3390    "create a hard link",
3391    "\
3392 This command creates a hard link using the C<ln -f> command.
3393 The C<-f> option removes the link (C<linkname>) if it exists already.");
3394
3395   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3396    [InitBasicFS, Always, TestOutputStruct (
3397       [["touch"; "/a"];
3398        ["ln_s"; "a"; "/b"];
3399        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3400    "create a symbolic link",
3401    "\
3402 This command creates a symbolic link using the C<ln -s> command.");
3403
3404   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3405    [InitBasicFS, Always, TestOutput (
3406       [["mkdir_p"; "/a/b"];
3407        ["touch"; "/a/b/c"];
3408        ["ln_sf"; "../d"; "/a/b/c"];
3409        ["readlink"; "/a/b/c"]], "../d")],
3410    "create a symbolic link",
3411    "\
3412 This command creates a symbolic link using the C<ln -sf> command,
3413 The C<-f> option removes the link (C<linkname>) if it exists already.");
3414
3415   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3416    [] (* XXX tested above *),
3417    "read the target of a symbolic link",
3418    "\
3419 This command reads the target of a symbolic link.");
3420
3421   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3422    [InitBasicFS, Always, TestOutputStruct (
3423       [["fallocate"; "/a"; "1000000"];
3424        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3425    "preallocate a file in the guest filesystem",
3426    "\
3427 This command preallocates a file (containing zero bytes) named
3428 C<path> of size C<len> bytes.  If the file exists already, it
3429 is overwritten.
3430
3431 Do not confuse this with the guestfish-specific
3432 C<alloc> command which allocates a file in the host and
3433 attaches it as a device.");
3434
3435   ("swapon_device", (RErr, [Device "device"]), 170, [],
3436    [InitPartition, Always, TestRun (
3437       [["mkswap"; "/dev/sda1"];
3438        ["swapon_device"; "/dev/sda1"];
3439        ["swapoff_device"; "/dev/sda1"]])],
3440    "enable swap on device",
3441    "\
3442 This command enables the libguestfs appliance to use the
3443 swap device or partition named C<device>.  The increased
3444 memory is made available for all commands, for example
3445 those run using C<guestfs_command> or C<guestfs_sh>.
3446
3447 Note that you should not swap to existing guest swap
3448 partitions unless you know what you are doing.  They may
3449 contain hibernation information, or other information that
3450 the guest doesn't want you to trash.  You also risk leaking
3451 information about the host to the guest this way.  Instead,
3452 attach a new host device to the guest and swap on that.");
3453
3454   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3455    [], (* XXX tested by swapon_device *)
3456    "disable swap on device",
3457    "\
3458 This command disables the libguestfs appliance swap
3459 device or partition named C<device>.
3460 See C<guestfs_swapon_device>.");
3461
3462   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3463    [InitBasicFS, Always, TestRun (
3464       [["fallocate"; "/swap"; "8388608"];
3465        ["mkswap_file"; "/swap"];
3466        ["swapon_file"; "/swap"];
3467        ["swapoff_file"; "/swap"]])],
3468    "enable swap on file",
3469    "\
3470 This command enables swap to a file.
3471 See C<guestfs_swapon_device> for other notes.");
3472
3473   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3474    [], (* XXX tested by swapon_file *)
3475    "disable swap on file",
3476    "\
3477 This command disables the libguestfs appliance swap on file.");
3478
3479   ("swapon_label", (RErr, [String "label"]), 174, [],
3480    [InitEmpty, Always, TestRun (
3481       [["part_disk"; "/dev/sdb"; "mbr"];
3482        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3483        ["swapon_label"; "swapit"];
3484        ["swapoff_label"; "swapit"];
3485        ["zero"; "/dev/sdb"];
3486        ["blockdev_rereadpt"; "/dev/sdb"]])],
3487    "enable swap on labeled swap partition",
3488    "\
3489 This command enables swap to a labeled swap partition.
3490 See C<guestfs_swapon_device> for other notes.");
3491
3492   ("swapoff_label", (RErr, [String "label"]), 175, [],
3493    [], (* XXX tested by swapon_label *)
3494    "disable swap on labeled swap partition",
3495    "\
3496 This command disables the libguestfs appliance swap on
3497 labeled swap partition.");
3498
3499   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3500    (let uuid = uuidgen () in
3501     [InitEmpty, Always, TestRun (
3502        [["mkswap_U"; uuid; "/dev/sdb"];
3503         ["swapon_uuid"; uuid];
3504         ["swapoff_uuid"; uuid]])]),
3505    "enable swap on swap partition by UUID",
3506    "\
3507 This command enables swap to a swap partition with the given UUID.
3508 See C<guestfs_swapon_device> for other notes.");
3509
3510   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3511    [], (* XXX tested by swapon_uuid *)
3512    "disable swap on swap partition by UUID",
3513    "\
3514 This command disables the libguestfs appliance swap partition
3515 with the given UUID.");
3516
3517   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3518    [InitBasicFS, Always, TestRun (
3519       [["fallocate"; "/swap"; "8388608"];
3520        ["mkswap_file"; "/swap"]])],
3521    "create a swap file",
3522    "\
3523 Create a swap file.
3524
3525 This command just writes a swap file signature to an existing
3526 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3527
3528   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3529    [InitISOFS, Always, TestRun (
3530       [["inotify_init"; "0"]])],
3531    "create an inotify handle",
3532    "\
3533 This command creates a new inotify handle.
3534 The inotify subsystem can be used to notify events which happen to
3535 objects in the guest filesystem.
3536
3537 C<maxevents> is the maximum number of events which will be
3538 queued up between calls to C<guestfs_inotify_read> or
3539 C<guestfs_inotify_files>.
3540 If this is passed as C<0>, then the kernel (or previously set)
3541 default is used.  For Linux 2.6.29 the default was 16384 events.
3542 Beyond this limit, the kernel throws away events, but records
3543 the fact that it threw them away by setting a flag
3544 C<IN_Q_OVERFLOW> in the returned structure list (see
3545 C<guestfs_inotify_read>).
3546
3547 Before any events are generated, you have to add some
3548 watches to the internal watch list.  See:
3549 C<guestfs_inotify_add_watch>,
3550 C<guestfs_inotify_rm_watch> and
3551 C<guestfs_inotify_watch_all>.
3552
3553 Queued up events should be read periodically by calling
3554 C<guestfs_inotify_read>
3555 (or C<guestfs_inotify_files> which is just a helpful
3556 wrapper around C<guestfs_inotify_read>).  If you don't
3557 read the events out often enough then you risk the internal
3558 queue overflowing.
3559
3560 The handle should be closed after use by calling
3561 C<guestfs_inotify_close>.  This also removes any
3562 watches automatically.
3563
3564 See also L<inotify(7)> for an overview of the inotify interface
3565 as exposed by the Linux kernel, which is roughly what we expose
3566 via libguestfs.  Note that there is one global inotify handle
3567 per libguestfs instance.");
3568
3569   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3570    [InitBasicFS, Always, TestOutputList (
3571       [["inotify_init"; "0"];
3572        ["inotify_add_watch"; "/"; "1073741823"];
3573        ["touch"; "/a"];
3574        ["touch"; "/b"];
3575        ["inotify_files"]], ["a"; "b"])],
3576    "add an inotify watch",
3577    "\
3578 Watch C<path> for the events listed in C<mask>.
3579
3580 Note that if C<path> is a directory then events within that
3581 directory are watched, but this does I<not> happen recursively
3582 (in subdirectories).
3583
3584 Note for non-C or non-Linux callers: the inotify events are
3585 defined by the Linux kernel ABI and are listed in
3586 C</usr/include/sys/inotify.h>.");
3587
3588   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3589    [],
3590    "remove an inotify watch",
3591    "\
3592 Remove a previously defined inotify watch.
3593 See C<guestfs_inotify_add_watch>.");
3594
3595   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3596    [],
3597    "return list of inotify events",
3598    "\
3599 Return the complete queue of events that have happened
3600 since the previous read call.
3601
3602 If no events have happened, this returns an empty list.
3603
3604 I<Note>: In order to make sure that all events have been
3605 read, you must call this function repeatedly until it
3606 returns an empty list.  The reason is that the call will
3607 read events up to the maximum appliance-to-host message
3608 size and leave remaining events in the queue.");
3609
3610   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3611    [],
3612    "return list of watched files that had events",
3613    "\
3614 This function is a helpful wrapper around C<guestfs_inotify_read>
3615 which just returns a list of pathnames of objects that were
3616 touched.  The returned pathnames are sorted and deduplicated.");
3617
3618   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3619    [],
3620    "close the inotify handle",
3621    "\
3622 This closes the inotify handle which was previously
3623 opened by inotify_init.  It removes all watches, throws
3624 away any pending events, and deallocates all resources.");
3625
3626   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3627    [],
3628    "set SELinux security context",
3629    "\
3630 This sets the SELinux security context of the daemon
3631 to the string C<context>.
3632
3633 See the documentation about SELINUX in L<guestfs(3)>.");
3634
3635   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3636    [],
3637    "get SELinux security context",
3638    "\
3639 This gets the SELinux security context of the daemon.
3640
3641 See the documentation about SELINUX in L<guestfs(3)>,
3642 and C<guestfs_setcon>");
3643
3644   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3645    [InitEmpty, Always, TestOutput (
3646       [["part_disk"; "/dev/sda"; "mbr"];
3647        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3648        ["mount_options"; ""; "/dev/sda1"; "/"];
3649        ["write_file"; "/new"; "new file contents"; "0"];
3650        ["cat"; "/new"]], "new file contents")],
3651    "make a filesystem with block size",
3652    "\
3653 This call is similar to C<guestfs_mkfs>, but it allows you to
3654 control the block size of the resulting filesystem.  Supported
3655 block sizes depend on the filesystem type, but typically they
3656 are C<1024>, C<2048> or C<4096> only.");
3657
3658   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3659    [InitEmpty, Always, TestOutput (
3660       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3661        ["mke2journal"; "4096"; "/dev/sda1"];
3662        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3663        ["mount_options"; ""; "/dev/sda2"; "/"];
3664        ["write_file"; "/new"; "new file contents"; "0"];
3665        ["cat"; "/new"]], "new file contents")],
3666    "make ext2/3/4 external journal",
3667    "\
3668 This creates an ext2 external journal on C<device>.  It is equivalent
3669 to the command:
3670
3671  mke2fs -O journal_dev -b blocksize device");
3672
3673   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3674    [InitEmpty, Always, TestOutput (
3675       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3676        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3677        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3678        ["mount_options"; ""; "/dev/sda2"; "/"];
3679        ["write_file"; "/new"; "new file contents"; "0"];
3680        ["cat"; "/new"]], "new file contents")],
3681    "make ext2/3/4 external journal with label",
3682    "\
3683 This creates an ext2 external journal on C<device> with label C<label>.");
3684
3685   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3686    (let uuid = uuidgen () in
3687     [InitEmpty, Always, TestOutput (
3688        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3689         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3690         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3691         ["mount_options"; ""; "/dev/sda2"; "/"];
3692         ["write_file"; "/new"; "new file contents"; "0"];
3693         ["cat"; "/new"]], "new file contents")]),
3694    "make ext2/3/4 external journal with UUID",
3695    "\
3696 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3697
3698   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3699    [],
3700    "make ext2/3/4 filesystem with external journal",
3701    "\
3702 This creates an ext2/3/4 filesystem on C<device> with
3703 an external journal on C<journal>.  It is equivalent
3704 to the command:
3705
3706  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3707
3708 See also C<guestfs_mke2journal>.");
3709
3710   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3711    [],
3712    "make ext2/3/4 filesystem with external journal",
3713    "\
3714 This creates an ext2/3/4 filesystem on C<device> with
3715 an external journal on the journal labeled C<label>.
3716
3717 See also C<guestfs_mke2journal_L>.");
3718
3719   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3720    [],
3721    "make ext2/3/4 filesystem with external journal",
3722    "\
3723 This creates an ext2/3/4 filesystem on C<device> with
3724 an external journal on the journal with UUID C<uuid>.
3725
3726 See also C<guestfs_mke2journal_U>.");
3727
3728   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3729    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3730    "load a kernel module",
3731    "\
3732 This loads a kernel module in the appliance.
3733
3734 The kernel module must have been whitelisted when libguestfs
3735 was built (see C<appliance/kmod.whitelist.in> in the source).");
3736
3737   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3738    [InitNone, Always, TestOutput (
3739       [["echo_daemon"; "This is a test"]], "This is a test"
3740     )],
3741    "echo arguments back to the client",
3742    "\
3743 This command concatenate the list of C<words> passed with single spaces between
3744 them and returns the resulting string.
3745
3746 You can use this command to test the connection through to the daemon.
3747
3748 See also C<guestfs_ping_daemon>.");
3749
3750   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3751    [], (* There is a regression test for this. *)
3752    "find all files and directories, returning NUL-separated list",
3753    "\
3754 This command lists out all files and directories, recursively,
3755 starting at C<directory>, placing the resulting list in the
3756 external file called C<files>.
3757
3758 This command works the same way as C<guestfs_find> with the
3759 following exceptions:
3760
3761 =over 4
3762
3763 =item *
3764
3765 The resulting list is written to an external file.
3766
3767 =item *
3768
3769 Items (filenames) in the result are separated
3770 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3771
3772 =item *
3773
3774 This command is not limited in the number of names that it
3775 can return.
3776
3777 =item *
3778
3779 The result list is not sorted.
3780
3781 =back");
3782
3783   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3784    [InitISOFS, Always, TestOutput (
3785       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3786     InitISOFS, Always, TestOutput (
3787       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3788     InitISOFS, Always, TestOutput (
3789       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3790     InitISOFS, Always, TestLastFail (
3791       [["case_sensitive_path"; "/Known-1/"]]);
3792     InitBasicFS, Always, TestOutput (
3793       [["mkdir"; "/a"];
3794        ["mkdir"; "/a/bbb"];
3795        ["touch"; "/a/bbb/c"];
3796        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3797     InitBasicFS, Always, TestOutput (
3798       [["mkdir"; "/a"];
3799        ["mkdir"; "/a/bbb"];
3800        ["touch"; "/a/bbb/c"];
3801        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3802     InitBasicFS, Always, TestLastFail (
3803       [["mkdir"; "/a"];
3804        ["mkdir"; "/a/bbb"];
3805        ["touch"; "/a/bbb/c"];
3806        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3807    "return true path on case-insensitive filesystem",
3808    "\
3809 This can be used to resolve case insensitive paths on
3810 a filesystem which is case sensitive.  The use case is
3811 to resolve paths which you have read from Windows configuration
3812 files or the Windows Registry, to the true path.
3813
3814 The command handles a peculiarity of the Linux ntfs-3g
3815 filesystem driver (and probably others), which is that although
3816 the underlying filesystem is case-insensitive, the driver
3817 exports the filesystem to Linux as case-sensitive.
3818
3819 One consequence of this is that special directories such
3820 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3821 (or other things) depending on the precise details of how
3822 they were created.  In Windows itself this would not be
3823 a problem.
3824
3825 Bug or feature?  You decide:
3826 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3827
3828 This function resolves the true case of each element in the
3829 path and returns the case-sensitive path.
3830
3831 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3832 might return C<\"/WINDOWS/system32\"> (the exact return value
3833 would depend on details of how the directories were originally
3834 created under Windows).
3835
3836 I<Note>:
3837 This function does not handle drive names, backslashes etc.
3838
3839 See also C<guestfs_realpath>.");
3840
3841   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3842    [InitBasicFS, Always, TestOutput (
3843       [["vfs_type"; "/dev/sda1"]], "ext2")],
3844    "get the Linux VFS type corresponding to a mounted device",
3845    "\
3846 This command gets the block device type corresponding to
3847 a mounted device called C<device>.
3848
3849 Usually the result is the name of the Linux VFS module that
3850 is used to mount this device (probably determined automatically
3851 if you used the C<guestfs_mount> call).");
3852
3853   ("truncate", (RErr, [Pathname "path"]), 199, [],
3854    [InitBasicFS, Always, TestOutputStruct (
3855       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3856        ["truncate"; "/test"];
3857        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3858    "truncate a file to zero size",
3859    "\
3860 This command truncates C<path> to a zero-length file.  The
3861 file must exist already.");
3862
3863   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3864    [InitBasicFS, Always, TestOutputStruct (
3865       [["touch"; "/test"];
3866        ["truncate_size"; "/test"; "1000"];
3867        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3868    "truncate a file to a particular size",
3869    "\
3870 This command truncates C<path> to size C<size> bytes.  The file
3871 must exist already.  If the file is smaller than C<size> then
3872 the file is extended to the required size with null bytes.");
3873
3874   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3875    [InitBasicFS, Always, TestOutputStruct (
3876       [["touch"; "/test"];
3877        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3878        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3879    "set timestamp of a file with nanosecond precision",
3880    "\
3881 This command sets the timestamps of a file with nanosecond
3882 precision.
3883
3884 C<atsecs, atnsecs> are the last access time (atime) in secs and
3885 nanoseconds from the epoch.
3886
3887 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3888 secs and nanoseconds from the epoch.
3889
3890 If the C<*nsecs> field contains the special value C<-1> then
3891 the corresponding timestamp is set to the current time.  (The
3892 C<*secs> field is ignored in this case).
3893
3894 If the C<*nsecs> field contains the special value C<-2> then
3895 the corresponding timestamp is left unchanged.  (The
3896 C<*secs> field is ignored in this case).");
3897
3898   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3899    [InitBasicFS, Always, TestOutputStruct (
3900       [["mkdir_mode"; "/test"; "0o111"];
3901        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3902    "create a directory with a particular mode",
3903    "\
3904 This command creates a directory, setting the initial permissions
3905 of the directory to C<mode>.
3906
3907 For common Linux filesystems, the actual mode which is set will
3908 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3909 interpret the mode in other ways.
3910
3911 See also C<guestfs_mkdir>, C<guestfs_umask>");
3912
3913   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3914    [], (* XXX *)
3915    "change file owner and group",
3916    "\
3917 Change the file owner to C<owner> and group to C<group>.
3918 This is like C<guestfs_chown> but if C<path> is a symlink then
3919 the link itself is changed, not the target.
3920
3921 Only numeric uid and gid are supported.  If you want to use
3922 names, you will need to locate and parse the password file
3923 yourself (Augeas support makes this relatively easy).");
3924
3925   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3926    [], (* XXX *)
3927    "lstat on multiple files",
3928    "\
3929 This call allows you to perform the C<guestfs_lstat> operation
3930 on multiple files, where all files are in the directory C<path>.
3931 C<names> is the list of files from this directory.
3932
3933 On return you get a list of stat structs, with a one-to-one
3934 correspondence to the C<names> list.  If any name did not exist
3935 or could not be lstat'd, then the C<ino> field of that structure
3936 is set to C<-1>.
3937
3938 This call is intended for programs that want to efficiently
3939 list a directory contents without making many round-trips.
3940 See also C<guestfs_lxattrlist> for a similarly efficient call
3941 for getting extended attributes.  Very long directory listings
3942 might cause the protocol message size to be exceeded, causing
3943 this call to fail.  The caller must split up such requests
3944 into smaller groups of names.");
3945
3946   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3947    [], (* XXX *)
3948    "lgetxattr on multiple files",
3949    "\
3950 This call allows you to get the extended attributes
3951 of multiple files, where all files are in the directory C<path>.
3952 C<names> is the list of files from this directory.
3953
3954 On return you get a flat list of xattr structs which must be
3955 interpreted sequentially.  The first xattr struct always has a zero-length
3956 C<attrname>.  C<attrval> in this struct is zero-length
3957 to indicate there was an error doing C<lgetxattr> for this
3958 file, I<or> is a C string which is a decimal number
3959 (the number of following attributes for this file, which could
3960 be C<\"0\">).  Then after the first xattr struct are the
3961 zero or more attributes for the first named file.
3962 This repeats for the second and subsequent files.
3963
3964 This call is intended for programs that want to efficiently
3965 list a directory contents without making many round-trips.
3966 See also C<guestfs_lstatlist> for a similarly efficient call
3967 for getting standard stats.  Very long directory listings
3968 might cause the protocol message size to be exceeded, causing
3969 this call to fail.  The caller must split up such requests
3970 into smaller groups of names.");
3971
3972   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3973    [], (* XXX *)
3974    "readlink on multiple files",
3975    "\
3976 This call allows you to do a C<readlink> operation
3977 on multiple files, where all files are in the directory C<path>.
3978 C<names> is the list of files from this directory.
3979
3980 On return you get a list of strings, with a one-to-one
3981 correspondence to the C<names> list.  Each string is the
3982 value of the symbol link.
3983
3984 If the C<readlink(2)> operation fails on any name, then
3985 the corresponding result string is the empty string C<\"\">.
3986 However the whole operation is completed even if there
3987 were C<readlink(2)> errors, and so you can call this
3988 function with names where you don't know if they are
3989 symbolic links already (albeit slightly less efficient).
3990
3991 This call is intended for programs that want to efficiently
3992 list a directory contents without making many round-trips.
3993 Very long directory listings might cause the protocol
3994 message size to be exceeded, causing
3995 this call to fail.  The caller must split up such requests
3996 into smaller groups of names.");
3997
3998   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3999    [InitISOFS, Always, TestOutputBuffer (
4000       [["pread"; "/known-4"; "1"; "3"]], "\n");
4001     InitISOFS, Always, TestOutputBuffer (
4002       [["pread"; "/empty"; "0"; "100"]], "")],
4003    "read part of a file",
4004    "\
4005 This command lets you read part of a file.  It reads C<count>
4006 bytes of the file, starting at C<offset>, from file C<path>.
4007
4008 This may read fewer bytes than requested.  For further details
4009 see the L<pread(2)> system call.");
4010
4011   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4012    [InitEmpty, Always, TestRun (
4013       [["part_init"; "/dev/sda"; "gpt"]])],
4014    "create an empty partition table",
4015    "\
4016 This creates an empty partition table on C<device> of one of the
4017 partition types listed below.  Usually C<parttype> should be
4018 either C<msdos> or C<gpt> (for large disks).
4019
4020 Initially there are no partitions.  Following this, you should
4021 call C<guestfs_part_add> for each partition required.
4022
4023 Possible values for C<parttype> are:
4024
4025 =over 4
4026
4027 =item B<efi> | B<gpt>
4028
4029 Intel EFI / GPT partition table.
4030
4031 This is recommended for >= 2 TB partitions that will be accessed
4032 from Linux and Intel-based Mac OS X.  It also has limited backwards
4033 compatibility with the C<mbr> format.
4034
4035 =item B<mbr> | B<msdos>
4036
4037 The standard PC \"Master Boot Record\" (MBR) format used
4038 by MS-DOS and Windows.  This partition type will B<only> work
4039 for device sizes up to 2 TB.  For large disks we recommend
4040 using C<gpt>.
4041
4042 =back
4043
4044 Other partition table types that may work but are not
4045 supported include:
4046
4047 =over 4
4048
4049 =item B<aix>
4050
4051 AIX disk labels.
4052
4053 =item B<amiga> | B<rdb>
4054
4055 Amiga \"Rigid Disk Block\" format.
4056
4057 =item B<bsd>
4058
4059 BSD disk labels.
4060
4061 =item B<dasd>
4062
4063 DASD, used on IBM mainframes.
4064
4065 =item B<dvh>
4066
4067 MIPS/SGI volumes.
4068
4069 =item B<mac>
4070
4071 Old Mac partition format.  Modern Macs use C<gpt>.
4072
4073 =item B<pc98>
4074
4075 NEC PC-98 format, common in Japan apparently.
4076
4077 =item B<sun>
4078
4079 Sun disk labels.
4080
4081 =back");
4082
4083   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4084    [InitEmpty, Always, TestRun (
4085       [["part_init"; "/dev/sda"; "mbr"];
4086        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4087     InitEmpty, Always, TestRun (
4088       [["part_init"; "/dev/sda"; "gpt"];
4089        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4090        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4091     InitEmpty, Always, TestRun (
4092       [["part_init"; "/dev/sda"; "mbr"];
4093        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4094        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4095        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4096        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4097    "add a partition to the device",
4098    "\
4099 This command adds a partition to C<device>.  If there is no partition
4100 table on the device, call C<guestfs_part_init> first.
4101
4102 The C<prlogex> parameter is the type of partition.  Normally you
4103 should pass C<p> or C<primary> here, but MBR partition tables also
4104 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4105 types.
4106
4107 C<startsect> and C<endsect> are the start and end of the partition
4108 in I<sectors>.  C<endsect> may be negative, which means it counts
4109 backwards from the end of the disk (C<-1> is the last sector).
4110
4111 Creating a partition which covers the whole disk is not so easy.
4112 Use C<guestfs_part_disk> to do that.");
4113
4114   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4115    [InitEmpty, Always, TestRun (
4116       [["part_disk"; "/dev/sda"; "mbr"]]);
4117     InitEmpty, Always, TestRun (
4118       [["part_disk"; "/dev/sda"; "gpt"]])],
4119    "partition whole disk with a single primary partition",
4120    "\
4121 This command is simply a combination of C<guestfs_part_init>
4122 followed by C<guestfs_part_add> to create a single primary partition
4123 covering the whole disk.
4124
4125 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4126 but other possible values are described in C<guestfs_part_init>.");
4127
4128   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4129    [InitEmpty, Always, TestRun (
4130       [["part_disk"; "/dev/sda"; "mbr"];
4131        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4132    "make a partition bootable",
4133    "\
4134 This sets the bootable flag on partition numbered C<partnum> on
4135 device C<device>.  Note that partitions are numbered from 1.
4136
4137 The bootable flag is used by some operating systems (notably
4138 Windows) to determine which partition to boot from.  It is by
4139 no means universally recognized.");
4140
4141   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4142    [InitEmpty, Always, TestRun (
4143       [["part_disk"; "/dev/sda"; "gpt"];
4144        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4145    "set partition name",
4146    "\
4147 This sets the partition name on partition numbered C<partnum> on
4148 device C<device>.  Note that partitions are numbered from 1.
4149
4150 The partition name can only be set on certain types of partition
4151 table.  This works on C<gpt> but not on C<mbr> partitions.");
4152
4153   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4154    [], (* XXX Add a regression test for this. *)
4155    "list partitions on a device",
4156    "\
4157 This command parses the partition table on C<device> and
4158 returns the list of partitions found.
4159
4160 The fields in the returned structure are:
4161
4162 =over 4
4163
4164 =item B<part_num>
4165
4166 Partition number, counting from 1.
4167
4168 =item B<part_start>
4169
4170 Start of the partition I<in bytes>.  To get sectors you have to
4171 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4172
4173 =item B<part_end>
4174
4175 End of the partition in bytes.
4176
4177 =item B<part_size>
4178
4179 Size of the partition in bytes.
4180
4181 =back");
4182
4183   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4184    [InitEmpty, Always, TestOutput (
4185       [["part_disk"; "/dev/sda"; "gpt"];
4186        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4187    "get the partition table type",
4188    "\
4189 This command examines the partition table on C<device> and
4190 returns the partition table type (format) being used.
4191
4192 Common return values include: C<msdos> (a DOS/Windows style MBR
4193 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4194 values are possible, although unusual.  See C<guestfs_part_init>
4195 for a full list.");
4196
4197   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4198    [InitBasicFS, Always, TestOutputBuffer (
4199       [["fill"; "0x63"; "10"; "/test"];
4200        ["read_file"; "/test"]], "cccccccccc")],
4201    "fill a file with octets",
4202    "\
4203 This command creates a new file called C<path>.  The initial
4204 content of the file is C<len> octets of C<c>, where C<c>
4205 must be a number in the range C<[0..255]>.
4206
4207 To fill a file with zero bytes (sparsely), it is
4208 much more efficient to use C<guestfs_truncate_size>.");
4209
4210   ("available", (RErr, [StringList "groups"]), 216, [],
4211    [InitNone, Always, TestRun [["available"; ""]]],
4212    "test availability of some parts of the API",
4213    "\
4214 This command is used to check the availability of some
4215 groups of functionality in the appliance, which not all builds of
4216 the libguestfs appliance will be able to provide.
4217
4218 The libguestfs groups, and the functions that those
4219 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4220
4221 The argument C<groups> is a list of group names, eg:
4222 C<[\"inotify\", \"augeas\"]> would check for the availability of
4223 the Linux inotify functions and Augeas (configuration file
4224 editing) functions.
4225
4226 The command returns no error if I<all> requested groups are available.
4227
4228 It fails with an error if one or more of the requested
4229 groups is unavailable in the appliance.
4230
4231 If an unknown group name is included in the
4232 list of groups then an error is always returned.
4233
4234 I<Notes:>
4235
4236 =over 4
4237
4238 =item *
4239
4240 You must call C<guestfs_launch> before calling this function.
4241
4242 The reason is because we don't know what groups are
4243 supported by the appliance/daemon until it is running and can
4244 be queried.
4245
4246 =item *
4247
4248 If a group of functions is available, this does not necessarily
4249 mean that they will work.  You still have to check for errors
4250 when calling individual API functions even if they are
4251 available.
4252
4253 =item *
4254
4255 It is usually the job of distro packagers to build
4256 complete functionality into the libguestfs appliance.
4257 Upstream libguestfs, if built from source with all
4258 requirements satisfied, will support everything.
4259
4260 =item *
4261
4262 This call was added in version C<1.0.80>.  In previous
4263 versions of libguestfs all you could do would be to speculatively
4264 execute a command to find out if the daemon implemented it.
4265 See also C<guestfs_version>.
4266
4267 =back");
4268
4269   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4270    [InitBasicFS, Always, TestOutputBuffer (
4271       [["write_file"; "/src"; "hello, world"; "0"];
4272        ["dd"; "/src"; "/dest"];
4273        ["read_file"; "/dest"]], "hello, world")],
4274    "copy from source to destination using dd",
4275    "\
4276 This command copies from one source device or file C<src>
4277 to another destination device or file C<dest>.  Normally you
4278 would use this to copy to or from a device or partition, for
4279 example to duplicate a filesystem.
4280
4281 If the destination is a device, it must be as large or larger
4282 than the source file or device, otherwise the copy will fail.
4283 This command cannot do partial copies (see C<guestfs_copy_size>).");
4284
4285   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4286    [InitBasicFS, Always, TestOutputInt (
4287       [["write_file"; "/file"; "hello, world"; "0"];
4288        ["filesize"; "/file"]], 12)],
4289    "return the size of the file in bytes",
4290    "\
4291 This command returns the size of C<file> in bytes.
4292
4293 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4294 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4295 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4296
4297   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4298    [InitBasicFSonLVM, Always, TestOutputList (
4299       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4300        ["lvs"]], ["/dev/VG/LV2"])],
4301    "rename an LVM logical volume",
4302    "\
4303 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4304
4305   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4306    [InitBasicFSonLVM, Always, TestOutputList (
4307       [["umount"; "/"];
4308        ["vg_activate"; "false"; "VG"];
4309        ["vgrename"; "VG"; "VG2"];
4310        ["vg_activate"; "true"; "VG2"];
4311        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4312        ["vgs"]], ["VG2"])],
4313    "rename an LVM volume group",
4314    "\
4315 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4316
4317   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4318    [InitISOFS, Always, TestOutputBuffer (
4319       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4320    "list the contents of a single file in an initrd",
4321    "\
4322 This command unpacks the file C<filename> from the initrd file
4323 called C<initrdpath>.  The filename must be given I<without> the
4324 initial C</> character.
4325
4326 For example, in guestfish you could use the following command
4327 to examine the boot script (usually called C</init>)
4328 contained in a Linux initrd or initramfs image:
4329
4330  initrd-cat /boot/initrd-<version>.img init
4331
4332 See also C<guestfs_initrd_list>.");
4333
4334   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4335    [],
4336    "get the UUID of a physical volume",
4337    "\
4338 This command returns the UUID of the LVM PV C<device>.");
4339
4340   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4341    [],
4342    "get the UUID of a volume group",
4343    "\
4344 This command returns the UUID of the LVM VG named C<vgname>.");
4345
4346   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4347    [],
4348    "get the UUID of a logical volume",
4349    "\
4350 This command returns the UUID of the LVM LV C<device>.");
4351
4352   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4353    [],
4354    "get the PV UUIDs containing the volume group",
4355    "\
4356 Given a VG called C<vgname>, this returns the UUIDs of all
4357 the physical volumes that this volume group resides on.
4358
4359 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4360 calls to associate physical volumes and volume groups.
4361
4362 See also C<guestfs_vglvuuids>.");
4363
4364   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4365    [],
4366    "get the LV UUIDs of all LVs in the volume group",
4367    "\
4368 Given a VG called C<vgname>, this returns the UUIDs of all
4369 the logical volumes created in this volume group.
4370
4371 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4372 calls to associate logical volumes and volume groups.
4373
4374 See also C<guestfs_vgpvuuids>.");
4375
4376   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4377    [InitBasicFS, Always, TestOutputBuffer (
4378       [["write_file"; "/src"; "hello, world"; "0"];
4379        ["copy_size"; "/src"; "/dest"; "5"];
4380        ["read_file"; "/dest"]], "hello")],
4381    "copy size bytes from source to destination using dd",
4382    "\
4383 This command copies exactly C<size> bytes from one source device
4384 or file C<src> to another destination device or file C<dest>.
4385
4386 Note this will fail if the source is too short or if the destination
4387 is not large enough.");
4388
4389   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4390    [InitEmpty, Always, TestRun (
4391       [["part_init"; "/dev/sda"; "mbr"];
4392        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4393        ["part_del"; "/dev/sda"; "1"]])],
4394    "delete a partition",
4395    "\
4396 This command deletes the partition numbered C<partnum> on C<device>.
4397
4398 Note that in the case of MBR partitioning, deleting an
4399 extended partition also deletes any logical partitions
4400 it contains.");
4401
4402   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4403    [InitEmpty, Always, TestOutputTrue (
4404       [["part_init"; "/dev/sda"; "mbr"];
4405        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4406        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4407        ["part_get_bootable"; "/dev/sda"; "1"]])],
4408    "return true if a partition is bootable",
4409    "\
4410 This command returns true if the partition C<partnum> on
4411 C<device> has the bootable flag set.
4412
4413 See also C<guestfs_part_set_bootable>.");
4414
4415   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4416    [InitEmpty, Always, TestOutputInt (
4417       [["part_init"; "/dev/sda"; "mbr"];
4418        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4419        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4420        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4421    "get the MBR type byte (ID byte) from a partition",
4422    "\
4423 Returns the MBR type byte (also known as the ID byte) from
4424 the numbered partition C<partnum>.
4425
4426 Note that only MBR (old DOS-style) partitions have type bytes.
4427 You will get undefined results for other partition table
4428 types (see C<guestfs_part_get_parttype>).");
4429
4430   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4431    [], (* tested by part_get_mbr_id *)
4432    "set the MBR type byte (ID byte) of a partition",
4433    "\
4434 Sets the MBR type byte (also known as the ID byte) of
4435 the numbered partition C<partnum> to C<idbyte>.  Note
4436 that the type bytes quoted in most documentation are
4437 in fact hexadecimal numbers, but usually documented
4438 without any leading \"0x\" which might be confusing.
4439
4440 Note that only MBR (old DOS-style) partitions have type bytes.
4441 You will get undefined results for other partition table
4442 types (see C<guestfs_part_get_parttype>).");
4443
4444 ]
4445
4446 let all_functions = non_daemon_functions @ daemon_functions
4447
4448 (* In some places we want the functions to be displayed sorted
4449  * alphabetically, so this is useful:
4450  *)
4451 let all_functions_sorted =
4452   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4453                compare n1 n2) all_functions
4454
4455 (* Field types for structures. *)
4456 type field =
4457   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4458   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4459   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4460   | FUInt32
4461   | FInt32
4462   | FUInt64
4463   | FInt64
4464   | FBytes                      (* Any int measure that counts bytes. *)
4465   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4466   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4467
4468 (* Because we generate extra parsing code for LVM command line tools,
4469  * we have to pull out the LVM columns separately here.
4470  *)
4471 let lvm_pv_cols = [
4472   "pv_name", FString;
4473   "pv_uuid", FUUID;
4474   "pv_fmt", FString;
4475   "pv_size", FBytes;
4476   "dev_size", FBytes;
4477   "pv_free", FBytes;
4478   "pv_used", FBytes;
4479   "pv_attr", FString (* XXX *);
4480   "pv_pe_count", FInt64;
4481   "pv_pe_alloc_count", FInt64;
4482   "pv_tags", FString;
4483   "pe_start", FBytes;
4484   "pv_mda_count", FInt64;
4485   "pv_mda_free", FBytes;
4486   (* Not in Fedora 10:
4487      "pv_mda_size", FBytes;
4488   *)
4489 ]
4490 let lvm_vg_cols = [
4491   "vg_name", FString;
4492   "vg_uuid", FUUID;
4493   "vg_fmt", FString;
4494   "vg_attr", FString (* XXX *);
4495   "vg_size", FBytes;
4496   "vg_free", FBytes;
4497   "vg_sysid", FString;
4498   "vg_extent_size", FBytes;
4499   "vg_extent_count", FInt64;
4500   "vg_free_count", FInt64;
4501   "max_lv", FInt64;
4502   "max_pv", FInt64;
4503   "pv_count", FInt64;
4504   "lv_count", FInt64;
4505   "snap_count", FInt64;
4506   "vg_seqno", FInt64;
4507   "vg_tags", FString;
4508   "vg_mda_count", FInt64;
4509   "vg_mda_free", FBytes;
4510   (* Not in Fedora 10:
4511      "vg_mda_size", FBytes;
4512   *)
4513 ]
4514 let lvm_lv_cols = [
4515   "lv_name", FString;
4516   "lv_uuid", FUUID;
4517   "lv_attr", FString (* XXX *);
4518   "lv_major", FInt64;
4519   "lv_minor", FInt64;
4520   "lv_kernel_major", FInt64;
4521   "lv_kernel_minor", FInt64;
4522   "lv_size", FBytes;
4523   "seg_count", FInt64;
4524   "origin", FString;
4525   "snap_percent", FOptPercent;
4526   "copy_percent", FOptPercent;
4527   "move_pv", FString;
4528   "lv_tags", FString;
4529   "mirror_log", FString;
4530   "modules", FString;
4531 ]
4532
4533 (* Names and fields in all structures (in RStruct and RStructList)
4534  * that we support.
4535  *)
4536 let structs = [
4537   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4538    * not use this struct in any new code.
4539    *)
4540   "int_bool", [
4541     "i", FInt32;                (* for historical compatibility *)
4542     "b", FInt32;                (* for historical compatibility *)
4543   ];
4544
4545   (* LVM PVs, VGs, LVs. *)
4546   "lvm_pv", lvm_pv_cols;
4547   "lvm_vg", lvm_vg_cols;
4548   "lvm_lv", lvm_lv_cols;
4549
4550   (* Column names and types from stat structures.
4551    * NB. Can't use things like 'st_atime' because glibc header files
4552    * define some of these as macros.  Ugh.
4553    *)
4554   "stat", [
4555     "dev", FInt64;
4556     "ino", FInt64;
4557     "mode", FInt64;
4558     "nlink", FInt64;
4559     "uid", FInt64;
4560     "gid", FInt64;
4561     "rdev", FInt64;
4562     "size", FInt64;
4563     "blksize", FInt64;
4564     "blocks", FInt64;
4565     "atime", FInt64;
4566     "mtime", FInt64;
4567     "ctime", FInt64;
4568   ];
4569   "statvfs", [
4570     "bsize", FInt64;
4571     "frsize", FInt64;
4572     "blocks", FInt64;
4573     "bfree", FInt64;
4574     "bavail", FInt64;
4575     "files", FInt64;
4576     "ffree", FInt64;
4577     "favail", FInt64;
4578     "fsid", FInt64;
4579     "flag", FInt64;
4580     "namemax", FInt64;
4581   ];
4582
4583   (* Column names in dirent structure. *)
4584   "dirent", [
4585     "ino", FInt64;
4586     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4587     "ftyp", FChar;
4588     "name", FString;
4589   ];
4590
4591   (* Version numbers. *)
4592   "version", [
4593     "major", FInt64;
4594     "minor", FInt64;
4595     "release", FInt64;
4596     "extra", FString;
4597   ];
4598
4599   (* Extended attribute. *)
4600   "xattr", [
4601     "attrname", FString;
4602     "attrval", FBuffer;
4603   ];
4604
4605   (* Inotify events. *)
4606   "inotify_event", [
4607     "in_wd", FInt64;
4608     "in_mask", FUInt32;
4609     "in_cookie", FUInt32;
4610     "in_name", FString;
4611   ];
4612
4613   (* Partition table entry. *)
4614   "partition", [
4615     "part_num", FInt32;
4616     "part_start", FBytes;
4617     "part_end", FBytes;
4618     "part_size", FBytes;
4619   ];
4620 ] (* end of structs *)
4621
4622 (* Ugh, Java has to be different ..
4623  * These names are also used by the Haskell bindings.
4624  *)
4625 let java_structs = [
4626   "int_bool", "IntBool";
4627   "lvm_pv", "PV";
4628   "lvm_vg", "VG";
4629   "lvm_lv", "LV";
4630   "stat", "Stat";
4631   "statvfs", "StatVFS";
4632   "dirent", "Dirent";
4633   "version", "Version";
4634   "xattr", "XAttr";
4635   "inotify_event", "INotifyEvent";
4636   "partition", "Partition";
4637 ]
4638
4639 (* What structs are actually returned. *)
4640 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4641
4642 (* Returns a list of RStruct/RStructList structs that are returned
4643  * by any function.  Each element of returned list is a pair:
4644  *
4645  * (structname, RStructOnly)
4646  *    == there exists function which returns RStruct (_, structname)
4647  * (structname, RStructListOnly)
4648  *    == there exists function which returns RStructList (_, structname)
4649  * (structname, RStructAndList)
4650  *    == there are functions returning both RStruct (_, structname)
4651  *                                      and RStructList (_, structname)
4652  *)
4653 let rstructs_used_by functions =
4654   (* ||| is a "logical OR" for rstructs_used_t *)
4655   let (|||) a b =
4656     match a, b with
4657     | RStructAndList, _
4658     | _, RStructAndList -> RStructAndList
4659     | RStructOnly, RStructListOnly
4660     | RStructListOnly, RStructOnly -> RStructAndList
4661     | RStructOnly, RStructOnly -> RStructOnly
4662     | RStructListOnly, RStructListOnly -> RStructListOnly
4663   in
4664
4665   let h = Hashtbl.create 13 in
4666
4667   (* if elem->oldv exists, update entry using ||| operator,
4668    * else just add elem->newv to the hash
4669    *)
4670   let update elem newv =
4671     try  let oldv = Hashtbl.find h elem in
4672          Hashtbl.replace h elem (newv ||| oldv)
4673     with Not_found -> Hashtbl.add h elem newv
4674   in
4675
4676   List.iter (
4677     fun (_, style, _, _, _, _, _) ->
4678       match fst style with
4679       | RStruct (_, structname) -> update structname RStructOnly
4680       | RStructList (_, structname) -> update structname RStructListOnly
4681       | _ -> ()
4682   ) functions;
4683
4684   (* return key->values as a list of (key,value) *)
4685   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4686
4687 (* Used for testing language bindings. *)
4688 type callt =
4689   | CallString of string
4690   | CallOptString of string option
4691   | CallStringList of string list
4692   | CallInt of int
4693   | CallInt64 of int64
4694   | CallBool of bool
4695
4696 (* Used to memoize the result of pod2text. *)
4697 let pod2text_memo_filename = "src/.pod2text.data"
4698 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4699   try
4700     let chan = open_in pod2text_memo_filename in
4701     let v = input_value chan in
4702     close_in chan;
4703     v
4704   with
4705     _ -> Hashtbl.create 13
4706 let pod2text_memo_updated () =
4707   let chan = open_out pod2text_memo_filename in
4708   output_value chan pod2text_memo;
4709   close_out chan
4710
4711 (* Useful functions.
4712  * Note we don't want to use any external OCaml libraries which
4713  * makes this a bit harder than it should be.
4714  *)
4715 module StringMap = Map.Make (String)
4716
4717 let failwithf fs = ksprintf failwith fs
4718
4719 let unique = let i = ref 0 in fun () -> incr i; !i
4720
4721 let replace_char s c1 c2 =
4722   let s2 = String.copy s in
4723   let r = ref false in
4724   for i = 0 to String.length s2 - 1 do
4725     if String.unsafe_get s2 i = c1 then (
4726       String.unsafe_set s2 i c2;
4727       r := true
4728     )
4729   done;
4730   if not !r then s else s2
4731
4732 let isspace c =
4733   c = ' '
4734   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4735
4736 let triml ?(test = isspace) str =
4737   let i = ref 0 in
4738   let n = ref (String.length str) in
4739   while !n > 0 && test str.[!i]; do
4740     decr n;
4741     incr i
4742   done;
4743   if !i = 0 then str
4744   else String.sub str !i !n
4745
4746 let trimr ?(test = isspace) str =
4747   let n = ref (String.length str) in
4748   while !n > 0 && test str.[!n-1]; do
4749     decr n
4750   done;
4751   if !n = String.length str then str
4752   else String.sub str 0 !n
4753
4754 let trim ?(test = isspace) str =
4755   trimr ~test (triml ~test str)
4756
4757 let rec find s sub =
4758   let len = String.length s in
4759   let sublen = String.length sub in
4760   let rec loop i =
4761     if i <= len-sublen then (
4762       let rec loop2 j =
4763         if j < sublen then (
4764           if s.[i+j] = sub.[j] then loop2 (j+1)
4765           else -1
4766         ) else
4767           i (* found *)
4768       in
4769       let r = loop2 0 in
4770       if r = -1 then loop (i+1) else r
4771     ) else
4772       -1 (* not found *)
4773   in
4774   loop 0
4775
4776 let rec replace_str s s1 s2 =
4777   let len = String.length s in
4778   let sublen = String.length s1 in
4779   let i = find s s1 in
4780   if i = -1 then s
4781   else (
4782     let s' = String.sub s 0 i in
4783     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4784     s' ^ s2 ^ replace_str s'' s1 s2
4785   )
4786
4787 let rec string_split sep str =
4788   let len = String.length str in
4789   let seplen = String.length sep in
4790   let i = find str sep in
4791   if i = -1 then [str]
4792   else (
4793     let s' = String.sub str 0 i in
4794     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4795     s' :: string_split sep s''
4796   )
4797
4798 let files_equal n1 n2 =
4799   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4800   match Sys.command cmd with
4801   | 0 -> true
4802   | 1 -> false
4803   | i -> failwithf "%s: failed with error code %d" cmd i
4804
4805 let rec filter_map f = function
4806   | [] -> []
4807   | x :: xs ->
4808       match f x with
4809       | Some y -> y :: filter_map f xs
4810       | None -> filter_map f xs
4811
4812 let rec find_map f = function
4813   | [] -> raise Not_found
4814   | x :: xs ->
4815       match f x with
4816       | Some y -> y
4817       | None -> find_map f xs
4818
4819 let iteri f xs =
4820   let rec loop i = function
4821     | [] -> ()
4822     | x :: xs -> f i x; loop (i+1) xs
4823   in
4824   loop 0 xs
4825
4826 let mapi f xs =
4827   let rec loop i = function
4828     | [] -> []
4829     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4830   in
4831   loop 0 xs
4832
4833 let count_chars c str =
4834   let count = ref 0 in
4835   for i = 0 to String.length str - 1 do
4836     if c = String.unsafe_get str i then incr count
4837   done;
4838   !count
4839
4840 let name_of_argt = function
4841   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4842   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4843   | FileIn n | FileOut n -> n
4844
4845 let java_name_of_struct typ =
4846   try List.assoc typ java_structs
4847   with Not_found ->
4848     failwithf
4849       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4850
4851 let cols_of_struct typ =
4852   try List.assoc typ structs
4853   with Not_found ->
4854     failwithf "cols_of_struct: unknown struct %s" typ
4855
4856 let seq_of_test = function
4857   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4858   | TestOutputListOfDevices (s, _)
4859   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4860   | TestOutputTrue s | TestOutputFalse s
4861   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4862   | TestOutputStruct (s, _)
4863   | TestLastFail s -> s
4864
4865 (* Handling for function flags. *)
4866 let protocol_limit_warning =
4867   "Because of the message protocol, there is a transfer limit
4868 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4869
4870 let danger_will_robinson =
4871   "B<This command is dangerous.  Without careful use you
4872 can easily destroy all your data>."
4873
4874 let deprecation_notice flags =
4875   try
4876     let alt =
4877       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4878     let txt =
4879       sprintf "This function is deprecated.
4880 In new code, use the C<%s> call instead.
4881
4882 Deprecated functions will not be removed from the API, but the
4883 fact that they are deprecated indicates that there are problems
4884 with correct use of these functions." alt in
4885     Some txt
4886   with
4887     Not_found -> None
4888
4889 (* Create list of optional groups. *)
4890 let optgroups =
4891   let h = Hashtbl.create 13 in
4892   List.iter (
4893     fun (name, _, _, flags, _, _, _) ->
4894       List.iter (
4895         function
4896         | Optional group ->
4897             let names = try Hashtbl.find h group with Not_found -> [] in
4898             Hashtbl.replace h group (name :: names)
4899         | _ -> ()
4900       ) flags
4901   ) daemon_functions;
4902   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4903   let groups =
4904     List.map (
4905       fun group -> group, List.sort compare (Hashtbl.find h group)
4906     ) groups in
4907   List.sort (fun x y -> compare (fst x) (fst y)) groups
4908
4909 (* Check function names etc. for consistency. *)
4910 let check_functions () =
4911   let contains_uppercase str =
4912     let len = String.length str in
4913     let rec loop i =
4914       if i >= len then false
4915       else (
4916         let c = str.[i] in
4917         if c >= 'A' && c <= 'Z' then true
4918         else loop (i+1)
4919       )
4920     in
4921     loop 0
4922   in
4923
4924   (* Check function names. *)
4925   List.iter (
4926     fun (name, _, _, _, _, _, _) ->
4927       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4928         failwithf "function name %s does not need 'guestfs' prefix" name;
4929       if name = "" then
4930         failwithf "function name is empty";
4931       if name.[0] < 'a' || name.[0] > 'z' then
4932         failwithf "function name %s must start with lowercase a-z" name;
4933       if String.contains name '-' then
4934         failwithf "function name %s should not contain '-', use '_' instead."
4935           name
4936   ) all_functions;
4937
4938   (* Check function parameter/return names. *)
4939   List.iter (
4940     fun (name, style, _, _, _, _, _) ->
4941       let check_arg_ret_name n =
4942         if contains_uppercase n then
4943           failwithf "%s param/ret %s should not contain uppercase chars"
4944             name n;
4945         if String.contains n '-' || String.contains n '_' then
4946           failwithf "%s param/ret %s should not contain '-' or '_'"
4947             name n;
4948         if n = "value" then
4949           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;
4950         if n = "int" || n = "char" || n = "short" || n = "long" then
4951           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4952         if n = "i" || n = "n" then
4953           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4954         if n = "argv" || n = "args" then
4955           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4956
4957         (* List Haskell, OCaml and C keywords here.
4958          * http://www.haskell.org/haskellwiki/Keywords
4959          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4960          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4961          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4962          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4963          * Omitting _-containing words, since they're handled above.
4964          * Omitting the OCaml reserved word, "val", is ok,
4965          * and saves us from renaming several parameters.
4966          *)
4967         let reserved = [
4968           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4969           "char"; "class"; "const"; "constraint"; "continue"; "data";
4970           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4971           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4972           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4973           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4974           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4975           "interface";
4976           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4977           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4978           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4979           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4980           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4981           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4982           "volatile"; "when"; "where"; "while";
4983           ] in
4984         if List.mem n reserved then
4985           failwithf "%s has param/ret using reserved word %s" name n;
4986       in
4987
4988       (match fst style with
4989        | RErr -> ()
4990        | RInt n | RInt64 n | RBool n
4991        | RConstString n | RConstOptString n | RString n
4992        | RStringList n | RStruct (n, _) | RStructList (n, _)
4993        | RHashtable n | RBufferOut n ->
4994            check_arg_ret_name n
4995       );
4996       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4997   ) all_functions;
4998
4999   (* Check short descriptions. *)
5000   List.iter (
5001     fun (name, _, _, _, _, shortdesc, _) ->
5002       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5003         failwithf "short description of %s should begin with lowercase." name;
5004       let c = shortdesc.[String.length shortdesc-1] in
5005       if c = '\n' || c = '.' then
5006         failwithf "short description of %s should not end with . or \\n." name
5007   ) all_functions;
5008
5009   (* Check long descriptions. *)
5010   List.iter (
5011     fun (name, _, _, _, _, _, longdesc) ->
5012       if longdesc.[String.length longdesc-1] = '\n' then
5013         failwithf "long description of %s should not end with \\n." name
5014   ) all_functions;
5015
5016   (* Check proc_nrs. *)
5017   List.iter (
5018     fun (name, _, proc_nr, _, _, _, _) ->
5019       if proc_nr <= 0 then
5020         failwithf "daemon function %s should have proc_nr > 0" name
5021   ) daemon_functions;
5022
5023   List.iter (
5024     fun (name, _, proc_nr, _, _, _, _) ->
5025       if proc_nr <> -1 then
5026         failwithf "non-daemon function %s should have proc_nr -1" name
5027   ) non_daemon_functions;
5028
5029   let proc_nrs =
5030     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5031       daemon_functions in
5032   let proc_nrs =
5033     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5034   let rec loop = function
5035     | [] -> ()
5036     | [_] -> ()
5037     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5038         loop rest
5039     | (name1,nr1) :: (name2,nr2) :: _ ->
5040         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5041           name1 name2 nr1 nr2
5042   in
5043   loop proc_nrs;
5044
5045   (* Check tests. *)
5046   List.iter (
5047     function
5048       (* Ignore functions that have no tests.  We generate a
5049        * warning when the user does 'make check' instead.
5050        *)
5051     | name, _, _, _, [], _, _ -> ()
5052     | name, _, _, _, tests, _, _ ->
5053         let funcs =
5054           List.map (
5055             fun (_, _, test) ->
5056               match seq_of_test test with
5057               | [] ->
5058                   failwithf "%s has a test containing an empty sequence" name
5059               | cmds -> List.map List.hd cmds
5060           ) tests in
5061         let funcs = List.flatten funcs in
5062
5063         let tested = List.mem name funcs in
5064
5065         if not tested then
5066           failwithf "function %s has tests but does not test itself" name
5067   ) all_functions
5068
5069 (* 'pr' prints to the current output file. *)
5070 let chan = ref Pervasives.stdout
5071 let lines = ref 0
5072 let pr fs =
5073   ksprintf
5074     (fun str ->
5075        let i = count_chars '\n' str in
5076        lines := !lines + i;
5077        output_string !chan str
5078     ) fs
5079
5080 let copyright_years =
5081   let this_year = 1900 + (localtime (time ())).tm_year in
5082   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5083
5084 (* Generate a header block in a number of standard styles. *)
5085 type comment_style =
5086     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5087 type license = GPLv2plus | LGPLv2plus
5088
5089 let generate_header ?(extra_inputs = []) comment license =
5090   let inputs = "src/generator.ml" :: extra_inputs in
5091   let c = match comment with
5092     | CStyle ->         pr "/* "; " *"
5093     | CPlusPlusStyle -> pr "// "; "//"
5094     | HashStyle ->      pr "# ";  "#"
5095     | OCamlStyle ->     pr "(* "; " *"
5096     | HaskellStyle ->   pr "{- "; "  " in
5097   pr "libguestfs generated file\n";
5098   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5099   List.iter (pr "%s   %s\n" c) inputs;
5100   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5101   pr "%s\n" c;
5102   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5103   pr "%s\n" c;
5104   (match license with
5105    | GPLv2plus ->
5106        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5107        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5108        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5109        pr "%s (at your option) any later version.\n" c;
5110        pr "%s\n" c;
5111        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5112        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5113        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5114        pr "%s GNU General Public License for more details.\n" c;
5115        pr "%s\n" c;
5116        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5117        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5118        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5119
5120    | LGPLv2plus ->
5121        pr "%s This library is free software; you can redistribute it and/or\n" c;
5122        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5123        pr "%s License as published by the Free Software Foundation; either\n" c;
5124        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5125        pr "%s\n" c;
5126        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5127        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5128        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5129        pr "%s Lesser General Public License for more details.\n" c;
5130        pr "%s\n" c;
5131        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5132        pr "%s License along with this library; if not, write to the Free Software\n" c;
5133        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5134   );
5135   (match comment with
5136    | CStyle -> pr " */\n"
5137    | CPlusPlusStyle
5138    | HashStyle -> ()
5139    | OCamlStyle -> pr " *)\n"
5140    | HaskellStyle -> pr "-}\n"
5141   );
5142   pr "\n"
5143
5144 (* Start of main code generation functions below this line. *)
5145
5146 (* Generate the pod documentation for the C API. *)
5147 let rec generate_actions_pod () =
5148   List.iter (
5149     fun (shortname, style, _, flags, _, _, longdesc) ->
5150       if not (List.mem NotInDocs flags) then (
5151         let name = "guestfs_" ^ shortname in
5152         pr "=head2 %s\n\n" name;
5153         pr " ";
5154         generate_prototype ~extern:false ~handle:"g" name style;
5155         pr "\n\n";
5156         pr "%s\n\n" longdesc;
5157         (match fst style with
5158          | RErr ->
5159              pr "This function returns 0 on success or -1 on error.\n\n"
5160          | RInt _ ->
5161              pr "On error this function returns -1.\n\n"
5162          | RInt64 _ ->
5163              pr "On error this function returns -1.\n\n"
5164          | RBool _ ->
5165              pr "This function returns a C truth value on success or -1 on error.\n\n"
5166          | RConstString _ ->
5167              pr "This function returns a string, or NULL on error.
5168 The string is owned by the guest handle and must I<not> be freed.\n\n"
5169          | RConstOptString _ ->
5170              pr "This function returns a string which may be NULL.
5171 There is way to return an error from this function.
5172 The string is owned by the guest handle and must I<not> be freed.\n\n"
5173          | RString _ ->
5174              pr "This function returns a string, or NULL on error.
5175 I<The caller must free the returned string after use>.\n\n"
5176          | RStringList _ ->
5177              pr "This function returns a NULL-terminated array of strings
5178 (like L<environ(3)>), or NULL if there was an error.
5179 I<The caller must free the strings and the array after use>.\n\n"
5180          | RStruct (_, typ) ->
5181              pr "This function returns a C<struct guestfs_%s *>,
5182 or NULL if there was an error.
5183 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5184          | RStructList (_, typ) ->
5185              pr "This function returns a C<struct guestfs_%s_list *>
5186 (see E<lt>guestfs-structs.hE<gt>),
5187 or NULL if there was an error.
5188 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5189          | RHashtable _ ->
5190              pr "This function returns a NULL-terminated array of
5191 strings, or NULL if there was an error.
5192 The array of strings will always have length C<2n+1>, where
5193 C<n> keys and values alternate, followed by the trailing NULL entry.
5194 I<The caller must free the strings and the array after use>.\n\n"
5195          | RBufferOut _ ->
5196              pr "This function returns a buffer, or NULL on error.
5197 The size of the returned buffer is written to C<*size_r>.
5198 I<The caller must free the returned buffer after use>.\n\n"
5199         );
5200         if List.mem ProtocolLimitWarning flags then
5201           pr "%s\n\n" protocol_limit_warning;
5202         if List.mem DangerWillRobinson flags then
5203           pr "%s\n\n" danger_will_robinson;
5204         match deprecation_notice flags with
5205         | None -> ()
5206         | Some txt -> pr "%s\n\n" txt
5207       )
5208   ) all_functions_sorted
5209
5210 and generate_structs_pod () =
5211   (* Structs documentation. *)
5212   List.iter (
5213     fun (typ, cols) ->
5214       pr "=head2 guestfs_%s\n" typ;
5215       pr "\n";
5216       pr " struct guestfs_%s {\n" typ;
5217       List.iter (
5218         function
5219         | name, FChar -> pr "   char %s;\n" name
5220         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5221         | name, FInt32 -> pr "   int32_t %s;\n" name
5222         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5223         | name, FInt64 -> pr "   int64_t %s;\n" name
5224         | name, FString -> pr "   char *%s;\n" name
5225         | name, FBuffer ->
5226             pr "   /* The next two fields describe a byte array. */\n";
5227             pr "   uint32_t %s_len;\n" name;
5228             pr "   char *%s;\n" name
5229         | name, FUUID ->
5230             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5231             pr "   char %s[32];\n" name
5232         | name, FOptPercent ->
5233             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5234             pr "   float %s;\n" name
5235       ) cols;
5236       pr " };\n";
5237       pr " \n";
5238       pr " struct guestfs_%s_list {\n" typ;
5239       pr "   uint32_t len; /* Number of elements in list. */\n";
5240       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5241       pr " };\n";
5242       pr " \n";
5243       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5244       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5245         typ typ;
5246       pr "\n"
5247   ) structs
5248
5249 and generate_availability_pod () =
5250   (* Availability documentation. *)
5251   pr "=over 4\n";
5252   pr "\n";
5253   List.iter (
5254     fun (group, functions) ->
5255       pr "=item B<%s>\n" group;
5256       pr "\n";
5257       pr "The following functions:\n";
5258       List.iter (pr "L</guestfs_%s>\n") functions;
5259       pr "\n"
5260   ) optgroups;
5261   pr "=back\n";
5262   pr "\n"
5263
5264 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5265  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5266  *
5267  * We have to use an underscore instead of a dash because otherwise
5268  * rpcgen generates incorrect code.
5269  *
5270  * This header is NOT exported to clients, but see also generate_structs_h.
5271  *)
5272 and generate_xdr () =
5273   generate_header CStyle LGPLv2plus;
5274
5275   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5276   pr "typedef string str<>;\n";
5277   pr "\n";
5278
5279   (* Internal structures. *)
5280   List.iter (
5281     function
5282     | typ, cols ->
5283         pr "struct guestfs_int_%s {\n" typ;
5284         List.iter (function
5285                    | name, FChar -> pr "  char %s;\n" name
5286                    | name, FString -> pr "  string %s<>;\n" name
5287                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5288                    | name, FUUID -> pr "  opaque %s[32];\n" name
5289                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5290                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5291                    | name, FOptPercent -> pr "  float %s;\n" name
5292                   ) cols;
5293         pr "};\n";
5294         pr "\n";
5295         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5296         pr "\n";
5297   ) structs;
5298
5299   List.iter (
5300     fun (shortname, style, _, _, _, _, _) ->
5301       let name = "guestfs_" ^ shortname in
5302
5303       (match snd style with
5304        | [] -> ()
5305        | args ->
5306            pr "struct %s_args {\n" name;
5307            List.iter (
5308              function
5309              | Pathname n | Device n | Dev_or_Path n | String n ->
5310                  pr "  string %s<>;\n" n
5311              | OptString n -> pr "  str *%s;\n" n
5312              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5313              | Bool n -> pr "  bool %s;\n" n
5314              | Int n -> pr "  int %s;\n" n
5315              | Int64 n -> pr "  hyper %s;\n" n
5316              | FileIn _ | FileOut _ -> ()
5317            ) args;
5318            pr "};\n\n"
5319       );
5320       (match fst style with
5321        | RErr -> ()
5322        | RInt n ->
5323            pr "struct %s_ret {\n" name;
5324            pr "  int %s;\n" n;
5325            pr "};\n\n"
5326        | RInt64 n ->
5327            pr "struct %s_ret {\n" name;
5328            pr "  hyper %s;\n" n;
5329            pr "};\n\n"
5330        | RBool n ->
5331            pr "struct %s_ret {\n" name;
5332            pr "  bool %s;\n" n;
5333            pr "};\n\n"
5334        | RConstString _ | RConstOptString _ ->
5335            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5336        | RString n ->
5337            pr "struct %s_ret {\n" name;
5338            pr "  string %s<>;\n" n;
5339            pr "};\n\n"
5340        | RStringList n ->
5341            pr "struct %s_ret {\n" name;
5342            pr "  str %s<>;\n" n;
5343            pr "};\n\n"
5344        | RStruct (n, typ) ->
5345            pr "struct %s_ret {\n" name;
5346            pr "  guestfs_int_%s %s;\n" typ n;
5347            pr "};\n\n"
5348        | RStructList (n, typ) ->
5349            pr "struct %s_ret {\n" name;
5350            pr "  guestfs_int_%s_list %s;\n" typ n;
5351            pr "};\n\n"
5352        | RHashtable n ->
5353            pr "struct %s_ret {\n" name;
5354            pr "  str %s<>;\n" n;
5355            pr "};\n\n"
5356        | RBufferOut n ->
5357            pr "struct %s_ret {\n" name;
5358            pr "  opaque %s<>;\n" n;
5359            pr "};\n\n"
5360       );
5361   ) daemon_functions;
5362
5363   (* Table of procedure numbers. *)
5364   pr "enum guestfs_procedure {\n";
5365   List.iter (
5366     fun (shortname, _, proc_nr, _, _, _, _) ->
5367       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5368   ) daemon_functions;
5369   pr "  GUESTFS_PROC_NR_PROCS\n";
5370   pr "};\n";
5371   pr "\n";
5372
5373   (* Having to choose a maximum message size is annoying for several
5374    * reasons (it limits what we can do in the API), but it (a) makes
5375    * the protocol a lot simpler, and (b) provides a bound on the size
5376    * of the daemon which operates in limited memory space.
5377    *)
5378   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5379   pr "\n";
5380
5381   (* Message header, etc. *)
5382   pr "\
5383 /* The communication protocol is now documented in the guestfs(3)
5384  * manpage.
5385  */
5386
5387 const GUESTFS_PROGRAM = 0x2000F5F5;
5388 const GUESTFS_PROTOCOL_VERSION = 1;
5389
5390 /* These constants must be larger than any possible message length. */
5391 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5392 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5393
5394 enum guestfs_message_direction {
5395   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5396   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5397 };
5398
5399 enum guestfs_message_status {
5400   GUESTFS_STATUS_OK = 0,
5401   GUESTFS_STATUS_ERROR = 1
5402 };
5403
5404 const GUESTFS_ERROR_LEN = 256;
5405
5406 struct guestfs_message_error {
5407   string error_message<GUESTFS_ERROR_LEN>;
5408 };
5409
5410 struct guestfs_message_header {
5411   unsigned prog;                     /* GUESTFS_PROGRAM */
5412   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5413   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5414   guestfs_message_direction direction;
5415   unsigned serial;                   /* message serial number */
5416   guestfs_message_status status;
5417 };
5418
5419 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5420
5421 struct guestfs_chunk {
5422   int cancel;                        /* if non-zero, transfer is cancelled */
5423   /* data size is 0 bytes if the transfer has finished successfully */
5424   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5425 };
5426 "
5427
5428 (* Generate the guestfs-structs.h file. *)
5429 and generate_structs_h () =
5430   generate_header CStyle LGPLv2plus;
5431
5432   (* This is a public exported header file containing various
5433    * structures.  The structures are carefully written to have
5434    * exactly the same in-memory format as the XDR structures that
5435    * we use on the wire to the daemon.  The reason for creating
5436    * copies of these structures here is just so we don't have to
5437    * export the whole of guestfs_protocol.h (which includes much
5438    * unrelated and XDR-dependent stuff that we don't want to be
5439    * public, or required by clients).
5440    *
5441    * To reiterate, we will pass these structures to and from the
5442    * client with a simple assignment or memcpy, so the format
5443    * must be identical to what rpcgen / the RFC defines.
5444    *)
5445
5446   (* Public structures. *)
5447   List.iter (
5448     fun (typ, cols) ->
5449       pr "struct guestfs_%s {\n" typ;
5450       List.iter (
5451         function
5452         | name, FChar -> pr "  char %s;\n" name
5453         | name, FString -> pr "  char *%s;\n" name
5454         | name, FBuffer ->
5455             pr "  uint32_t %s_len;\n" name;
5456             pr "  char *%s;\n" name
5457         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5458         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5459         | name, FInt32 -> pr "  int32_t %s;\n" name
5460         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5461         | name, FInt64 -> pr "  int64_t %s;\n" name
5462         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5463       ) cols;
5464       pr "};\n";
5465       pr "\n";
5466       pr "struct guestfs_%s_list {\n" typ;
5467       pr "  uint32_t len;\n";
5468       pr "  struct guestfs_%s *val;\n" typ;
5469       pr "};\n";
5470       pr "\n";
5471       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5472       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5473       pr "\n"
5474   ) structs
5475
5476 (* Generate the guestfs-actions.h file. *)
5477 and generate_actions_h () =
5478   generate_header CStyle LGPLv2plus;
5479   List.iter (
5480     fun (shortname, style, _, _, _, _, _) ->
5481       let name = "guestfs_" ^ shortname in
5482       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5483         name style
5484   ) all_functions
5485
5486 (* Generate the guestfs-internal-actions.h file. *)
5487 and generate_internal_actions_h () =
5488   generate_header CStyle LGPLv2plus;
5489   List.iter (
5490     fun (shortname, style, _, _, _, _, _) ->
5491       let name = "guestfs__" ^ shortname in
5492       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5493         name style
5494   ) non_daemon_functions
5495
5496 (* Generate the client-side dispatch stubs. *)
5497 and generate_client_actions () =
5498   generate_header CStyle LGPLv2plus;
5499
5500   pr "\
5501 #include <stdio.h>
5502 #include <stdlib.h>
5503 #include <stdint.h>
5504 #include <string.h>
5505 #include <inttypes.h>
5506
5507 #include \"guestfs.h\"
5508 #include \"guestfs-internal.h\"
5509 #include \"guestfs-internal-actions.h\"
5510 #include \"guestfs_protocol.h\"
5511
5512 #define error guestfs_error
5513 //#define perrorf guestfs_perrorf
5514 #define safe_malloc guestfs_safe_malloc
5515 #define safe_realloc guestfs_safe_realloc
5516 //#define safe_strdup guestfs_safe_strdup
5517 #define safe_memdup guestfs_safe_memdup
5518
5519 /* Check the return message from a call for validity. */
5520 static int
5521 check_reply_header (guestfs_h *g,
5522                     const struct guestfs_message_header *hdr,
5523                     unsigned int proc_nr, unsigned int serial)
5524 {
5525   if (hdr->prog != GUESTFS_PROGRAM) {
5526     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5527     return -1;
5528   }
5529   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5530     error (g, \"wrong protocol version (%%d/%%d)\",
5531            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5532     return -1;
5533   }
5534   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5535     error (g, \"unexpected message direction (%%d/%%d)\",
5536            hdr->direction, GUESTFS_DIRECTION_REPLY);
5537     return -1;
5538   }
5539   if (hdr->proc != proc_nr) {
5540     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5541     return -1;
5542   }
5543   if (hdr->serial != serial) {
5544     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5545     return -1;
5546   }
5547
5548   return 0;
5549 }
5550
5551 /* Check we are in the right state to run a high-level action. */
5552 static int
5553 check_state (guestfs_h *g, const char *caller)
5554 {
5555   if (!guestfs__is_ready (g)) {
5556     if (guestfs__is_config (g) || guestfs__is_launching (g))
5557       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5558         caller);
5559     else
5560       error (g, \"%%s called from the wrong state, %%d != READY\",
5561         caller, guestfs__get_state (g));
5562     return -1;
5563   }
5564   return 0;
5565 }
5566
5567 ";
5568
5569   (* Generate code to generate guestfish call traces. *)
5570   let trace_call shortname style =
5571     pr "  if (guestfs__get_trace (g)) {\n";
5572
5573     let needs_i =
5574       List.exists (function
5575                    | StringList _ | DeviceList _ -> true
5576                    | _ -> false) (snd style) in
5577     if needs_i then (
5578       pr "    int i;\n";
5579       pr "\n"
5580     );
5581
5582     pr "    printf (\"%s\");\n" shortname;
5583     List.iter (
5584       function
5585       | String n                        (* strings *)
5586       | Device n
5587       | Pathname n
5588       | Dev_or_Path n
5589       | FileIn n
5590       | FileOut n ->
5591           (* guestfish doesn't support string escaping, so neither do we *)
5592           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5593       | OptString n ->                  (* string option *)
5594           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5595           pr "    else printf (\" null\");\n"
5596       | StringList n
5597       | DeviceList n ->                 (* string list *)
5598           pr "    putchar (' ');\n";
5599           pr "    putchar ('\"');\n";
5600           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5601           pr "      if (i > 0) putchar (' ');\n";
5602           pr "      fputs (%s[i], stdout);\n" n;
5603           pr "    }\n";
5604           pr "    putchar ('\"');\n";
5605       | Bool n ->                       (* boolean *)
5606           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5607       | Int n ->                        (* int *)
5608           pr "    printf (\" %%d\", %s);\n" n
5609       | Int64 n ->
5610           pr "    printf (\" %%\" PRIi64, %s);\n" n
5611     ) (snd style);
5612     pr "    putchar ('\\n');\n";
5613     pr "  }\n";
5614     pr "\n";
5615   in
5616
5617   (* For non-daemon functions, generate a wrapper around each function. *)
5618   List.iter (
5619     fun (shortname, style, _, _, _, _, _) ->
5620       let name = "guestfs_" ^ shortname in
5621
5622       generate_prototype ~extern:false ~semicolon:false ~newline:true
5623         ~handle:"g" name style;
5624       pr "{\n";
5625       trace_call shortname style;
5626       pr "  return guestfs__%s " shortname;
5627       generate_c_call_args ~handle:"g" style;
5628       pr ";\n";
5629       pr "}\n";
5630       pr "\n"
5631   ) non_daemon_functions;
5632
5633   (* Client-side stubs for each function. *)
5634   List.iter (
5635     fun (shortname, style, _, _, _, _, _) ->
5636       let name = "guestfs_" ^ shortname in
5637
5638       (* Generate the action stub. *)
5639       generate_prototype ~extern:false ~semicolon:false ~newline:true
5640         ~handle:"g" name style;
5641
5642       let error_code =
5643         match fst style with
5644         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5645         | RConstString _ | RConstOptString _ ->
5646             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5647         | RString _ | RStringList _
5648         | RStruct _ | RStructList _
5649         | RHashtable _ | RBufferOut _ ->
5650             "NULL" in
5651
5652       pr "{\n";
5653
5654       (match snd style with
5655        | [] -> ()
5656        | _ -> pr "  struct %s_args args;\n" name
5657       );
5658
5659       pr "  guestfs_message_header hdr;\n";
5660       pr "  guestfs_message_error err;\n";
5661       let has_ret =
5662         match fst style with
5663         | RErr -> false
5664         | RConstString _ | RConstOptString _ ->
5665             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5666         | RInt _ | RInt64 _
5667         | RBool _ | RString _ | RStringList _
5668         | RStruct _ | RStructList _
5669         | RHashtable _ | RBufferOut _ ->
5670             pr "  struct %s_ret ret;\n" name;
5671             true in
5672
5673       pr "  int serial;\n";
5674       pr "  int r;\n";
5675       pr "\n";
5676       trace_call shortname style;
5677       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5678       pr "  guestfs___set_busy (g);\n";
5679       pr "\n";
5680
5681       (* Send the main header and arguments. *)
5682       (match snd style with
5683        | [] ->
5684            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5685              (String.uppercase shortname)
5686        | args ->
5687            List.iter (
5688              function
5689              | Pathname n | Device n | Dev_or_Path n | String n ->
5690                  pr "  args.%s = (char *) %s;\n" n n
5691              | OptString n ->
5692                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5693              | StringList n | DeviceList n ->
5694                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5695                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5696              | Bool n ->
5697                  pr "  args.%s = %s;\n" n n
5698              | Int n ->
5699                  pr "  args.%s = %s;\n" n n
5700              | Int64 n ->
5701                  pr "  args.%s = %s;\n" n n
5702              | FileIn _ | FileOut _ -> ()
5703            ) args;
5704            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5705              (String.uppercase shortname);
5706            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5707              name;
5708       );
5709       pr "  if (serial == -1) {\n";
5710       pr "    guestfs___end_busy (g);\n";
5711       pr "    return %s;\n" error_code;
5712       pr "  }\n";
5713       pr "\n";
5714
5715       (* Send any additional files (FileIn) requested. *)
5716       let need_read_reply_label = ref false in
5717       List.iter (
5718         function
5719         | FileIn n ->
5720             pr "  r = guestfs___send_file (g, %s);\n" n;
5721             pr "  if (r == -1) {\n";
5722             pr "    guestfs___end_busy (g);\n";
5723             pr "    return %s;\n" error_code;
5724             pr "  }\n";
5725             pr "  if (r == -2) /* daemon cancelled */\n";
5726             pr "    goto read_reply;\n";
5727             need_read_reply_label := true;
5728             pr "\n";
5729         | _ -> ()
5730       ) (snd style);
5731
5732       (* Wait for the reply from the remote end. *)
5733       if !need_read_reply_label then pr " read_reply:\n";
5734       pr "  memset (&hdr, 0, sizeof hdr);\n";
5735       pr "  memset (&err, 0, sizeof err);\n";
5736       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5737       pr "\n";
5738       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5739       if not has_ret then
5740         pr "NULL, NULL"
5741       else
5742         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5743       pr ");\n";
5744
5745       pr "  if (r == -1) {\n";
5746       pr "    guestfs___end_busy (g);\n";
5747       pr "    return %s;\n" error_code;
5748       pr "  }\n";
5749       pr "\n";
5750
5751       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5752         (String.uppercase shortname);
5753       pr "    guestfs___end_busy (g);\n";
5754       pr "    return %s;\n" error_code;
5755       pr "  }\n";
5756       pr "\n";
5757
5758       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5759       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5760       pr "    free (err.error_message);\n";
5761       pr "    guestfs___end_busy (g);\n";
5762       pr "    return %s;\n" error_code;
5763       pr "  }\n";
5764       pr "\n";
5765
5766       (* Expecting to receive further files (FileOut)? *)
5767       List.iter (
5768         function
5769         | FileOut n ->
5770             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5771             pr "    guestfs___end_busy (g);\n";
5772             pr "    return %s;\n" error_code;
5773             pr "  }\n";
5774             pr "\n";
5775         | _ -> ()
5776       ) (snd style);
5777
5778       pr "  guestfs___end_busy (g);\n";
5779
5780       (match fst style with
5781        | RErr -> pr "  return 0;\n"
5782        | RInt n | RInt64 n | RBool n ->
5783            pr "  return ret.%s;\n" n
5784        | RConstString _ | RConstOptString _ ->
5785            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5786        | RString n ->
5787            pr "  return ret.%s; /* caller will free */\n" n
5788        | RStringList n | RHashtable n ->
5789            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5790            pr "  ret.%s.%s_val =\n" n n;
5791            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5792            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5793              n n;
5794            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5795            pr "  return ret.%s.%s_val;\n" n n
5796        | RStruct (n, _) ->
5797            pr "  /* caller will free this */\n";
5798            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5799        | RStructList (n, _) ->
5800            pr "  /* caller will free this */\n";
5801            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5802        | RBufferOut n ->
5803            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5804            pr "   * _val might be NULL here.  To make the API saner for\n";
5805            pr "   * callers, we turn this case into a unique pointer (using\n";
5806            pr "   * malloc(1)).\n";
5807            pr "   */\n";
5808            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5809            pr "    *size_r = ret.%s.%s_len;\n" n n;
5810            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5811            pr "  } else {\n";
5812            pr "    free (ret.%s.%s_val);\n" n n;
5813            pr "    char *p = safe_malloc (g, 1);\n";
5814            pr "    *size_r = ret.%s.%s_len;\n" n n;
5815            pr "    return p;\n";
5816            pr "  }\n";
5817       );
5818
5819       pr "}\n\n"
5820   ) daemon_functions;
5821
5822   (* Functions to free structures. *)
5823   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5824   pr " * structure format is identical to the XDR format.  See note in\n";
5825   pr " * generator.ml.\n";
5826   pr " */\n";
5827   pr "\n";
5828
5829   List.iter (
5830     fun (typ, _) ->
5831       pr "void\n";
5832       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5833       pr "{\n";
5834       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5835       pr "  free (x);\n";
5836       pr "}\n";
5837       pr "\n";
5838
5839       pr "void\n";
5840       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5841       pr "{\n";
5842       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5843       pr "  free (x);\n";
5844       pr "}\n";
5845       pr "\n";
5846
5847   ) structs;
5848
5849 (* Generate daemon/actions.h. *)
5850 and generate_daemon_actions_h () =
5851   generate_header CStyle GPLv2plus;
5852
5853   pr "#include \"../src/guestfs_protocol.h\"\n";
5854   pr "\n";
5855
5856   List.iter (
5857     fun (name, style, _, _, _, _, _) ->
5858       generate_prototype
5859         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5860         name style;
5861   ) daemon_functions
5862
5863 (* Generate the linker script which controls the visibility of
5864  * symbols in the public ABI and ensures no other symbols get
5865  * exported accidentally.
5866  *)
5867 and generate_linker_script () =
5868   generate_header HashStyle GPLv2plus;
5869
5870   let globals = [
5871     "guestfs_create";
5872     "guestfs_close";
5873     "guestfs_get_error_handler";
5874     "guestfs_get_out_of_memory_handler";
5875     "guestfs_last_error";
5876     "guestfs_set_error_handler";
5877     "guestfs_set_launch_done_callback";
5878     "guestfs_set_log_message_callback";
5879     "guestfs_set_out_of_memory_handler";
5880     "guestfs_set_subprocess_quit_callback";
5881
5882     (* Unofficial parts of the API: the bindings code use these
5883      * functions, so it is useful to export them.
5884      *)
5885     "guestfs_safe_calloc";
5886     "guestfs_safe_malloc";
5887   ] in
5888   let functions =
5889     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5890       all_functions in
5891   let structs =
5892     List.concat (
5893       List.map (fun (typ, _) ->
5894                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5895         structs
5896     ) in
5897   let globals = List.sort compare (globals @ functions @ structs) in
5898
5899   pr "{\n";
5900   pr "    global:\n";
5901   List.iter (pr "        %s;\n") globals;
5902   pr "\n";
5903
5904   pr "    local:\n";
5905   pr "        *;\n";
5906   pr "};\n"
5907
5908 (* Generate the server-side stubs. *)
5909 and generate_daemon_actions () =
5910   generate_header CStyle GPLv2plus;
5911
5912   pr "#include <config.h>\n";
5913   pr "\n";
5914   pr "#include <stdio.h>\n";
5915   pr "#include <stdlib.h>\n";
5916   pr "#include <string.h>\n";
5917   pr "#include <inttypes.h>\n";
5918   pr "#include <rpc/types.h>\n";
5919   pr "#include <rpc/xdr.h>\n";
5920   pr "\n";
5921   pr "#include \"daemon.h\"\n";
5922   pr "#include \"c-ctype.h\"\n";
5923   pr "#include \"../src/guestfs_protocol.h\"\n";
5924   pr "#include \"actions.h\"\n";
5925   pr "\n";
5926
5927   List.iter (
5928     fun (name, style, _, _, _, _, _) ->
5929       (* Generate server-side stubs. *)
5930       pr "static void %s_stub (XDR *xdr_in)\n" name;
5931       pr "{\n";
5932       let error_code =
5933         match fst style with
5934         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5935         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5936         | RBool _ -> pr "  int r;\n"; "-1"
5937         | RConstString _ | RConstOptString _ ->
5938             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5939         | RString _ -> pr "  char *r;\n"; "NULL"
5940         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5941         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5942         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5943         | RBufferOut _ ->
5944             pr "  size_t size = 1;\n";
5945             pr "  char *r;\n";
5946             "NULL" in
5947
5948       (match snd style with
5949        | [] -> ()
5950        | args ->
5951            pr "  struct guestfs_%s_args args;\n" name;
5952            List.iter (
5953              function
5954              | Device n | Dev_or_Path n
5955              | Pathname n
5956              | String n -> ()
5957              | OptString n -> pr "  char *%s;\n" n
5958              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5959              | Bool n -> pr "  int %s;\n" n
5960              | Int n -> pr "  int %s;\n" n
5961              | Int64 n -> pr "  int64_t %s;\n" n
5962              | FileIn _ | FileOut _ -> ()
5963            ) args
5964       );
5965       pr "\n";
5966
5967       (match snd style with
5968        | [] -> ()
5969        | args ->
5970            pr "  memset (&args, 0, sizeof args);\n";
5971            pr "\n";
5972            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5973            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5974            pr "    return;\n";
5975            pr "  }\n";
5976            let pr_args n =
5977              pr "  char *%s = args.%s;\n" n n
5978            in
5979            let pr_list_handling_code n =
5980              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5981              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5982              pr "  if (%s == NULL) {\n" n;
5983              pr "    reply_with_perror (\"realloc\");\n";
5984              pr "    goto done;\n";
5985              pr "  }\n";
5986              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5987              pr "  args.%s.%s_val = %s;\n" n n n;
5988            in
5989            List.iter (
5990              function
5991              | Pathname n ->
5992                  pr_args n;
5993                  pr "  ABS_PATH (%s, goto done);\n" n;
5994              | Device n ->
5995                  pr_args n;
5996                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5997              | Dev_or_Path n ->
5998                  pr_args n;
5999                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6000              | String n -> pr_args n
6001              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6002              | StringList n ->
6003                  pr_list_handling_code n;
6004              | DeviceList n ->
6005                  pr_list_handling_code n;
6006                  pr "  /* Ensure that each is a device,\n";
6007                  pr "   * and perform device name translation. */\n";
6008                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6009                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6010                  pr "  }\n";
6011              | Bool n -> pr "  %s = args.%s;\n" n n
6012              | Int n -> pr "  %s = args.%s;\n" n n
6013              | Int64 n -> pr "  %s = args.%s;\n" n n
6014              | FileIn _ | FileOut _ -> ()
6015            ) args;
6016            pr "\n"
6017       );
6018
6019
6020       (* this is used at least for do_equal *)
6021       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6022         (* Emit NEED_ROOT just once, even when there are two or
6023            more Pathname args *)
6024         pr "  NEED_ROOT (goto done);\n";
6025       );
6026
6027       (* Don't want to call the impl with any FileIn or FileOut
6028        * parameters, since these go "outside" the RPC protocol.
6029        *)
6030       let args' =
6031         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6032           (snd style) in
6033       pr "  r = do_%s " name;
6034       generate_c_call_args (fst style, args');
6035       pr ";\n";
6036
6037       (match fst style with
6038        | RErr | RInt _ | RInt64 _ | RBool _
6039        | RConstString _ | RConstOptString _
6040        | RString _ | RStringList _ | RHashtable _
6041        | RStruct (_, _) | RStructList (_, _) ->
6042            pr "  if (r == %s)\n" error_code;
6043            pr "    /* do_%s has already called reply_with_error */\n" name;
6044            pr "    goto done;\n";
6045            pr "\n"
6046        | RBufferOut _ ->
6047            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6048            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6049            pr "   */\n";
6050            pr "  if (size == 1 && r == %s)\n" error_code;
6051            pr "    /* do_%s has already called reply_with_error */\n" name;
6052            pr "    goto done;\n";
6053            pr "\n"
6054       );
6055
6056       (* If there are any FileOut parameters, then the impl must
6057        * send its own reply.
6058        *)
6059       let no_reply =
6060         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6061       if no_reply then
6062         pr "  /* do_%s has already sent a reply */\n" name
6063       else (
6064         match fst style with
6065         | RErr -> pr "  reply (NULL, NULL);\n"
6066         | RInt n | RInt64 n | RBool n ->
6067             pr "  struct guestfs_%s_ret ret;\n" name;
6068             pr "  ret.%s = r;\n" n;
6069             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6070               name
6071         | RConstString _ | RConstOptString _ ->
6072             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6073         | RString n ->
6074             pr "  struct guestfs_%s_ret ret;\n" name;
6075             pr "  ret.%s = r;\n" n;
6076             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6077               name;
6078             pr "  free (r);\n"
6079         | RStringList n | RHashtable n ->
6080             pr "  struct guestfs_%s_ret ret;\n" name;
6081             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6082             pr "  ret.%s.%s_val = r;\n" n n;
6083             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6084               name;
6085             pr "  free_strings (r);\n"
6086         | RStruct (n, _) ->
6087             pr "  struct guestfs_%s_ret ret;\n" name;
6088             pr "  ret.%s = *r;\n" n;
6089             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6090               name;
6091             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6092               name
6093         | RStructList (n, _) ->
6094             pr "  struct guestfs_%s_ret ret;\n" name;
6095             pr "  ret.%s = *r;\n" n;
6096             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6097               name;
6098             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6099               name
6100         | RBufferOut n ->
6101             pr "  struct guestfs_%s_ret ret;\n" name;
6102             pr "  ret.%s.%s_val = r;\n" n n;
6103             pr "  ret.%s.%s_len = size;\n" n n;
6104             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6105               name;
6106             pr "  free (r);\n"
6107       );
6108
6109       (* Free the args. *)
6110       (match snd style with
6111        | [] ->
6112            pr "done: ;\n";
6113        | _ ->
6114            pr "done:\n";
6115            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6116              name
6117       );
6118
6119       pr "}\n\n";
6120   ) daemon_functions;
6121
6122   (* Dispatch function. *)
6123   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6124   pr "{\n";
6125   pr "  switch (proc_nr) {\n";
6126
6127   List.iter (
6128     fun (name, style, _, _, _, _, _) ->
6129       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6130       pr "      %s_stub (xdr_in);\n" name;
6131       pr "      break;\n"
6132   ) daemon_functions;
6133
6134   pr "    default:\n";
6135   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";
6136   pr "  }\n";
6137   pr "}\n";
6138   pr "\n";
6139
6140   (* LVM columns and tokenization functions. *)
6141   (* XXX This generates crap code.  We should rethink how we
6142    * do this parsing.
6143    *)
6144   List.iter (
6145     function
6146     | typ, cols ->
6147         pr "static const char *lvm_%s_cols = \"%s\";\n"
6148           typ (String.concat "," (List.map fst cols));
6149         pr "\n";
6150
6151         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6152         pr "{\n";
6153         pr "  char *tok, *p, *next;\n";
6154         pr "  int i, j;\n";
6155         pr "\n";
6156         (*
6157           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6158           pr "\n";
6159         *)
6160         pr "  if (!str) {\n";
6161         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6162         pr "    return -1;\n";
6163         pr "  }\n";
6164         pr "  if (!*str || c_isspace (*str)) {\n";
6165         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6166         pr "    return -1;\n";
6167         pr "  }\n";
6168         pr "  tok = str;\n";
6169         List.iter (
6170           fun (name, coltype) ->
6171             pr "  if (!tok) {\n";
6172             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6173             pr "    return -1;\n";
6174             pr "  }\n";
6175             pr "  p = strchrnul (tok, ',');\n";
6176             pr "  if (*p) next = p+1; else next = NULL;\n";
6177             pr "  *p = '\\0';\n";
6178             (match coltype with
6179              | FString ->
6180                  pr "  r->%s = strdup (tok);\n" name;
6181                  pr "  if (r->%s == NULL) {\n" name;
6182                  pr "    perror (\"strdup\");\n";
6183                  pr "    return -1;\n";
6184                  pr "  }\n"
6185              | FUUID ->
6186                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6187                  pr "    if (tok[j] == '\\0') {\n";
6188                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6189                  pr "      return -1;\n";
6190                  pr "    } else if (tok[j] != '-')\n";
6191                  pr "      r->%s[i++] = tok[j];\n" name;
6192                  pr "  }\n";
6193              | FBytes ->
6194                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6195                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6196                  pr "    return -1;\n";
6197                  pr "  }\n";
6198              | FInt64 ->
6199                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6200                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6201                  pr "    return -1;\n";
6202                  pr "  }\n";
6203              | FOptPercent ->
6204                  pr "  if (tok[0] == '\\0')\n";
6205                  pr "    r->%s = -1;\n" name;
6206                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6207                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6208                  pr "    return -1;\n";
6209                  pr "  }\n";
6210              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6211                  assert false (* can never be an LVM column *)
6212             );
6213             pr "  tok = next;\n";
6214         ) cols;
6215
6216         pr "  if (tok != NULL) {\n";
6217         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6218         pr "    return -1;\n";
6219         pr "  }\n";
6220         pr "  return 0;\n";
6221         pr "}\n";
6222         pr "\n";
6223
6224         pr "guestfs_int_lvm_%s_list *\n" typ;
6225         pr "parse_command_line_%ss (void)\n" typ;
6226         pr "{\n";
6227         pr "  char *out, *err;\n";
6228         pr "  char *p, *pend;\n";
6229         pr "  int r, i;\n";
6230         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6231         pr "  void *newp;\n";
6232         pr "\n";
6233         pr "  ret = malloc (sizeof *ret);\n";
6234         pr "  if (!ret) {\n";
6235         pr "    reply_with_perror (\"malloc\");\n";
6236         pr "    return NULL;\n";
6237         pr "  }\n";
6238         pr "\n";
6239         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6240         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6241         pr "\n";
6242         pr "  r = command (&out, &err,\n";
6243         pr "           \"lvm\", \"%ss\",\n" typ;
6244         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6245         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6246         pr "  if (r == -1) {\n";
6247         pr "    reply_with_error (\"%%s\", err);\n";
6248         pr "    free (out);\n";
6249         pr "    free (err);\n";
6250         pr "    free (ret);\n";
6251         pr "    return NULL;\n";
6252         pr "  }\n";
6253         pr "\n";
6254         pr "  free (err);\n";
6255         pr "\n";
6256         pr "  /* Tokenize each line of the output. */\n";
6257         pr "  p = out;\n";
6258         pr "  i = 0;\n";
6259         pr "  while (p) {\n";
6260         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6261         pr "    if (pend) {\n";
6262         pr "      *pend = '\\0';\n";
6263         pr "      pend++;\n";
6264         pr "    }\n";
6265         pr "\n";
6266         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6267         pr "      p++;\n";
6268         pr "\n";
6269         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6270         pr "      p = pend;\n";
6271         pr "      continue;\n";
6272         pr "    }\n";
6273         pr "\n";
6274         pr "    /* Allocate some space to store this next entry. */\n";
6275         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6276         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6277         pr "    if (newp == NULL) {\n";
6278         pr "      reply_with_perror (\"realloc\");\n";
6279         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6280         pr "      free (ret);\n";
6281         pr "      free (out);\n";
6282         pr "      return NULL;\n";
6283         pr "    }\n";
6284         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6285         pr "\n";
6286         pr "    /* Tokenize the next entry. */\n";
6287         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6288         pr "    if (r == -1) {\n";
6289         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6290         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6291         pr "      free (ret);\n";
6292         pr "      free (out);\n";
6293         pr "      return NULL;\n";
6294         pr "    }\n";
6295         pr "\n";
6296         pr "    ++i;\n";
6297         pr "    p = pend;\n";
6298         pr "  }\n";
6299         pr "\n";
6300         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6301         pr "\n";
6302         pr "  free (out);\n";
6303         pr "  return ret;\n";
6304         pr "}\n"
6305
6306   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6307
6308 (* Generate a list of function names, for debugging in the daemon.. *)
6309 and generate_daemon_names () =
6310   generate_header CStyle GPLv2plus;
6311
6312   pr "#include <config.h>\n";
6313   pr "\n";
6314   pr "#include \"daemon.h\"\n";
6315   pr "\n";
6316
6317   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6318   pr "const char *function_names[] = {\n";
6319   List.iter (
6320     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6321   ) daemon_functions;
6322   pr "};\n";
6323
6324 (* Generate the optional groups for the daemon to implement
6325  * guestfs_available.
6326  *)
6327 and generate_daemon_optgroups_c () =
6328   generate_header CStyle GPLv2plus;
6329
6330   pr "#include <config.h>\n";
6331   pr "\n";
6332   pr "#include \"daemon.h\"\n";
6333   pr "#include \"optgroups.h\"\n";
6334   pr "\n";
6335
6336   pr "struct optgroup optgroups[] = {\n";
6337   List.iter (
6338     fun (group, _) ->
6339       pr "  { \"%s\", optgroup_%s_available },\n" group group
6340   ) optgroups;
6341   pr "  { NULL, NULL }\n";
6342   pr "};\n"
6343
6344 and generate_daemon_optgroups_h () =
6345   generate_header CStyle GPLv2plus;
6346
6347   List.iter (
6348     fun (group, _) ->
6349       pr "extern int optgroup_%s_available (void);\n" group
6350   ) optgroups
6351
6352 (* Generate the tests. *)
6353 and generate_tests () =
6354   generate_header CStyle GPLv2plus;
6355
6356   pr "\
6357 #include <stdio.h>
6358 #include <stdlib.h>
6359 #include <string.h>
6360 #include <unistd.h>
6361 #include <sys/types.h>
6362 #include <fcntl.h>
6363
6364 #include \"guestfs.h\"
6365 #include \"guestfs-internal.h\"
6366
6367 static guestfs_h *g;
6368 static int suppress_error = 0;
6369
6370 static void print_error (guestfs_h *g, void *data, const char *msg)
6371 {
6372   if (!suppress_error)
6373     fprintf (stderr, \"%%s\\n\", msg);
6374 }
6375
6376 /* FIXME: nearly identical code appears in fish.c */
6377 static void print_strings (char *const *argv)
6378 {
6379   int argc;
6380
6381   for (argc = 0; argv[argc] != NULL; ++argc)
6382     printf (\"\\t%%s\\n\", argv[argc]);
6383 }
6384
6385 /*
6386 static void print_table (char const *const *argv)
6387 {
6388   int i;
6389
6390   for (i = 0; argv[i] != NULL; i += 2)
6391     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6392 }
6393 */
6394
6395 ";
6396
6397   (* Generate a list of commands which are not tested anywhere. *)
6398   pr "static void no_test_warnings (void)\n";
6399   pr "{\n";
6400
6401   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6402   List.iter (
6403     fun (_, _, _, _, tests, _, _) ->
6404       let tests = filter_map (
6405         function
6406         | (_, (Always|If _|Unless _), test) -> Some test
6407         | (_, Disabled, _) -> None
6408       ) tests in
6409       let seq = List.concat (List.map seq_of_test tests) in
6410       let cmds_tested = List.map List.hd seq in
6411       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6412   ) all_functions;
6413
6414   List.iter (
6415     fun (name, _, _, _, _, _, _) ->
6416       if not (Hashtbl.mem hash name) then
6417         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6418   ) all_functions;
6419
6420   pr "}\n";
6421   pr "\n";
6422
6423   (* Generate the actual tests.  Note that we generate the tests
6424    * in reverse order, deliberately, so that (in general) the
6425    * newest tests run first.  This makes it quicker and easier to
6426    * debug them.
6427    *)
6428   let test_names =
6429     List.map (
6430       fun (name, _, _, flags, tests, _, _) ->
6431         mapi (generate_one_test name flags) tests
6432     ) (List.rev all_functions) in
6433   let test_names = List.concat test_names in
6434   let nr_tests = List.length test_names in
6435
6436   pr "\
6437 int main (int argc, char *argv[])
6438 {
6439   char c = 0;
6440   unsigned long int n_failed = 0;
6441   const char *filename;
6442   int fd;
6443   int nr_tests, test_num = 0;
6444
6445   setbuf (stdout, NULL);
6446
6447   no_test_warnings ();
6448
6449   g = guestfs_create ();
6450   if (g == NULL) {
6451     printf (\"guestfs_create FAILED\\n\");
6452     exit (EXIT_FAILURE);
6453   }
6454
6455   guestfs_set_error_handler (g, print_error, NULL);
6456
6457   guestfs_set_path (g, \"../appliance\");
6458
6459   filename = \"test1.img\";
6460   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6461   if (fd == -1) {
6462     perror (filename);
6463     exit (EXIT_FAILURE);
6464   }
6465   if (lseek (fd, %d, SEEK_SET) == -1) {
6466     perror (\"lseek\");
6467     close (fd);
6468     unlink (filename);
6469     exit (EXIT_FAILURE);
6470   }
6471   if (write (fd, &c, 1) == -1) {
6472     perror (\"write\");
6473     close (fd);
6474     unlink (filename);
6475     exit (EXIT_FAILURE);
6476   }
6477   if (close (fd) == -1) {
6478     perror (filename);
6479     unlink (filename);
6480     exit (EXIT_FAILURE);
6481   }
6482   if (guestfs_add_drive (g, filename) == -1) {
6483     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6484     exit (EXIT_FAILURE);
6485   }
6486
6487   filename = \"test2.img\";
6488   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6489   if (fd == -1) {
6490     perror (filename);
6491     exit (EXIT_FAILURE);
6492   }
6493   if (lseek (fd, %d, SEEK_SET) == -1) {
6494     perror (\"lseek\");
6495     close (fd);
6496     unlink (filename);
6497     exit (EXIT_FAILURE);
6498   }
6499   if (write (fd, &c, 1) == -1) {
6500     perror (\"write\");
6501     close (fd);
6502     unlink (filename);
6503     exit (EXIT_FAILURE);
6504   }
6505   if (close (fd) == -1) {
6506     perror (filename);
6507     unlink (filename);
6508     exit (EXIT_FAILURE);
6509   }
6510   if (guestfs_add_drive (g, filename) == -1) {
6511     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6512     exit (EXIT_FAILURE);
6513   }
6514
6515   filename = \"test3.img\";
6516   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6517   if (fd == -1) {
6518     perror (filename);
6519     exit (EXIT_FAILURE);
6520   }
6521   if (lseek (fd, %d, SEEK_SET) == -1) {
6522     perror (\"lseek\");
6523     close (fd);
6524     unlink (filename);
6525     exit (EXIT_FAILURE);
6526   }
6527   if (write (fd, &c, 1) == -1) {
6528     perror (\"write\");
6529     close (fd);
6530     unlink (filename);
6531     exit (EXIT_FAILURE);
6532   }
6533   if (close (fd) == -1) {
6534     perror (filename);
6535     unlink (filename);
6536     exit (EXIT_FAILURE);
6537   }
6538   if (guestfs_add_drive (g, filename) == -1) {
6539     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6540     exit (EXIT_FAILURE);
6541   }
6542
6543   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6544     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6545     exit (EXIT_FAILURE);
6546   }
6547
6548   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6549   alarm (600);
6550
6551   if (guestfs_launch (g) == -1) {
6552     printf (\"guestfs_launch FAILED\\n\");
6553     exit (EXIT_FAILURE);
6554   }
6555
6556   /* Cancel previous alarm. */
6557   alarm (0);
6558
6559   nr_tests = %d;
6560
6561 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6562
6563   iteri (
6564     fun i test_name ->
6565       pr "  test_num++;\n";
6566       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6567       pr "  if (%s () == -1) {\n" test_name;
6568       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6569       pr "    n_failed++;\n";
6570       pr "  }\n";
6571   ) test_names;
6572   pr "\n";
6573
6574   pr "  guestfs_close (g);\n";
6575   pr "  unlink (\"test1.img\");\n";
6576   pr "  unlink (\"test2.img\");\n";
6577   pr "  unlink (\"test3.img\");\n";
6578   pr "\n";
6579
6580   pr "  if (n_failed > 0) {\n";
6581   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6582   pr "    exit (EXIT_FAILURE);\n";
6583   pr "  }\n";
6584   pr "\n";
6585
6586   pr "  exit (EXIT_SUCCESS);\n";
6587   pr "}\n"
6588
6589 and generate_one_test name flags i (init, prereq, test) =
6590   let test_name = sprintf "test_%s_%d" name i in
6591
6592   pr "\
6593 static int %s_skip (void)
6594 {
6595   const char *str;
6596
6597   str = getenv (\"TEST_ONLY\");
6598   if (str)
6599     return strstr (str, \"%s\") == NULL;
6600   str = getenv (\"SKIP_%s\");
6601   if (str && STREQ (str, \"1\")) return 1;
6602   str = getenv (\"SKIP_TEST_%s\");
6603   if (str && STREQ (str, \"1\")) return 1;
6604   return 0;
6605 }
6606
6607 " test_name name (String.uppercase test_name) (String.uppercase name);
6608
6609   (match prereq with
6610    | Disabled | Always -> ()
6611    | If code | Unless code ->
6612        pr "static int %s_prereq (void)\n" test_name;
6613        pr "{\n";
6614        pr "  %s\n" code;
6615        pr "}\n";
6616        pr "\n";
6617   );
6618
6619   pr "\
6620 static int %s (void)
6621 {
6622   if (%s_skip ()) {
6623     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6624     return 0;
6625   }
6626
6627 " test_name test_name test_name;
6628
6629   (* Optional functions should only be tested if the relevant
6630    * support is available in the daemon.
6631    *)
6632   List.iter (
6633     function
6634     | Optional group ->
6635         pr "  {\n";
6636         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6637         pr "    int r;\n";
6638         pr "    suppress_error = 1;\n";
6639         pr "    r = guestfs_available (g, (char **) groups);\n";
6640         pr "    suppress_error = 0;\n";
6641         pr "    if (r == -1) {\n";
6642         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6643         pr "      return 0;\n";
6644         pr "    }\n";
6645         pr "  }\n";
6646     | _ -> ()
6647   ) flags;
6648
6649   (match prereq with
6650    | Disabled ->
6651        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6652    | If _ ->
6653        pr "  if (! %s_prereq ()) {\n" test_name;
6654        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6655        pr "    return 0;\n";
6656        pr "  }\n";
6657        pr "\n";
6658        generate_one_test_body name i test_name init test;
6659    | Unless _ ->
6660        pr "  if (%s_prereq ()) {\n" test_name;
6661        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6662        pr "    return 0;\n";
6663        pr "  }\n";
6664        pr "\n";
6665        generate_one_test_body name i test_name init test;
6666    | Always ->
6667        generate_one_test_body name i test_name init test
6668   );
6669
6670   pr "  return 0;\n";
6671   pr "}\n";
6672   pr "\n";
6673   test_name
6674
6675 and generate_one_test_body name i test_name init test =
6676   (match init with
6677    | InitNone (* XXX at some point, InitNone and InitEmpty became
6678                * folded together as the same thing.  Really we should
6679                * make InitNone do nothing at all, but the tests may
6680                * need to be checked to make sure this is OK.
6681                *)
6682    | InitEmpty ->
6683        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6684        List.iter (generate_test_command_call test_name)
6685          [["blockdev_setrw"; "/dev/sda"];
6686           ["umount_all"];
6687           ["lvm_remove_all"]]
6688    | InitPartition ->
6689        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6690        List.iter (generate_test_command_call test_name)
6691          [["blockdev_setrw"; "/dev/sda"];
6692           ["umount_all"];
6693           ["lvm_remove_all"];
6694           ["part_disk"; "/dev/sda"; "mbr"]]
6695    | InitBasicFS ->
6696        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6697        List.iter (generate_test_command_call test_name)
6698          [["blockdev_setrw"; "/dev/sda"];
6699           ["umount_all"];
6700           ["lvm_remove_all"];
6701           ["part_disk"; "/dev/sda"; "mbr"];
6702           ["mkfs"; "ext2"; "/dev/sda1"];
6703           ["mount_options"; ""; "/dev/sda1"; "/"]]
6704    | InitBasicFSonLVM ->
6705        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6706          test_name;
6707        List.iter (generate_test_command_call test_name)
6708          [["blockdev_setrw"; "/dev/sda"];
6709           ["umount_all"];
6710           ["lvm_remove_all"];
6711           ["part_disk"; "/dev/sda"; "mbr"];
6712           ["pvcreate"; "/dev/sda1"];
6713           ["vgcreate"; "VG"; "/dev/sda1"];
6714           ["lvcreate"; "LV"; "VG"; "8"];
6715           ["mkfs"; "ext2"; "/dev/VG/LV"];
6716           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6717    | InitISOFS ->
6718        pr "  /* InitISOFS for %s */\n" test_name;
6719        List.iter (generate_test_command_call test_name)
6720          [["blockdev_setrw"; "/dev/sda"];
6721           ["umount_all"];
6722           ["lvm_remove_all"];
6723           ["mount_ro"; "/dev/sdd"; "/"]]
6724   );
6725
6726   let get_seq_last = function
6727     | [] ->
6728         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6729           test_name
6730     | seq ->
6731         let seq = List.rev seq in
6732         List.rev (List.tl seq), List.hd seq
6733   in
6734
6735   match test with
6736   | TestRun seq ->
6737       pr "  /* TestRun for %s (%d) */\n" name i;
6738       List.iter (generate_test_command_call test_name) seq
6739   | TestOutput (seq, expected) ->
6740       pr "  /* TestOutput for %s (%d) */\n" name i;
6741       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6742       let seq, last = get_seq_last seq in
6743       let test () =
6744         pr "    if (STRNEQ (r, expected)) {\n";
6745         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6746         pr "      return -1;\n";
6747         pr "    }\n"
6748       in
6749       List.iter (generate_test_command_call test_name) seq;
6750       generate_test_command_call ~test test_name last
6751   | TestOutputList (seq, expected) ->
6752       pr "  /* TestOutputList for %s (%d) */\n" name i;
6753       let seq, last = get_seq_last seq in
6754       let test () =
6755         iteri (
6756           fun i str ->
6757             pr "    if (!r[%d]) {\n" i;
6758             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6759             pr "      print_strings (r);\n";
6760             pr "      return -1;\n";
6761             pr "    }\n";
6762             pr "    {\n";
6763             pr "      const char *expected = \"%s\";\n" (c_quote str);
6764             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6765             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6766             pr "        return -1;\n";
6767             pr "      }\n";
6768             pr "    }\n"
6769         ) expected;
6770         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6771         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6772           test_name;
6773         pr "      print_strings (r);\n";
6774         pr "      return -1;\n";
6775         pr "    }\n"
6776       in
6777       List.iter (generate_test_command_call test_name) seq;
6778       generate_test_command_call ~test test_name last
6779   | TestOutputListOfDevices (seq, expected) ->
6780       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6781       let seq, last = get_seq_last seq in
6782       let test () =
6783         iteri (
6784           fun i str ->
6785             pr "    if (!r[%d]) {\n" i;
6786             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6787             pr "      print_strings (r);\n";
6788             pr "      return -1;\n";
6789             pr "    }\n";
6790             pr "    {\n";
6791             pr "      const char *expected = \"%s\";\n" (c_quote str);
6792             pr "      r[%d][5] = 's';\n" i;
6793             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6794             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6795             pr "        return -1;\n";
6796             pr "      }\n";
6797             pr "    }\n"
6798         ) expected;
6799         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6800         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6801           test_name;
6802         pr "      print_strings (r);\n";
6803         pr "      return -1;\n";
6804         pr "    }\n"
6805       in
6806       List.iter (generate_test_command_call test_name) seq;
6807       generate_test_command_call ~test test_name last
6808   | TestOutputInt (seq, expected) ->
6809       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6810       let seq, last = get_seq_last seq in
6811       let test () =
6812         pr "    if (r != %d) {\n" expected;
6813         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6814           test_name expected;
6815         pr "               (int) r);\n";
6816         pr "      return -1;\n";
6817         pr "    }\n"
6818       in
6819       List.iter (generate_test_command_call test_name) seq;
6820       generate_test_command_call ~test test_name last
6821   | TestOutputIntOp (seq, op, expected) ->
6822       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6823       let seq, last = get_seq_last seq in
6824       let test () =
6825         pr "    if (! (r %s %d)) {\n" op expected;
6826         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6827           test_name op expected;
6828         pr "               (int) r);\n";
6829         pr "      return -1;\n";
6830         pr "    }\n"
6831       in
6832       List.iter (generate_test_command_call test_name) seq;
6833       generate_test_command_call ~test test_name last
6834   | TestOutputTrue seq ->
6835       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6836       let seq, last = get_seq_last seq in
6837       let test () =
6838         pr "    if (!r) {\n";
6839         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6840           test_name;
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   | TestOutputFalse seq ->
6847       pr "  /* TestOutputFalse 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 false, got true\\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   | TestOutputLength (seq, expected) ->
6859       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6860       let seq, last = get_seq_last seq in
6861       let test () =
6862         pr "    int j;\n";
6863         pr "    for (j = 0; j < %d; ++j)\n" expected;
6864         pr "      if (r[j] == NULL) {\n";
6865         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6866           test_name;
6867         pr "        print_strings (r);\n";
6868         pr "        return -1;\n";
6869         pr "      }\n";
6870         pr "    if (r[j] != NULL) {\n";
6871         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6872           test_name;
6873         pr "      print_strings (r);\n";
6874         pr "      return -1;\n";
6875         pr "    }\n"
6876       in
6877       List.iter (generate_test_command_call test_name) seq;
6878       generate_test_command_call ~test test_name last
6879   | TestOutputBuffer (seq, expected) ->
6880       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6881       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6882       let seq, last = get_seq_last seq in
6883       let len = String.length expected in
6884       let test () =
6885         pr "    if (size != %d) {\n" len;
6886         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6887         pr "      return -1;\n";
6888         pr "    }\n";
6889         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6890         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6891         pr "      return -1;\n";
6892         pr "    }\n"
6893       in
6894       List.iter (generate_test_command_call test_name) seq;
6895       generate_test_command_call ~test test_name last
6896   | TestOutputStruct (seq, checks) ->
6897       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6898       let seq, last = get_seq_last seq in
6899       let test () =
6900         List.iter (
6901           function
6902           | CompareWithInt (field, expected) ->
6903               pr "    if (r->%s != %d) {\n" field expected;
6904               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6905                 test_name field expected;
6906               pr "               (int) r->%s);\n" field;
6907               pr "      return -1;\n";
6908               pr "    }\n"
6909           | CompareWithIntOp (field, op, expected) ->
6910               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6911               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6912                 test_name field op expected;
6913               pr "               (int) r->%s);\n" field;
6914               pr "      return -1;\n";
6915               pr "    }\n"
6916           | CompareWithString (field, expected) ->
6917               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6918               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6919                 test_name field expected;
6920               pr "               r->%s);\n" field;
6921               pr "      return -1;\n";
6922               pr "    }\n"
6923           | CompareFieldsIntEq (field1, field2) ->
6924               pr "    if (r->%s != r->%s) {\n" field1 field2;
6925               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6926                 test_name field1 field2;
6927               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6928               pr "      return -1;\n";
6929               pr "    }\n"
6930           | CompareFieldsStrEq (field1, field2) ->
6931               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6932               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6933                 test_name field1 field2;
6934               pr "               r->%s, r->%s);\n" field1 field2;
6935               pr "      return -1;\n";
6936               pr "    }\n"
6937         ) checks
6938       in
6939       List.iter (generate_test_command_call test_name) seq;
6940       generate_test_command_call ~test test_name last
6941   | TestLastFail seq ->
6942       pr "  /* TestLastFail for %s (%d) */\n" name i;
6943       let seq, last = get_seq_last seq in
6944       List.iter (generate_test_command_call test_name) seq;
6945       generate_test_command_call test_name ~expect_error:true last
6946
6947 (* Generate the code to run a command, leaving the result in 'r'.
6948  * If you expect to get an error then you should set expect_error:true.
6949  *)
6950 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6951   match cmd with
6952   | [] -> assert false
6953   | name :: args ->
6954       (* Look up the command to find out what args/ret it has. *)
6955       let style =
6956         try
6957           let _, style, _, _, _, _, _ =
6958             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6959           style
6960         with Not_found ->
6961           failwithf "%s: in test, command %s was not found" test_name name in
6962
6963       if List.length (snd style) <> List.length args then
6964         failwithf "%s: in test, wrong number of args given to %s"
6965           test_name name;
6966
6967       pr "  {\n";
6968
6969       List.iter (
6970         function
6971         | OptString n, "NULL" -> ()
6972         | Pathname n, arg
6973         | Device n, arg
6974         | Dev_or_Path n, arg
6975         | String n, arg
6976         | OptString n, arg ->
6977             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6978         | Int _, _
6979         | Int64 _, _
6980         | Bool _, _
6981         | FileIn _, _ | FileOut _, _ -> ()
6982         | StringList n, "" | DeviceList n, "" ->
6983             pr "    const char *const %s[1] = { NULL };\n" n
6984         | StringList n, arg | DeviceList n, arg ->
6985             let strs = string_split " " arg in
6986             iteri (
6987               fun i str ->
6988                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6989             ) strs;
6990             pr "    const char *const %s[] = {\n" n;
6991             iteri (
6992               fun i _ -> pr "      %s_%d,\n" n i
6993             ) strs;
6994             pr "      NULL\n";
6995             pr "    };\n";
6996       ) (List.combine (snd style) args);
6997
6998       let error_code =
6999         match fst style with
7000         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7001         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7002         | RConstString _ | RConstOptString _ ->
7003             pr "    const char *r;\n"; "NULL"
7004         | RString _ -> pr "    char *r;\n"; "NULL"
7005         | RStringList _ | RHashtable _ ->
7006             pr "    char **r;\n";
7007             pr "    int i;\n";
7008             "NULL"
7009         | RStruct (_, typ) ->
7010             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7011         | RStructList (_, typ) ->
7012             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7013         | RBufferOut _ ->
7014             pr "    char *r;\n";
7015             pr "    size_t size;\n";
7016             "NULL" in
7017
7018       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7019       pr "    r = guestfs_%s (g" name;
7020
7021       (* Generate the parameters. *)
7022       List.iter (
7023         function
7024         | OptString _, "NULL" -> pr ", NULL"
7025         | Pathname n, _
7026         | Device n, _ | Dev_or_Path n, _
7027         | String n, _
7028         | OptString n, _ ->
7029             pr ", %s" n
7030         | FileIn _, arg | FileOut _, arg ->
7031             pr ", \"%s\"" (c_quote arg)
7032         | StringList n, _ | DeviceList n, _ ->
7033             pr ", (char **) %s" n
7034         | Int _, arg ->
7035             let i =
7036               try int_of_string arg
7037               with Failure "int_of_string" ->
7038                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7039             pr ", %d" i
7040         | Int64 _, arg ->
7041             let i =
7042               try Int64.of_string arg
7043               with Failure "int_of_string" ->
7044                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7045             pr ", %Ld" i
7046         | Bool _, arg ->
7047             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7048       ) (List.combine (snd style) args);
7049
7050       (match fst style with
7051        | RBufferOut _ -> pr ", &size"
7052        | _ -> ()
7053       );
7054
7055       pr ");\n";
7056
7057       if not expect_error then
7058         pr "    if (r == %s)\n" error_code
7059       else
7060         pr "    if (r != %s)\n" error_code;
7061       pr "      return -1;\n";
7062
7063       (* Insert the test code. *)
7064       (match test with
7065        | None -> ()
7066        | Some f -> f ()
7067       );
7068
7069       (match fst style with
7070        | RErr | RInt _ | RInt64 _ | RBool _
7071        | RConstString _ | RConstOptString _ -> ()
7072        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7073        | RStringList _ | RHashtable _ ->
7074            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7075            pr "      free (r[i]);\n";
7076            pr "    free (r);\n"
7077        | RStruct (_, typ) ->
7078            pr "    guestfs_free_%s (r);\n" typ
7079        | RStructList (_, typ) ->
7080            pr "    guestfs_free_%s_list (r);\n" typ
7081       );
7082
7083       pr "  }\n"
7084
7085 and c_quote str =
7086   let str = replace_str str "\r" "\\r" in
7087   let str = replace_str str "\n" "\\n" in
7088   let str = replace_str str "\t" "\\t" in
7089   let str = replace_str str "\000" "\\0" in
7090   str
7091
7092 (* Generate a lot of different functions for guestfish. *)
7093 and generate_fish_cmds () =
7094   generate_header CStyle GPLv2plus;
7095
7096   let all_functions =
7097     List.filter (
7098       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7099     ) all_functions in
7100   let all_functions_sorted =
7101     List.filter (
7102       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7103     ) all_functions_sorted in
7104
7105   pr "#include <config.h>\n";
7106   pr "\n";
7107   pr "#include <stdio.h>\n";
7108   pr "#include <stdlib.h>\n";
7109   pr "#include <string.h>\n";
7110   pr "#include <inttypes.h>\n";
7111   pr "\n";
7112   pr "#include <guestfs.h>\n";
7113   pr "#include \"c-ctype.h\"\n";
7114   pr "#include \"full-write.h\"\n";
7115   pr "#include \"xstrtol.h\"\n";
7116   pr "#include \"fish.h\"\n";
7117   pr "\n";
7118
7119   (* list_commands function, which implements guestfish -h *)
7120   pr "void list_commands (void)\n";
7121   pr "{\n";
7122   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7123   pr "  list_builtin_commands ();\n";
7124   List.iter (
7125     fun (name, _, _, flags, _, shortdesc, _) ->
7126       let name = replace_char name '_' '-' in
7127       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7128         name shortdesc
7129   ) all_functions_sorted;
7130   pr "  printf (\"    %%s\\n\",";
7131   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7132   pr "}\n";
7133   pr "\n";
7134
7135   (* display_command function, which implements guestfish -h cmd *)
7136   pr "void display_command (const char *cmd)\n";
7137   pr "{\n";
7138   List.iter (
7139     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7140       let name2 = replace_char name '_' '-' in
7141       let alias =
7142         try find_map (function FishAlias n -> Some n | _ -> None) flags
7143         with Not_found -> name in
7144       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7145       let synopsis =
7146         match snd style with
7147         | [] -> name2
7148         | args ->
7149             sprintf "%s %s"
7150               name2 (String.concat " " (List.map name_of_argt args)) in
7151
7152       let warnings =
7153         if List.mem ProtocolLimitWarning flags then
7154           ("\n\n" ^ protocol_limit_warning)
7155         else "" in
7156
7157       (* For DangerWillRobinson commands, we should probably have
7158        * guestfish prompt before allowing you to use them (especially
7159        * in interactive mode). XXX
7160        *)
7161       let warnings =
7162         warnings ^
7163           if List.mem DangerWillRobinson flags then
7164             ("\n\n" ^ danger_will_robinson)
7165           else "" in
7166
7167       let warnings =
7168         warnings ^
7169           match deprecation_notice flags with
7170           | None -> ""
7171           | Some txt -> "\n\n" ^ txt in
7172
7173       let describe_alias =
7174         if name <> alias then
7175           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7176         else "" in
7177
7178       pr "  if (";
7179       pr "STRCASEEQ (cmd, \"%s\")" name;
7180       if name <> name2 then
7181         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7182       if name <> alias then
7183         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7184       pr ")\n";
7185       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7186         name2 shortdesc
7187         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7188          "=head1 DESCRIPTION\n\n" ^
7189          longdesc ^ warnings ^ describe_alias);
7190       pr "  else\n"
7191   ) all_functions;
7192   pr "    display_builtin_command (cmd);\n";
7193   pr "}\n";
7194   pr "\n";
7195
7196   let emit_print_list_function typ =
7197     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7198       typ typ typ;
7199     pr "{\n";
7200     pr "  unsigned int i;\n";
7201     pr "\n";
7202     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7203     pr "    printf (\"[%%d] = {\\n\", i);\n";
7204     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7205     pr "    printf (\"}\\n\");\n";
7206     pr "  }\n";
7207     pr "}\n";
7208     pr "\n";
7209   in
7210
7211   (* print_* functions *)
7212   List.iter (
7213     fun (typ, cols) ->
7214       let needs_i =
7215         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7216
7217       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7218       pr "{\n";
7219       if needs_i then (
7220         pr "  unsigned int i;\n";
7221         pr "\n"
7222       );
7223       List.iter (
7224         function
7225         | name, FString ->
7226             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7227         | name, FUUID ->
7228             pr "  printf (\"%%s%s: \", indent);\n" name;
7229             pr "  for (i = 0; i < 32; ++i)\n";
7230             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7231             pr "  printf (\"\\n\");\n"
7232         | name, FBuffer ->
7233             pr "  printf (\"%%s%s: \", indent);\n" name;
7234             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7235             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7236             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7237             pr "    else\n";
7238             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7239             pr "  printf (\"\\n\");\n"
7240         | name, (FUInt64|FBytes) ->
7241             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7242               name typ name
7243         | name, FInt64 ->
7244             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7245               name typ name
7246         | name, FUInt32 ->
7247             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7248               name typ name
7249         | name, FInt32 ->
7250             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7251               name typ name
7252         | name, FChar ->
7253             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7254               name typ name
7255         | name, FOptPercent ->
7256             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7257               typ name name typ name;
7258             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7259       ) cols;
7260       pr "}\n";
7261       pr "\n";
7262   ) structs;
7263
7264   (* Emit a print_TYPE_list function definition only if that function is used. *)
7265   List.iter (
7266     function
7267     | typ, (RStructListOnly | RStructAndList) ->
7268         (* generate the function for typ *)
7269         emit_print_list_function typ
7270     | typ, _ -> () (* empty *)
7271   ) (rstructs_used_by all_functions);
7272
7273   (* Emit a print_TYPE function definition only if that function is used. *)
7274   List.iter (
7275     function
7276     | typ, (RStructOnly | RStructAndList) ->
7277         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7278         pr "{\n";
7279         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7280         pr "}\n";
7281         pr "\n";
7282     | typ, _ -> () (* empty *)
7283   ) (rstructs_used_by all_functions);
7284
7285   (* run_<action> actions *)
7286   List.iter (
7287     fun (name, style, _, flags, _, _, _) ->
7288       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7289       pr "{\n";
7290       (match fst style with
7291        | RErr
7292        | RInt _
7293        | RBool _ -> pr "  int r;\n"
7294        | RInt64 _ -> pr "  int64_t r;\n"
7295        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7296        | RString _ -> pr "  char *r;\n"
7297        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7298        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7299        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7300        | RBufferOut _ ->
7301            pr "  char *r;\n";
7302            pr "  size_t size;\n";
7303       );
7304       List.iter (
7305         function
7306         | Device n
7307         | String n
7308         | OptString n
7309         | FileIn n
7310         | FileOut n -> pr "  const char *%s;\n" n
7311         | Pathname n
7312         | Dev_or_Path n -> pr "  char *%s;\n" n
7313         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7314         | Bool n -> pr "  int %s;\n" n
7315         | Int n -> pr "  int %s;\n" n
7316         | Int64 n -> pr "  int64_t %s;\n" n
7317       ) (snd style);
7318
7319       (* Check and convert parameters. *)
7320       let argc_expected = List.length (snd style) in
7321       pr "  if (argc != %d) {\n" argc_expected;
7322       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7323         argc_expected;
7324       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7325       pr "    return -1;\n";
7326       pr "  }\n";
7327
7328       let parse_integer fn fntyp rtyp range name i =
7329         pr "  {\n";
7330         pr "    strtol_error xerr;\n";
7331         pr "    %s r;\n" fntyp;
7332         pr "\n";
7333         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7334         pr "    if (xerr != LONGINT_OK) {\n";
7335         pr "      fprintf (stderr,\n";
7336         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7337         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7338         pr "      return -1;\n";
7339         pr "    }\n";
7340         (match range with
7341          | None -> ()
7342          | Some (min, max, comment) ->
7343              pr "    /* %s */\n" comment;
7344              pr "    if (r < %s || r > %s) {\n" min max;
7345              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7346                name;
7347              pr "      return -1;\n";
7348              pr "    }\n";
7349              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7350         );
7351         pr "    %s = r;\n" name;
7352         pr "  }\n";
7353       in
7354
7355       iteri (
7356         fun i ->
7357           function
7358           | Device name
7359           | String name ->
7360               pr "  %s = argv[%d];\n" name i
7361           | Pathname name
7362           | Dev_or_Path name ->
7363               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7364               pr "  if (%s == NULL) return -1;\n" name
7365           | OptString name ->
7366               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7367                 name i i
7368           | FileIn name ->
7369               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7370                 name i i
7371           | FileOut name ->
7372               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7373                 name i i
7374           | StringList name | DeviceList name ->
7375               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7376               pr "  if (%s == NULL) return -1;\n" name;
7377           | Bool name ->
7378               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7379           | Int name ->
7380               let range =
7381                 let min = "(-(2LL<<30))"
7382                 and max = "((2LL<<30)-1)"
7383                 and comment =
7384                   "The Int type in the generator is a signed 31 bit int." in
7385                 Some (min, max, comment) in
7386               parse_integer "xstrtoll" "long long" "int" range name i
7387           | Int64 name ->
7388               parse_integer "xstrtoll" "long long" "int64_t" None name i
7389       ) (snd style);
7390
7391       (* Call C API function. *)
7392       let fn =
7393         try find_map (function FishAction n -> Some n | _ -> None) flags
7394         with Not_found -> sprintf "guestfs_%s" name in
7395       pr "  r = %s " fn;
7396       generate_c_call_args ~handle:"g" style;
7397       pr ";\n";
7398
7399       List.iter (
7400         function
7401         | Device name | String name
7402         | OptString name | FileIn name | FileOut name | Bool name
7403         | Int name | Int64 name -> ()
7404         | Pathname name | Dev_or_Path name ->
7405             pr "  free (%s);\n" name
7406         | StringList name | DeviceList name ->
7407             pr "  free_strings (%s);\n" name
7408       ) (snd style);
7409
7410       (* Check return value for errors and display command results. *)
7411       (match fst style with
7412        | RErr -> pr "  return r;\n"
7413        | RInt _ ->
7414            pr "  if (r == -1) return -1;\n";
7415            pr "  printf (\"%%d\\n\", r);\n";
7416            pr "  return 0;\n"
7417        | RInt64 _ ->
7418            pr "  if (r == -1) return -1;\n";
7419            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7420            pr "  return 0;\n"
7421        | RBool _ ->
7422            pr "  if (r == -1) return -1;\n";
7423            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7424            pr "  return 0;\n"
7425        | RConstString _ ->
7426            pr "  if (r == NULL) return -1;\n";
7427            pr "  printf (\"%%s\\n\", r);\n";
7428            pr "  return 0;\n"
7429        | RConstOptString _ ->
7430            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7431            pr "  return 0;\n"
7432        | RString _ ->
7433            pr "  if (r == NULL) return -1;\n";
7434            pr "  printf (\"%%s\\n\", r);\n";
7435            pr "  free (r);\n";
7436            pr "  return 0;\n"
7437        | RStringList _ ->
7438            pr "  if (r == NULL) return -1;\n";
7439            pr "  print_strings (r);\n";
7440            pr "  free_strings (r);\n";
7441            pr "  return 0;\n"
7442        | RStruct (_, typ) ->
7443            pr "  if (r == NULL) return -1;\n";
7444            pr "  print_%s (r);\n" typ;
7445            pr "  guestfs_free_%s (r);\n" typ;
7446            pr "  return 0;\n"
7447        | RStructList (_, typ) ->
7448            pr "  if (r == NULL) return -1;\n";
7449            pr "  print_%s_list (r);\n" typ;
7450            pr "  guestfs_free_%s_list (r);\n" typ;
7451            pr "  return 0;\n"
7452        | RHashtable _ ->
7453            pr "  if (r == NULL) return -1;\n";
7454            pr "  print_table (r);\n";
7455            pr "  free_strings (r);\n";
7456            pr "  return 0;\n"
7457        | RBufferOut _ ->
7458            pr "  if (r == NULL) return -1;\n";
7459            pr "  if (full_write (1, r, size) != size) {\n";
7460            pr "    perror (\"write\");\n";
7461            pr "    free (r);\n";
7462            pr "    return -1;\n";
7463            pr "  }\n";
7464            pr "  free (r);\n";
7465            pr "  return 0;\n"
7466       );
7467       pr "}\n";
7468       pr "\n"
7469   ) all_functions;
7470
7471   (* run_action function *)
7472   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7473   pr "{\n";
7474   List.iter (
7475     fun (name, _, _, flags, _, _, _) ->
7476       let name2 = replace_char name '_' '-' in
7477       let alias =
7478         try find_map (function FishAlias n -> Some n | _ -> None) flags
7479         with Not_found -> name in
7480       pr "  if (";
7481       pr "STRCASEEQ (cmd, \"%s\")" name;
7482       if name <> name2 then
7483         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7484       if name <> alias then
7485         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7486       pr ")\n";
7487       pr "    return run_%s (cmd, argc, argv);\n" name;
7488       pr "  else\n";
7489   ) all_functions;
7490   pr "    {\n";
7491   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7492   pr "      if (command_num == 1)\n";
7493   pr "        extended_help_message ();\n";
7494   pr "      return -1;\n";
7495   pr "    }\n";
7496   pr "  return 0;\n";
7497   pr "}\n";
7498   pr "\n"
7499
7500 (* Readline completion for guestfish. *)
7501 and generate_fish_completion () =
7502   generate_header CStyle GPLv2plus;
7503
7504   let all_functions =
7505     List.filter (
7506       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7507     ) all_functions in
7508
7509   pr "\
7510 #include <config.h>
7511
7512 #include <stdio.h>
7513 #include <stdlib.h>
7514 #include <string.h>
7515
7516 #ifdef HAVE_LIBREADLINE
7517 #include <readline/readline.h>
7518 #endif
7519
7520 #include \"fish.h\"
7521
7522 #ifdef HAVE_LIBREADLINE
7523
7524 static const char *const commands[] = {
7525   BUILTIN_COMMANDS_FOR_COMPLETION,
7526 ";
7527
7528   (* Get the commands, including the aliases.  They don't need to be
7529    * sorted - the generator() function just does a dumb linear search.
7530    *)
7531   let commands =
7532     List.map (
7533       fun (name, _, _, flags, _, _, _) ->
7534         let name2 = replace_char name '_' '-' in
7535         let alias =
7536           try find_map (function FishAlias n -> Some n | _ -> None) flags
7537           with Not_found -> name in
7538
7539         if name <> alias then [name2; alias] else [name2]
7540     ) all_functions in
7541   let commands = List.flatten commands in
7542
7543   List.iter (pr "  \"%s\",\n") commands;
7544
7545   pr "  NULL
7546 };
7547
7548 static char *
7549 generator (const char *text, int state)
7550 {
7551   static int index, len;
7552   const char *name;
7553
7554   if (!state) {
7555     index = 0;
7556     len = strlen (text);
7557   }
7558
7559   rl_attempted_completion_over = 1;
7560
7561   while ((name = commands[index]) != NULL) {
7562     index++;
7563     if (STRCASEEQLEN (name, text, len))
7564       return strdup (name);
7565   }
7566
7567   return NULL;
7568 }
7569
7570 #endif /* HAVE_LIBREADLINE */
7571
7572 #ifdef HAVE_RL_COMPLETION_MATCHES
7573 #define RL_COMPLETION_MATCHES rl_completion_matches
7574 #else
7575 #ifdef HAVE_COMPLETION_MATCHES
7576 #define RL_COMPLETION_MATCHES completion_matches
7577 #endif
7578 #endif /* else just fail if we don't have either symbol */
7579
7580 char **
7581 do_completion (const char *text, int start, int end)
7582 {
7583   char **matches = NULL;
7584
7585 #ifdef HAVE_LIBREADLINE
7586   rl_completion_append_character = ' ';
7587
7588   if (start == 0)
7589     matches = RL_COMPLETION_MATCHES (text, generator);
7590   else if (complete_dest_paths)
7591     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7592 #endif
7593
7594   return matches;
7595 }
7596 ";
7597
7598 (* Generate the POD documentation for guestfish. *)
7599 and generate_fish_actions_pod () =
7600   let all_functions_sorted =
7601     List.filter (
7602       fun (_, _, _, flags, _, _, _) ->
7603         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7604     ) all_functions_sorted in
7605
7606   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7607
7608   List.iter (
7609     fun (name, style, _, flags, _, _, longdesc) ->
7610       let longdesc =
7611         Str.global_substitute rex (
7612           fun s ->
7613             let sub =
7614               try Str.matched_group 1 s
7615               with Not_found ->
7616                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7617             "C<" ^ replace_char sub '_' '-' ^ ">"
7618         ) longdesc in
7619       let name = replace_char name '_' '-' in
7620       let alias =
7621         try find_map (function FishAlias n -> Some n | _ -> None) flags
7622         with Not_found -> name in
7623
7624       pr "=head2 %s" name;
7625       if name <> alias then
7626         pr " | %s" alias;
7627       pr "\n";
7628       pr "\n";
7629       pr " %s" name;
7630       List.iter (
7631         function
7632         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7633         | OptString n -> pr " %s" n
7634         | StringList n | DeviceList n -> pr " '%s ...'" n
7635         | Bool _ -> pr " true|false"
7636         | Int n -> pr " %s" n
7637         | Int64 n -> pr " %s" n
7638         | FileIn n | FileOut n -> pr " (%s|-)" n
7639       ) (snd style);
7640       pr "\n";
7641       pr "\n";
7642       pr "%s\n\n" longdesc;
7643
7644       if List.exists (function FileIn _ | FileOut _ -> true
7645                       | _ -> false) (snd style) then
7646         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7647
7648       if List.mem ProtocolLimitWarning flags then
7649         pr "%s\n\n" protocol_limit_warning;
7650
7651       if List.mem DangerWillRobinson flags then
7652         pr "%s\n\n" danger_will_robinson;
7653
7654       match deprecation_notice flags with
7655       | None -> ()
7656       | Some txt -> pr "%s\n\n" txt
7657   ) all_functions_sorted
7658
7659 (* Generate a C function prototype. *)
7660 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7661     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7662     ?(prefix = "")
7663     ?handle name style =
7664   if extern then pr "extern ";
7665   if static then pr "static ";
7666   (match fst style with
7667    | RErr -> pr "int "
7668    | RInt _ -> pr "int "
7669    | RInt64 _ -> pr "int64_t "
7670    | RBool _ -> pr "int "
7671    | RConstString _ | RConstOptString _ -> pr "const char *"
7672    | RString _ | RBufferOut _ -> pr "char *"
7673    | RStringList _ | RHashtable _ -> pr "char **"
7674    | RStruct (_, typ) ->
7675        if not in_daemon then pr "struct guestfs_%s *" typ
7676        else pr "guestfs_int_%s *" typ
7677    | RStructList (_, typ) ->
7678        if not in_daemon then pr "struct guestfs_%s_list *" typ
7679        else pr "guestfs_int_%s_list *" typ
7680   );
7681   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7682   pr "%s%s (" prefix name;
7683   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7684     pr "void"
7685   else (
7686     let comma = ref false in
7687     (match handle with
7688      | None -> ()
7689      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7690     );
7691     let next () =
7692       if !comma then (
7693         if single_line then pr ", " else pr ",\n\t\t"
7694       );
7695       comma := true
7696     in
7697     List.iter (
7698       function
7699       | Pathname n
7700       | Device n | Dev_or_Path n
7701       | String n
7702       | OptString n ->
7703           next ();
7704           pr "const char *%s" n
7705       | StringList n | DeviceList n ->
7706           next ();
7707           pr "char *const *%s" n
7708       | Bool n -> next (); pr "int %s" n
7709       | Int n -> next (); pr "int %s" n
7710       | Int64 n -> next (); pr "int64_t %s" n
7711       | FileIn n
7712       | FileOut n ->
7713           if not in_daemon then (next (); pr "const char *%s" n)
7714     ) (snd style);
7715     if is_RBufferOut then (next (); pr "size_t *size_r");
7716   );
7717   pr ")";
7718   if semicolon then pr ";";
7719   if newline then pr "\n"
7720
7721 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7722 and generate_c_call_args ?handle ?(decl = false) style =
7723   pr "(";
7724   let comma = ref false in
7725   let next () =
7726     if !comma then pr ", ";
7727     comma := true
7728   in
7729   (match handle with
7730    | None -> ()
7731    | Some handle -> pr "%s" handle; comma := true
7732   );
7733   List.iter (
7734     fun arg ->
7735       next ();
7736       pr "%s" (name_of_argt arg)
7737   ) (snd style);
7738   (* For RBufferOut calls, add implicit &size parameter. *)
7739   if not decl then (
7740     match fst style with
7741     | RBufferOut _ ->
7742         next ();
7743         pr "&size"
7744     | _ -> ()
7745   );
7746   pr ")"
7747
7748 (* Generate the OCaml bindings interface. *)
7749 and generate_ocaml_mli () =
7750   generate_header OCamlStyle LGPLv2plus;
7751
7752   pr "\
7753 (** For API documentation you should refer to the C API
7754     in the guestfs(3) manual page.  The OCaml API uses almost
7755     exactly the same calls. *)
7756
7757 type t
7758 (** A [guestfs_h] handle. *)
7759
7760 exception Error of string
7761 (** This exception is raised when there is an error. *)
7762
7763 exception Handle_closed of string
7764 (** This exception is raised if you use a {!Guestfs.t} handle
7765     after calling {!close} on it.  The string is the name of
7766     the function. *)
7767
7768 val create : unit -> t
7769 (** Create a {!Guestfs.t} handle. *)
7770
7771 val close : t -> unit
7772 (** Close the {!Guestfs.t} handle and free up all resources used
7773     by it immediately.
7774
7775     Handles are closed by the garbage collector when they become
7776     unreferenced, but callers can call this in order to provide
7777     predictable cleanup. *)
7778
7779 ";
7780   generate_ocaml_structure_decls ();
7781
7782   (* The actions. *)
7783   List.iter (
7784     fun (name, style, _, _, _, shortdesc, _) ->
7785       generate_ocaml_prototype name style;
7786       pr "(** %s *)\n" shortdesc;
7787       pr "\n"
7788   ) all_functions_sorted
7789
7790 (* Generate the OCaml bindings implementation. *)
7791 and generate_ocaml_ml () =
7792   generate_header OCamlStyle LGPLv2plus;
7793
7794   pr "\
7795 type t
7796
7797 exception Error of string
7798 exception Handle_closed of string
7799
7800 external create : unit -> t = \"ocaml_guestfs_create\"
7801 external close : t -> unit = \"ocaml_guestfs_close\"
7802
7803 (* Give the exceptions names, so they can be raised from the C code. *)
7804 let () =
7805   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7806   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7807
7808 ";
7809
7810   generate_ocaml_structure_decls ();
7811
7812   (* The actions. *)
7813   List.iter (
7814     fun (name, style, _, _, _, shortdesc, _) ->
7815       generate_ocaml_prototype ~is_external:true name style;
7816   ) all_functions_sorted
7817
7818 (* Generate the OCaml bindings C implementation. *)
7819 and generate_ocaml_c () =
7820   generate_header CStyle LGPLv2plus;
7821
7822   pr "\
7823 #include <stdio.h>
7824 #include <stdlib.h>
7825 #include <string.h>
7826
7827 #include <caml/config.h>
7828 #include <caml/alloc.h>
7829 #include <caml/callback.h>
7830 #include <caml/fail.h>
7831 #include <caml/memory.h>
7832 #include <caml/mlvalues.h>
7833 #include <caml/signals.h>
7834
7835 #include <guestfs.h>
7836
7837 #include \"guestfs_c.h\"
7838
7839 /* Copy a hashtable of string pairs into an assoc-list.  We return
7840  * the list in reverse order, but hashtables aren't supposed to be
7841  * ordered anyway.
7842  */
7843 static CAMLprim value
7844 copy_table (char * const * argv)
7845 {
7846   CAMLparam0 ();
7847   CAMLlocal5 (rv, pairv, kv, vv, cons);
7848   int i;
7849
7850   rv = Val_int (0);
7851   for (i = 0; argv[i] != NULL; i += 2) {
7852     kv = caml_copy_string (argv[i]);
7853     vv = caml_copy_string (argv[i+1]);
7854     pairv = caml_alloc (2, 0);
7855     Store_field (pairv, 0, kv);
7856     Store_field (pairv, 1, vv);
7857     cons = caml_alloc (2, 0);
7858     Store_field (cons, 1, rv);
7859     rv = cons;
7860     Store_field (cons, 0, pairv);
7861   }
7862
7863   CAMLreturn (rv);
7864 }
7865
7866 ";
7867
7868   (* Struct copy functions. *)
7869
7870   let emit_ocaml_copy_list_function typ =
7871     pr "static CAMLprim value\n";
7872     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7873     pr "{\n";
7874     pr "  CAMLparam0 ();\n";
7875     pr "  CAMLlocal2 (rv, v);\n";
7876     pr "  unsigned int i;\n";
7877     pr "\n";
7878     pr "  if (%ss->len == 0)\n" typ;
7879     pr "    CAMLreturn (Atom (0));\n";
7880     pr "  else {\n";
7881     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7882     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7883     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7884     pr "      caml_modify (&Field (rv, i), v);\n";
7885     pr "    }\n";
7886     pr "    CAMLreturn (rv);\n";
7887     pr "  }\n";
7888     pr "}\n";
7889     pr "\n";
7890   in
7891
7892   List.iter (
7893     fun (typ, cols) ->
7894       let has_optpercent_col =
7895         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7896
7897       pr "static CAMLprim value\n";
7898       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7899       pr "{\n";
7900       pr "  CAMLparam0 ();\n";
7901       if has_optpercent_col then
7902         pr "  CAMLlocal3 (rv, v, v2);\n"
7903       else
7904         pr "  CAMLlocal2 (rv, v);\n";
7905       pr "\n";
7906       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7907       iteri (
7908         fun i col ->
7909           (match col with
7910            | name, FString ->
7911                pr "  v = caml_copy_string (%s->%s);\n" typ name
7912            | name, FBuffer ->
7913                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7914                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7915                  typ name typ name
7916            | name, FUUID ->
7917                pr "  v = caml_alloc_string (32);\n";
7918                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7919            | name, (FBytes|FInt64|FUInt64) ->
7920                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7921            | name, (FInt32|FUInt32) ->
7922                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7923            | name, FOptPercent ->
7924                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7925                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7926                pr "    v = caml_alloc (1, 0);\n";
7927                pr "    Store_field (v, 0, v2);\n";
7928                pr "  } else /* None */\n";
7929                pr "    v = Val_int (0);\n";
7930            | name, FChar ->
7931                pr "  v = Val_int (%s->%s);\n" typ name
7932           );
7933           pr "  Store_field (rv, %d, v);\n" i
7934       ) cols;
7935       pr "  CAMLreturn (rv);\n";
7936       pr "}\n";
7937       pr "\n";
7938   ) structs;
7939
7940   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7941   List.iter (
7942     function
7943     | typ, (RStructListOnly | RStructAndList) ->
7944         (* generate the function for typ *)
7945         emit_ocaml_copy_list_function typ
7946     | typ, _ -> () (* empty *)
7947   ) (rstructs_used_by all_functions);
7948
7949   (* The wrappers. *)
7950   List.iter (
7951     fun (name, style, _, _, _, _, _) ->
7952       pr "/* Automatically generated wrapper for function\n";
7953       pr " * ";
7954       generate_ocaml_prototype name style;
7955       pr " */\n";
7956       pr "\n";
7957
7958       let params =
7959         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7960
7961       let needs_extra_vs =
7962         match fst style with RConstOptString _ -> true | _ -> false in
7963
7964       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7965       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7966       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7967       pr "\n";
7968
7969       pr "CAMLprim value\n";
7970       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7971       List.iter (pr ", value %s") (List.tl params);
7972       pr ")\n";
7973       pr "{\n";
7974
7975       (match params with
7976        | [p1; p2; p3; p4; p5] ->
7977            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7978        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7979            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7980            pr "  CAMLxparam%d (%s);\n"
7981              (List.length rest) (String.concat ", " rest)
7982        | ps ->
7983            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7984       );
7985       if not needs_extra_vs then
7986         pr "  CAMLlocal1 (rv);\n"
7987       else
7988         pr "  CAMLlocal3 (rv, v, v2);\n";
7989       pr "\n";
7990
7991       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7992       pr "  if (g == NULL)\n";
7993       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7994       pr "\n";
7995
7996       List.iter (
7997         function
7998         | Pathname n
7999         | Device n | Dev_or_Path n
8000         | String n
8001         | FileIn n
8002         | FileOut n ->
8003             pr "  const char *%s = String_val (%sv);\n" n n
8004         | OptString n ->
8005             pr "  const char *%s =\n" n;
8006             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8007               n n
8008         | StringList n | DeviceList n ->
8009             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8010         | Bool n ->
8011             pr "  int %s = Bool_val (%sv);\n" n n
8012         | Int n ->
8013             pr "  int %s = Int_val (%sv);\n" n n
8014         | Int64 n ->
8015             pr "  int64_t %s = Int64_val (%sv);\n" n n
8016       ) (snd style);
8017       let error_code =
8018         match fst style with
8019         | RErr -> pr "  int r;\n"; "-1"
8020         | RInt _ -> pr "  int r;\n"; "-1"
8021         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8022         | RBool _ -> pr "  int r;\n"; "-1"
8023         | RConstString _ | RConstOptString _ ->
8024             pr "  const char *r;\n"; "NULL"
8025         | RString _ -> pr "  char *r;\n"; "NULL"
8026         | RStringList _ ->
8027             pr "  int i;\n";
8028             pr "  char **r;\n";
8029             "NULL"
8030         | RStruct (_, typ) ->
8031             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8032         | RStructList (_, typ) ->
8033             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8034         | RHashtable _ ->
8035             pr "  int i;\n";
8036             pr "  char **r;\n";
8037             "NULL"
8038         | RBufferOut _ ->
8039             pr "  char *r;\n";
8040             pr "  size_t size;\n";
8041             "NULL" in
8042       pr "\n";
8043
8044       pr "  caml_enter_blocking_section ();\n";
8045       pr "  r = guestfs_%s " name;
8046       generate_c_call_args ~handle:"g" style;
8047       pr ";\n";
8048       pr "  caml_leave_blocking_section ();\n";
8049
8050       List.iter (
8051         function
8052         | StringList n | DeviceList n ->
8053             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8054         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8055         | Bool _ | Int _ | Int64 _
8056         | FileIn _ | FileOut _ -> ()
8057       ) (snd style);
8058
8059       pr "  if (r == %s)\n" error_code;
8060       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8061       pr "\n";
8062
8063       (match fst style with
8064        | RErr -> pr "  rv = Val_unit;\n"
8065        | RInt _ -> pr "  rv = Val_int (r);\n"
8066        | RInt64 _ ->
8067            pr "  rv = caml_copy_int64 (r);\n"
8068        | RBool _ -> pr "  rv = Val_bool (r);\n"
8069        | RConstString _ ->
8070            pr "  rv = caml_copy_string (r);\n"
8071        | RConstOptString _ ->
8072            pr "  if (r) { /* Some string */\n";
8073            pr "    v = caml_alloc (1, 0);\n";
8074            pr "    v2 = caml_copy_string (r);\n";
8075            pr "    Store_field (v, 0, v2);\n";
8076            pr "  } else /* None */\n";
8077            pr "    v = Val_int (0);\n";
8078        | RString _ ->
8079            pr "  rv = caml_copy_string (r);\n";
8080            pr "  free (r);\n"
8081        | RStringList _ ->
8082            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8083            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8084            pr "  free (r);\n"
8085        | RStruct (_, typ) ->
8086            pr "  rv = copy_%s (r);\n" typ;
8087            pr "  guestfs_free_%s (r);\n" typ;
8088        | RStructList (_, typ) ->
8089            pr "  rv = copy_%s_list (r);\n" typ;
8090            pr "  guestfs_free_%s_list (r);\n" typ;
8091        | RHashtable _ ->
8092            pr "  rv = copy_table (r);\n";
8093            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8094            pr "  free (r);\n";
8095        | RBufferOut _ ->
8096            pr "  rv = caml_alloc_string (size);\n";
8097            pr "  memcpy (String_val (rv), r, size);\n";
8098       );
8099
8100       pr "  CAMLreturn (rv);\n";
8101       pr "}\n";
8102       pr "\n";
8103
8104       if List.length params > 5 then (
8105         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8106         pr "CAMLprim value ";
8107         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8108         pr "CAMLprim value\n";
8109         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8110         pr "{\n";
8111         pr "  return ocaml_guestfs_%s (argv[0]" name;
8112         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8113         pr ");\n";
8114         pr "}\n";
8115         pr "\n"
8116       )
8117   ) all_functions_sorted
8118
8119 and generate_ocaml_structure_decls () =
8120   List.iter (
8121     fun (typ, cols) ->
8122       pr "type %s = {\n" typ;
8123       List.iter (
8124         function
8125         | name, FString -> pr "  %s : string;\n" name
8126         | name, FBuffer -> pr "  %s : string;\n" name
8127         | name, FUUID -> pr "  %s : string;\n" name
8128         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8129         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8130         | name, FChar -> pr "  %s : char;\n" name
8131         | name, FOptPercent -> pr "  %s : float option;\n" name
8132       ) cols;
8133       pr "}\n";
8134       pr "\n"
8135   ) structs
8136
8137 and generate_ocaml_prototype ?(is_external = false) name style =
8138   if is_external then pr "external " else pr "val ";
8139   pr "%s : t -> " name;
8140   List.iter (
8141     function
8142     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8143     | OptString _ -> pr "string option -> "
8144     | StringList _ | DeviceList _ -> pr "string array -> "
8145     | Bool _ -> pr "bool -> "
8146     | Int _ -> pr "int -> "
8147     | Int64 _ -> pr "int64 -> "
8148   ) (snd style);
8149   (match fst style with
8150    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8151    | RInt _ -> pr "int"
8152    | RInt64 _ -> pr "int64"
8153    | RBool _ -> pr "bool"
8154    | RConstString _ -> pr "string"
8155    | RConstOptString _ -> pr "string option"
8156    | RString _ | RBufferOut _ -> pr "string"
8157    | RStringList _ -> pr "string array"
8158    | RStruct (_, typ) -> pr "%s" typ
8159    | RStructList (_, typ) -> pr "%s array" typ
8160    | RHashtable _ -> pr "(string * string) list"
8161   );
8162   if is_external then (
8163     pr " = ";
8164     if List.length (snd style) + 1 > 5 then
8165       pr "\"ocaml_guestfs_%s_byte\" " name;
8166     pr "\"ocaml_guestfs_%s\"" name
8167   );
8168   pr "\n"
8169
8170 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8171 and generate_perl_xs () =
8172   generate_header CStyle LGPLv2plus;
8173
8174   pr "\
8175 #include \"EXTERN.h\"
8176 #include \"perl.h\"
8177 #include \"XSUB.h\"
8178
8179 #include <guestfs.h>
8180
8181 #ifndef PRId64
8182 #define PRId64 \"lld\"
8183 #endif
8184
8185 static SV *
8186 my_newSVll(long long val) {
8187 #ifdef USE_64_BIT_ALL
8188   return newSViv(val);
8189 #else
8190   char buf[100];
8191   int len;
8192   len = snprintf(buf, 100, \"%%\" PRId64, val);
8193   return newSVpv(buf, len);
8194 #endif
8195 }
8196
8197 #ifndef PRIu64
8198 #define PRIu64 \"llu\"
8199 #endif
8200
8201 static SV *
8202 my_newSVull(unsigned long long val) {
8203 #ifdef USE_64_BIT_ALL
8204   return newSVuv(val);
8205 #else
8206   char buf[100];
8207   int len;
8208   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8209   return newSVpv(buf, len);
8210 #endif
8211 }
8212
8213 /* http://www.perlmonks.org/?node_id=680842 */
8214 static char **
8215 XS_unpack_charPtrPtr (SV *arg) {
8216   char **ret;
8217   AV *av;
8218   I32 i;
8219
8220   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8221     croak (\"array reference expected\");
8222
8223   av = (AV *)SvRV (arg);
8224   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8225   if (!ret)
8226     croak (\"malloc failed\");
8227
8228   for (i = 0; i <= av_len (av); i++) {
8229     SV **elem = av_fetch (av, i, 0);
8230
8231     if (!elem || !*elem)
8232       croak (\"missing element in list\");
8233
8234     ret[i] = SvPV_nolen (*elem);
8235   }
8236
8237   ret[i] = NULL;
8238
8239   return ret;
8240 }
8241
8242 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8243
8244 PROTOTYPES: ENABLE
8245
8246 guestfs_h *
8247 _create ()
8248    CODE:
8249       RETVAL = guestfs_create ();
8250       if (!RETVAL)
8251         croak (\"could not create guestfs handle\");
8252       guestfs_set_error_handler (RETVAL, NULL, NULL);
8253  OUTPUT:
8254       RETVAL
8255
8256 void
8257 DESTROY (g)
8258       guestfs_h *g;
8259  PPCODE:
8260       guestfs_close (g);
8261
8262 ";
8263
8264   List.iter (
8265     fun (name, style, _, _, _, _, _) ->
8266       (match fst style with
8267        | RErr -> pr "void\n"
8268        | RInt _ -> pr "SV *\n"
8269        | RInt64 _ -> pr "SV *\n"
8270        | RBool _ -> pr "SV *\n"
8271        | RConstString _ -> pr "SV *\n"
8272        | RConstOptString _ -> pr "SV *\n"
8273        | RString _ -> pr "SV *\n"
8274        | RBufferOut _ -> pr "SV *\n"
8275        | RStringList _
8276        | RStruct _ | RStructList _
8277        | RHashtable _ ->
8278            pr "void\n" (* all lists returned implictly on the stack *)
8279       );
8280       (* Call and arguments. *)
8281       pr "%s " name;
8282       generate_c_call_args ~handle:"g" ~decl:true style;
8283       pr "\n";
8284       pr "      guestfs_h *g;\n";
8285       iteri (
8286         fun i ->
8287           function
8288           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8289               pr "      char *%s;\n" n
8290           | OptString n ->
8291               (* http://www.perlmonks.org/?node_id=554277
8292                * Note that the implicit handle argument means we have
8293                * to add 1 to the ST(x) operator.
8294                *)
8295               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8296           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8297           | Bool n -> pr "      int %s;\n" n
8298           | Int n -> pr "      int %s;\n" n
8299           | Int64 n -> pr "      int64_t %s;\n" n
8300       ) (snd style);
8301
8302       let do_cleanups () =
8303         List.iter (
8304           function
8305           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8306           | Bool _ | Int _ | Int64 _
8307           | FileIn _ | FileOut _ -> ()
8308           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8309         ) (snd style)
8310       in
8311
8312       (* Code. *)
8313       (match fst style with
8314        | RErr ->
8315            pr "PREINIT:\n";
8316            pr "      int r;\n";
8317            pr " PPCODE:\n";
8318            pr "      r = guestfs_%s " name;
8319            generate_c_call_args ~handle:"g" style;
8320            pr ";\n";
8321            do_cleanups ();
8322            pr "      if (r == -1)\n";
8323            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8324        | RInt n
8325        | RBool n ->
8326            pr "PREINIT:\n";
8327            pr "      int %s;\n" n;
8328            pr "   CODE:\n";
8329            pr "      %s = guestfs_%s " n name;
8330            generate_c_call_args ~handle:"g" style;
8331            pr ";\n";
8332            do_cleanups ();
8333            pr "      if (%s == -1)\n" n;
8334            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8335            pr "      RETVAL = newSViv (%s);\n" n;
8336            pr " OUTPUT:\n";
8337            pr "      RETVAL\n"
8338        | RInt64 n ->
8339            pr "PREINIT:\n";
8340            pr "      int64_t %s;\n" n;
8341            pr "   CODE:\n";
8342            pr "      %s = guestfs_%s " n name;
8343            generate_c_call_args ~handle:"g" style;
8344            pr ";\n";
8345            do_cleanups ();
8346            pr "      if (%s == -1)\n" n;
8347            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8348            pr "      RETVAL = my_newSVll (%s);\n" n;
8349            pr " OUTPUT:\n";
8350            pr "      RETVAL\n"
8351        | RConstString n ->
8352            pr "PREINIT:\n";
8353            pr "      const char *%s;\n" n;
8354            pr "   CODE:\n";
8355            pr "      %s = guestfs_%s " n name;
8356            generate_c_call_args ~handle:"g" style;
8357            pr ";\n";
8358            do_cleanups ();
8359            pr "      if (%s == NULL)\n" n;
8360            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8361            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8362            pr " OUTPUT:\n";
8363            pr "      RETVAL\n"
8364        | RConstOptString n ->
8365            pr "PREINIT:\n";
8366            pr "      const char *%s;\n" n;
8367            pr "   CODE:\n";
8368            pr "      %s = guestfs_%s " n name;
8369            generate_c_call_args ~handle:"g" style;
8370            pr ";\n";
8371            do_cleanups ();
8372            pr "      if (%s == NULL)\n" n;
8373            pr "        RETVAL = &PL_sv_undef;\n";
8374            pr "      else\n";
8375            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8376            pr " OUTPUT:\n";
8377            pr "      RETVAL\n"
8378        | RString n ->
8379            pr "PREINIT:\n";
8380            pr "      char *%s;\n" n;
8381            pr "   CODE:\n";
8382            pr "      %s = guestfs_%s " n name;
8383            generate_c_call_args ~handle:"g" style;
8384            pr ";\n";
8385            do_cleanups ();
8386            pr "      if (%s == NULL)\n" n;
8387            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8388            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8389            pr "      free (%s);\n" n;
8390            pr " OUTPUT:\n";
8391            pr "      RETVAL\n"
8392        | RStringList n | RHashtable n ->
8393            pr "PREINIT:\n";
8394            pr "      char **%s;\n" n;
8395            pr "      int i, n;\n";
8396            pr " PPCODE:\n";
8397            pr "      %s = guestfs_%s " n name;
8398            generate_c_call_args ~handle:"g" style;
8399            pr ";\n";
8400            do_cleanups ();
8401            pr "      if (%s == NULL)\n" n;
8402            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8403            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8404            pr "      EXTEND (SP, n);\n";
8405            pr "      for (i = 0; i < n; ++i) {\n";
8406            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8407            pr "        free (%s[i]);\n" n;
8408            pr "      }\n";
8409            pr "      free (%s);\n" n;
8410        | RStruct (n, typ) ->
8411            let cols = cols_of_struct typ in
8412            generate_perl_struct_code typ cols name style n do_cleanups
8413        | RStructList (n, typ) ->
8414            let cols = cols_of_struct typ in
8415            generate_perl_struct_list_code typ cols name style n do_cleanups
8416        | RBufferOut n ->
8417            pr "PREINIT:\n";
8418            pr "      char *%s;\n" n;
8419            pr "      size_t size;\n";
8420            pr "   CODE:\n";
8421            pr "      %s = guestfs_%s " n name;
8422            generate_c_call_args ~handle:"g" style;
8423            pr ";\n";
8424            do_cleanups ();
8425            pr "      if (%s == NULL)\n" n;
8426            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8427            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8428            pr "      free (%s);\n" n;
8429            pr " OUTPUT:\n";
8430            pr "      RETVAL\n"
8431       );
8432
8433       pr "\n"
8434   ) all_functions
8435
8436 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8437   pr "PREINIT:\n";
8438   pr "      struct guestfs_%s_list *%s;\n" typ n;
8439   pr "      int i;\n";
8440   pr "      HV *hv;\n";
8441   pr " PPCODE:\n";
8442   pr "      %s = guestfs_%s " n name;
8443   generate_c_call_args ~handle:"g" style;
8444   pr ";\n";
8445   do_cleanups ();
8446   pr "      if (%s == NULL)\n" n;
8447   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8448   pr "      EXTEND (SP, %s->len);\n" n;
8449   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8450   pr "        hv = newHV ();\n";
8451   List.iter (
8452     function
8453     | name, FString ->
8454         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8455           name (String.length name) n name
8456     | name, FUUID ->
8457         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8458           name (String.length name) n name
8459     | name, FBuffer ->
8460         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8461           name (String.length name) n name n name
8462     | name, (FBytes|FUInt64) ->
8463         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8464           name (String.length name) n name
8465     | name, FInt64 ->
8466         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8467           name (String.length name) n name
8468     | name, (FInt32|FUInt32) ->
8469         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8470           name (String.length name) n name
8471     | name, FChar ->
8472         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8473           name (String.length name) n name
8474     | name, FOptPercent ->
8475         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8476           name (String.length name) n name
8477   ) cols;
8478   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8479   pr "      }\n";
8480   pr "      guestfs_free_%s_list (%s);\n" typ n
8481
8482 and generate_perl_struct_code typ cols name style n do_cleanups =
8483   pr "PREINIT:\n";
8484   pr "      struct guestfs_%s *%s;\n" typ n;
8485   pr " PPCODE:\n";
8486   pr "      %s = guestfs_%s " n name;
8487   generate_c_call_args ~handle:"g" style;
8488   pr ";\n";
8489   do_cleanups ();
8490   pr "      if (%s == NULL)\n" n;
8491   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8492   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8493   List.iter (
8494     fun ((name, _) as col) ->
8495       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8496
8497       match col with
8498       | name, FString ->
8499           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8500             n name
8501       | name, FBuffer ->
8502           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8503             n name n name
8504       | name, FUUID ->
8505           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8506             n name
8507       | name, (FBytes|FUInt64) ->
8508           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8509             n name
8510       | name, FInt64 ->
8511           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8512             n name
8513       | name, (FInt32|FUInt32) ->
8514           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8515             n name
8516       | name, FChar ->
8517           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8518             n name
8519       | name, FOptPercent ->
8520           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8521             n name
8522   ) cols;
8523   pr "      free (%s);\n" n
8524
8525 (* Generate Sys/Guestfs.pm. *)
8526 and generate_perl_pm () =
8527   generate_header HashStyle LGPLv2plus;
8528
8529   pr "\
8530 =pod
8531
8532 =head1 NAME
8533
8534 Sys::Guestfs - Perl bindings for libguestfs
8535
8536 =head1 SYNOPSIS
8537
8538  use Sys::Guestfs;
8539
8540  my $h = Sys::Guestfs->new ();
8541  $h->add_drive ('guest.img');
8542  $h->launch ();
8543  $h->mount ('/dev/sda1', '/');
8544  $h->touch ('/hello');
8545  $h->sync ();
8546
8547 =head1 DESCRIPTION
8548
8549 The C<Sys::Guestfs> module provides a Perl XS binding to the
8550 libguestfs API for examining and modifying virtual machine
8551 disk images.
8552
8553 Amongst the things this is good for: making batch configuration
8554 changes to guests, getting disk used/free statistics (see also:
8555 virt-df), migrating between virtualization systems (see also:
8556 virt-p2v), performing partial backups, performing partial guest
8557 clones, cloning guests and changing registry/UUID/hostname info, and
8558 much else besides.
8559
8560 Libguestfs uses Linux kernel and qemu code, and can access any type of
8561 guest filesystem that Linux and qemu can, including but not limited
8562 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8563 schemes, qcow, qcow2, vmdk.
8564
8565 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8566 LVs, what filesystem is in each LV, etc.).  It can also run commands
8567 in the context of the guest.  Also you can access filesystems over
8568 FUSE.
8569
8570 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8571 functions for using libguestfs from Perl, including integration
8572 with libvirt.
8573
8574 =head1 ERRORS
8575
8576 All errors turn into calls to C<croak> (see L<Carp(3)>).
8577
8578 =head1 METHODS
8579
8580 =over 4
8581
8582 =cut
8583
8584 package Sys::Guestfs;
8585
8586 use strict;
8587 use warnings;
8588
8589 require XSLoader;
8590 XSLoader::load ('Sys::Guestfs');
8591
8592 =item $h = Sys::Guestfs->new ();
8593
8594 Create a new guestfs handle.
8595
8596 =cut
8597
8598 sub new {
8599   my $proto = shift;
8600   my $class = ref ($proto) || $proto;
8601
8602   my $self = Sys::Guestfs::_create ();
8603   bless $self, $class;
8604   return $self;
8605 }
8606
8607 ";
8608
8609   (* Actions.  We only need to print documentation for these as
8610    * they are pulled in from the XS code automatically.
8611    *)
8612   List.iter (
8613     fun (name, style, _, flags, _, _, longdesc) ->
8614       if not (List.mem NotInDocs flags) then (
8615         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8616         pr "=item ";
8617         generate_perl_prototype name style;
8618         pr "\n\n";
8619         pr "%s\n\n" longdesc;
8620         if List.mem ProtocolLimitWarning flags then
8621           pr "%s\n\n" protocol_limit_warning;
8622         if List.mem DangerWillRobinson flags then
8623           pr "%s\n\n" danger_will_robinson;
8624         match deprecation_notice flags with
8625         | None -> ()
8626         | Some txt -> pr "%s\n\n" txt
8627       )
8628   ) all_functions_sorted;
8629
8630   (* End of file. *)
8631   pr "\
8632 =cut
8633
8634 1;
8635
8636 =back
8637
8638 =head1 COPYRIGHT
8639
8640 Copyright (C) %s Red Hat Inc.
8641
8642 =head1 LICENSE
8643
8644 Please see the file COPYING.LIB for the full license.
8645
8646 =head1 SEE ALSO
8647
8648 L<guestfs(3)>,
8649 L<guestfish(1)>,
8650 L<http://libguestfs.org>,
8651 L<Sys::Guestfs::Lib(3)>.
8652
8653 =cut
8654 " copyright_years
8655
8656 and generate_perl_prototype name style =
8657   (match fst style with
8658    | RErr -> ()
8659    | RBool n
8660    | RInt n
8661    | RInt64 n
8662    | RConstString n
8663    | RConstOptString n
8664    | RString n
8665    | RBufferOut n -> pr "$%s = " n
8666    | RStruct (n,_)
8667    | RHashtable n -> pr "%%%s = " n
8668    | RStringList n
8669    | RStructList (n,_) -> pr "@%s = " n
8670   );
8671   pr "$h->%s (" name;
8672   let comma = ref false in
8673   List.iter (
8674     fun arg ->
8675       if !comma then pr ", ";
8676       comma := true;
8677       match arg with
8678       | Pathname n | Device n | Dev_or_Path n | String n
8679       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8680           pr "$%s" n
8681       | StringList n | DeviceList n ->
8682           pr "\\@%s" n
8683   ) (snd style);
8684   pr ");"
8685
8686 (* Generate Python C module. *)
8687 and generate_python_c () =
8688   generate_header CStyle LGPLv2plus;
8689
8690   pr "\
8691 #include <Python.h>
8692
8693 #include <stdio.h>
8694 #include <stdlib.h>
8695 #include <assert.h>
8696
8697 #include \"guestfs.h\"
8698
8699 typedef struct {
8700   PyObject_HEAD
8701   guestfs_h *g;
8702 } Pyguestfs_Object;
8703
8704 static guestfs_h *
8705 get_handle (PyObject *obj)
8706 {
8707   assert (obj);
8708   assert (obj != Py_None);
8709   return ((Pyguestfs_Object *) obj)->g;
8710 }
8711
8712 static PyObject *
8713 put_handle (guestfs_h *g)
8714 {
8715   assert (g);
8716   return
8717     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8718 }
8719
8720 /* This list should be freed (but not the strings) after use. */
8721 static char **
8722 get_string_list (PyObject *obj)
8723 {
8724   int i, len;
8725   char **r;
8726
8727   assert (obj);
8728
8729   if (!PyList_Check (obj)) {
8730     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8731     return NULL;
8732   }
8733
8734   len = PyList_Size (obj);
8735   r = malloc (sizeof (char *) * (len+1));
8736   if (r == NULL) {
8737     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8738     return NULL;
8739   }
8740
8741   for (i = 0; i < len; ++i)
8742     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8743   r[len] = NULL;
8744
8745   return r;
8746 }
8747
8748 static PyObject *
8749 put_string_list (char * const * const argv)
8750 {
8751   PyObject *list;
8752   int argc, i;
8753
8754   for (argc = 0; argv[argc] != NULL; ++argc)
8755     ;
8756
8757   list = PyList_New (argc);
8758   for (i = 0; i < argc; ++i)
8759     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8760
8761   return list;
8762 }
8763
8764 static PyObject *
8765 put_table (char * const * const argv)
8766 {
8767   PyObject *list, *item;
8768   int argc, i;
8769
8770   for (argc = 0; argv[argc] != NULL; ++argc)
8771     ;
8772
8773   list = PyList_New (argc >> 1);
8774   for (i = 0; i < argc; i += 2) {
8775     item = PyTuple_New (2);
8776     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8777     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8778     PyList_SetItem (list, i >> 1, item);
8779   }
8780
8781   return list;
8782 }
8783
8784 static void
8785 free_strings (char **argv)
8786 {
8787   int argc;
8788
8789   for (argc = 0; argv[argc] != NULL; ++argc)
8790     free (argv[argc]);
8791   free (argv);
8792 }
8793
8794 static PyObject *
8795 py_guestfs_create (PyObject *self, PyObject *args)
8796 {
8797   guestfs_h *g;
8798
8799   g = guestfs_create ();
8800   if (g == NULL) {
8801     PyErr_SetString (PyExc_RuntimeError,
8802                      \"guestfs.create: failed to allocate handle\");
8803     return NULL;
8804   }
8805   guestfs_set_error_handler (g, NULL, NULL);
8806   return put_handle (g);
8807 }
8808
8809 static PyObject *
8810 py_guestfs_close (PyObject *self, PyObject *args)
8811 {
8812   PyObject *py_g;
8813   guestfs_h *g;
8814
8815   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8816     return NULL;
8817   g = get_handle (py_g);
8818
8819   guestfs_close (g);
8820
8821   Py_INCREF (Py_None);
8822   return Py_None;
8823 }
8824
8825 ";
8826
8827   let emit_put_list_function typ =
8828     pr "static PyObject *\n";
8829     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8830     pr "{\n";
8831     pr "  PyObject *list;\n";
8832     pr "  int i;\n";
8833     pr "\n";
8834     pr "  list = PyList_New (%ss->len);\n" typ;
8835     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8836     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8837     pr "  return list;\n";
8838     pr "};\n";
8839     pr "\n"
8840   in
8841
8842   (* Structures, turned into Python dictionaries. *)
8843   List.iter (
8844     fun (typ, cols) ->
8845       pr "static PyObject *\n";
8846       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8847       pr "{\n";
8848       pr "  PyObject *dict;\n";
8849       pr "\n";
8850       pr "  dict = PyDict_New ();\n";
8851       List.iter (
8852         function
8853         | name, FString ->
8854             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8855             pr "                        PyString_FromString (%s->%s));\n"
8856               typ name
8857         | name, FBuffer ->
8858             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8859             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8860               typ name typ name
8861         | name, FUUID ->
8862             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8863             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8864               typ name
8865         | name, (FBytes|FUInt64) ->
8866             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8867             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8868               typ name
8869         | name, FInt64 ->
8870             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8871             pr "                        PyLong_FromLongLong (%s->%s));\n"
8872               typ name
8873         | name, FUInt32 ->
8874             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8875             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8876               typ name
8877         | name, FInt32 ->
8878             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8879             pr "                        PyLong_FromLong (%s->%s));\n"
8880               typ name
8881         | name, FOptPercent ->
8882             pr "  if (%s->%s >= 0)\n" typ name;
8883             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8884             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8885               typ name;
8886             pr "  else {\n";
8887             pr "    Py_INCREF (Py_None);\n";
8888             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8889             pr "  }\n"
8890         | name, FChar ->
8891             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8892             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8893       ) cols;
8894       pr "  return dict;\n";
8895       pr "};\n";
8896       pr "\n";
8897
8898   ) structs;
8899
8900   (* Emit a put_TYPE_list function definition only if that function is used. *)
8901   List.iter (
8902     function
8903     | typ, (RStructListOnly | RStructAndList) ->
8904         (* generate the function for typ *)
8905         emit_put_list_function typ
8906     | typ, _ -> () (* empty *)
8907   ) (rstructs_used_by all_functions);
8908
8909   (* Python wrapper functions. *)
8910   List.iter (
8911     fun (name, style, _, _, _, _, _) ->
8912       pr "static PyObject *\n";
8913       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8914       pr "{\n";
8915
8916       pr "  PyObject *py_g;\n";
8917       pr "  guestfs_h *g;\n";
8918       pr "  PyObject *py_r;\n";
8919
8920       let error_code =
8921         match fst style with
8922         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8923         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8924         | RConstString _ | RConstOptString _ ->
8925             pr "  const char *r;\n"; "NULL"
8926         | RString _ -> pr "  char *r;\n"; "NULL"
8927         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8928         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8929         | RStructList (_, typ) ->
8930             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8931         | RBufferOut _ ->
8932             pr "  char *r;\n";
8933             pr "  size_t size;\n";
8934             "NULL" in
8935
8936       List.iter (
8937         function
8938         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8939             pr "  const char *%s;\n" n
8940         | OptString n -> pr "  const char *%s;\n" n
8941         | StringList n | DeviceList n ->
8942             pr "  PyObject *py_%s;\n" n;
8943             pr "  char **%s;\n" n
8944         | Bool n -> pr "  int %s;\n" n
8945         | Int n -> pr "  int %s;\n" n
8946         | Int64 n -> pr "  long long %s;\n" n
8947       ) (snd style);
8948
8949       pr "\n";
8950
8951       (* Convert the parameters. *)
8952       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8953       List.iter (
8954         function
8955         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8956         | OptString _ -> pr "z"
8957         | StringList _ | DeviceList _ -> pr "O"
8958         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8959         | Int _ -> pr "i"
8960         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8961                              * emulate C's int/long/long long in Python?
8962                              *)
8963       ) (snd style);
8964       pr ":guestfs_%s\",\n" name;
8965       pr "                         &py_g";
8966       List.iter (
8967         function
8968         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8969         | OptString n -> pr ", &%s" n
8970         | StringList n | DeviceList n -> pr ", &py_%s" n
8971         | Bool n -> pr ", &%s" n
8972         | Int n -> pr ", &%s" n
8973         | Int64 n -> pr ", &%s" n
8974       ) (snd style);
8975
8976       pr "))\n";
8977       pr "    return NULL;\n";
8978
8979       pr "  g = get_handle (py_g);\n";
8980       List.iter (
8981         function
8982         | Pathname _ | Device _ | Dev_or_Path _ | String _
8983         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8984         | StringList n | DeviceList n ->
8985             pr "  %s = get_string_list (py_%s);\n" n n;
8986             pr "  if (!%s) return NULL;\n" n
8987       ) (snd style);
8988
8989       pr "\n";
8990
8991       pr "  r = guestfs_%s " name;
8992       generate_c_call_args ~handle:"g" style;
8993       pr ";\n";
8994
8995       List.iter (
8996         function
8997         | Pathname _ | Device _ | Dev_or_Path _ | String _
8998         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8999         | StringList n | DeviceList n ->
9000             pr "  free (%s);\n" n
9001       ) (snd style);
9002
9003       pr "  if (r == %s) {\n" error_code;
9004       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9005       pr "    return NULL;\n";
9006       pr "  }\n";
9007       pr "\n";
9008
9009       (match fst style with
9010        | RErr ->
9011            pr "  Py_INCREF (Py_None);\n";
9012            pr "  py_r = Py_None;\n"
9013        | RInt _
9014        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9015        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9016        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9017        | RConstOptString _ ->
9018            pr "  if (r)\n";
9019            pr "    py_r = PyString_FromString (r);\n";
9020            pr "  else {\n";
9021            pr "    Py_INCREF (Py_None);\n";
9022            pr "    py_r = Py_None;\n";
9023            pr "  }\n"
9024        | RString _ ->
9025            pr "  py_r = PyString_FromString (r);\n";
9026            pr "  free (r);\n"
9027        | RStringList _ ->
9028            pr "  py_r = put_string_list (r);\n";
9029            pr "  free_strings (r);\n"
9030        | RStruct (_, typ) ->
9031            pr "  py_r = put_%s (r);\n" typ;
9032            pr "  guestfs_free_%s (r);\n" typ
9033        | RStructList (_, typ) ->
9034            pr "  py_r = put_%s_list (r);\n" typ;
9035            pr "  guestfs_free_%s_list (r);\n" typ
9036        | RHashtable n ->
9037            pr "  py_r = put_table (r);\n";
9038            pr "  free_strings (r);\n"
9039        | RBufferOut _ ->
9040            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9041            pr "  free (r);\n"
9042       );
9043
9044       pr "  return py_r;\n";
9045       pr "}\n";
9046       pr "\n"
9047   ) all_functions;
9048
9049   (* Table of functions. *)
9050   pr "static PyMethodDef methods[] = {\n";
9051   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9052   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9053   List.iter (
9054     fun (name, _, _, _, _, _, _) ->
9055       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9056         name name
9057   ) all_functions;
9058   pr "  { NULL, NULL, 0, NULL }\n";
9059   pr "};\n";
9060   pr "\n";
9061
9062   (* Init function. *)
9063   pr "\
9064 void
9065 initlibguestfsmod (void)
9066 {
9067   static int initialized = 0;
9068
9069   if (initialized) return;
9070   Py_InitModule ((char *) \"libguestfsmod\", methods);
9071   initialized = 1;
9072 }
9073 "
9074
9075 (* Generate Python module. *)
9076 and generate_python_py () =
9077   generate_header HashStyle LGPLv2plus;
9078
9079   pr "\
9080 u\"\"\"Python bindings for libguestfs
9081
9082 import guestfs
9083 g = guestfs.GuestFS ()
9084 g.add_drive (\"guest.img\")
9085 g.launch ()
9086 parts = g.list_partitions ()
9087
9088 The guestfs module provides a Python binding to the libguestfs API
9089 for examining and modifying virtual machine disk images.
9090
9091 Amongst the things this is good for: making batch configuration
9092 changes to guests, getting disk used/free statistics (see also:
9093 virt-df), migrating between virtualization systems (see also:
9094 virt-p2v), performing partial backups, performing partial guest
9095 clones, cloning guests and changing registry/UUID/hostname info, and
9096 much else besides.
9097
9098 Libguestfs uses Linux kernel and qemu code, and can access any type of
9099 guest filesystem that Linux and qemu can, including but not limited
9100 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9101 schemes, qcow, qcow2, vmdk.
9102
9103 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9104 LVs, what filesystem is in each LV, etc.).  It can also run commands
9105 in the context of the guest.  Also you can access filesystems over
9106 FUSE.
9107
9108 Errors which happen while using the API are turned into Python
9109 RuntimeError exceptions.
9110
9111 To create a guestfs handle you usually have to perform the following
9112 sequence of calls:
9113
9114 # Create the handle, call add_drive at least once, and possibly
9115 # several times if the guest has multiple block devices:
9116 g = guestfs.GuestFS ()
9117 g.add_drive (\"guest.img\")
9118
9119 # Launch the qemu subprocess and wait for it to become ready:
9120 g.launch ()
9121
9122 # Now you can issue commands, for example:
9123 logvols = g.lvs ()
9124
9125 \"\"\"
9126
9127 import libguestfsmod
9128
9129 class GuestFS:
9130     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9131
9132     def __init__ (self):
9133         \"\"\"Create a new libguestfs handle.\"\"\"
9134         self._o = libguestfsmod.create ()
9135
9136     def __del__ (self):
9137         libguestfsmod.close (self._o)
9138
9139 ";
9140
9141   List.iter (
9142     fun (name, style, _, flags, _, _, longdesc) ->
9143       pr "    def %s " name;
9144       generate_py_call_args ~handle:"self" (snd style);
9145       pr ":\n";
9146
9147       if not (List.mem NotInDocs flags) then (
9148         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9149         let doc =
9150           match fst style with
9151           | RErr | RInt _ | RInt64 _ | RBool _
9152           | RConstOptString _ | RConstString _
9153           | RString _ | RBufferOut _ -> doc
9154           | RStringList _ ->
9155               doc ^ "\n\nThis function returns a list of strings."
9156           | RStruct (_, typ) ->
9157               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9158           | RStructList (_, typ) ->
9159               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9160           | RHashtable _ ->
9161               doc ^ "\n\nThis function returns a dictionary." in
9162         let doc =
9163           if List.mem ProtocolLimitWarning flags then
9164             doc ^ "\n\n" ^ protocol_limit_warning
9165           else doc in
9166         let doc =
9167           if List.mem DangerWillRobinson flags then
9168             doc ^ "\n\n" ^ danger_will_robinson
9169           else doc in
9170         let doc =
9171           match deprecation_notice flags with
9172           | None -> doc
9173           | Some txt -> doc ^ "\n\n" ^ txt in
9174         let doc = pod2text ~width:60 name doc in
9175         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9176         let doc = String.concat "\n        " doc in
9177         pr "        u\"\"\"%s\"\"\"\n" doc;
9178       );
9179       pr "        return libguestfsmod.%s " name;
9180       generate_py_call_args ~handle:"self._o" (snd style);
9181       pr "\n";
9182       pr "\n";
9183   ) all_functions
9184
9185 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9186 and generate_py_call_args ~handle args =
9187   pr "(%s" handle;
9188   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9189   pr ")"
9190
9191 (* Useful if you need the longdesc POD text as plain text.  Returns a
9192  * list of lines.
9193  *
9194  * Because this is very slow (the slowest part of autogeneration),
9195  * we memoize the results.
9196  *)
9197 and pod2text ~width name longdesc =
9198   let key = width, name, longdesc in
9199   try Hashtbl.find pod2text_memo key
9200   with Not_found ->
9201     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9202     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9203     close_out chan;
9204     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9205     let chan = open_process_in cmd in
9206     let lines = ref [] in
9207     let rec loop i =
9208       let line = input_line chan in
9209       if i = 1 then             (* discard the first line of output *)
9210         loop (i+1)
9211       else (
9212         let line = triml line in
9213         lines := line :: !lines;
9214         loop (i+1)
9215       ) in
9216     let lines = try loop 1 with End_of_file -> List.rev !lines in
9217     unlink filename;
9218     (match close_process_in chan with
9219      | WEXITED 0 -> ()
9220      | WEXITED i ->
9221          failwithf "pod2text: process exited with non-zero status (%d)" i
9222      | WSIGNALED i | WSTOPPED i ->
9223          failwithf "pod2text: process signalled or stopped by signal %d" i
9224     );
9225     Hashtbl.add pod2text_memo key lines;
9226     pod2text_memo_updated ();
9227     lines
9228
9229 (* Generate ruby bindings. *)
9230 and generate_ruby_c () =
9231   generate_header CStyle LGPLv2plus;
9232
9233   pr "\
9234 #include <stdio.h>
9235 #include <stdlib.h>
9236
9237 #include <ruby.h>
9238
9239 #include \"guestfs.h\"
9240
9241 #include \"extconf.h\"
9242
9243 /* For Ruby < 1.9 */
9244 #ifndef RARRAY_LEN
9245 #define RARRAY_LEN(r) (RARRAY((r))->len)
9246 #endif
9247
9248 static VALUE m_guestfs;                 /* guestfs module */
9249 static VALUE c_guestfs;                 /* guestfs_h handle */
9250 static VALUE e_Error;                   /* used for all errors */
9251
9252 static void ruby_guestfs_free (void *p)
9253 {
9254   if (!p) return;
9255   guestfs_close ((guestfs_h *) p);
9256 }
9257
9258 static VALUE ruby_guestfs_create (VALUE m)
9259 {
9260   guestfs_h *g;
9261
9262   g = guestfs_create ();
9263   if (!g)
9264     rb_raise (e_Error, \"failed to create guestfs handle\");
9265
9266   /* Don't print error messages to stderr by default. */
9267   guestfs_set_error_handler (g, NULL, NULL);
9268
9269   /* Wrap it, and make sure the close function is called when the
9270    * handle goes away.
9271    */
9272   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9273 }
9274
9275 static VALUE ruby_guestfs_close (VALUE gv)
9276 {
9277   guestfs_h *g;
9278   Data_Get_Struct (gv, guestfs_h, g);
9279
9280   ruby_guestfs_free (g);
9281   DATA_PTR (gv) = NULL;
9282
9283   return Qnil;
9284 }
9285
9286 ";
9287
9288   List.iter (
9289     fun (name, style, _, _, _, _, _) ->
9290       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9291       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9292       pr ")\n";
9293       pr "{\n";
9294       pr "  guestfs_h *g;\n";
9295       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9296       pr "  if (!g)\n";
9297       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9298         name;
9299       pr "\n";
9300
9301       List.iter (
9302         function
9303         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9304             pr "  Check_Type (%sv, T_STRING);\n" n;
9305             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9306             pr "  if (!%s)\n" n;
9307             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9308             pr "              \"%s\", \"%s\");\n" n name
9309         | OptString n ->
9310             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9311         | StringList n | DeviceList n ->
9312             pr "  char **%s;\n" n;
9313             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9314             pr "  {\n";
9315             pr "    int i, len;\n";
9316             pr "    len = RARRAY_LEN (%sv);\n" n;
9317             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9318               n;
9319             pr "    for (i = 0; i < len; ++i) {\n";
9320             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9321             pr "      %s[i] = StringValueCStr (v);\n" n;
9322             pr "    }\n";
9323             pr "    %s[len] = NULL;\n" n;
9324             pr "  }\n";
9325         | Bool n ->
9326             pr "  int %s = RTEST (%sv);\n" n n
9327         | Int n ->
9328             pr "  int %s = NUM2INT (%sv);\n" n n
9329         | Int64 n ->
9330             pr "  long long %s = NUM2LL (%sv);\n" n n
9331       ) (snd style);
9332       pr "\n";
9333
9334       let error_code =
9335         match fst style with
9336         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9337         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9338         | RConstString _ | RConstOptString _ ->
9339             pr "  const char *r;\n"; "NULL"
9340         | RString _ -> pr "  char *r;\n"; "NULL"
9341         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9342         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9343         | RStructList (_, typ) ->
9344             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9345         | RBufferOut _ ->
9346             pr "  char *r;\n";
9347             pr "  size_t size;\n";
9348             "NULL" in
9349       pr "\n";
9350
9351       pr "  r = guestfs_%s " name;
9352       generate_c_call_args ~handle:"g" style;
9353       pr ";\n";
9354
9355       List.iter (
9356         function
9357         | Pathname _ | Device _ | Dev_or_Path _ | String _
9358         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9359         | StringList n | DeviceList n ->
9360             pr "  free (%s);\n" n
9361       ) (snd style);
9362
9363       pr "  if (r == %s)\n" error_code;
9364       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9365       pr "\n";
9366
9367       (match fst style with
9368        | RErr ->
9369            pr "  return Qnil;\n"
9370        | RInt _ | RBool _ ->
9371            pr "  return INT2NUM (r);\n"
9372        | RInt64 _ ->
9373            pr "  return ULL2NUM (r);\n"
9374        | RConstString _ ->
9375            pr "  return rb_str_new2 (r);\n";
9376        | RConstOptString _ ->
9377            pr "  if (r)\n";
9378            pr "    return rb_str_new2 (r);\n";
9379            pr "  else\n";
9380            pr "    return Qnil;\n";
9381        | RString _ ->
9382            pr "  VALUE rv = rb_str_new2 (r);\n";
9383            pr "  free (r);\n";
9384            pr "  return rv;\n";
9385        | RStringList _ ->
9386            pr "  int i, len = 0;\n";
9387            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9388            pr "  VALUE rv = rb_ary_new2 (len);\n";
9389            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9390            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9391            pr "    free (r[i]);\n";
9392            pr "  }\n";
9393            pr "  free (r);\n";
9394            pr "  return rv;\n"
9395        | RStruct (_, typ) ->
9396            let cols = cols_of_struct typ in
9397            generate_ruby_struct_code typ cols
9398        | RStructList (_, typ) ->
9399            let cols = cols_of_struct typ in
9400            generate_ruby_struct_list_code typ cols
9401        | RHashtable _ ->
9402            pr "  VALUE rv = rb_hash_new ();\n";
9403            pr "  int i;\n";
9404            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9405            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9406            pr "    free (r[i]);\n";
9407            pr "    free (r[i+1]);\n";
9408            pr "  }\n";
9409            pr "  free (r);\n";
9410            pr "  return rv;\n"
9411        | RBufferOut _ ->
9412            pr "  VALUE rv = rb_str_new (r, size);\n";
9413            pr "  free (r);\n";
9414            pr "  return rv;\n";
9415       );
9416
9417       pr "}\n";
9418       pr "\n"
9419   ) all_functions;
9420
9421   pr "\
9422 /* Initialize the module. */
9423 void Init__guestfs ()
9424 {
9425   m_guestfs = rb_define_module (\"Guestfs\");
9426   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9427   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9428
9429   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9430   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9431
9432 ";
9433   (* Define the rest of the methods. *)
9434   List.iter (
9435     fun (name, style, _, _, _, _, _) ->
9436       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9437       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9438   ) all_functions;
9439
9440   pr "}\n"
9441
9442 (* Ruby code to return a struct. *)
9443 and generate_ruby_struct_code typ cols =
9444   pr "  VALUE rv = rb_hash_new ();\n";
9445   List.iter (
9446     function
9447     | name, FString ->
9448         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9449     | name, FBuffer ->
9450         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9451     | name, FUUID ->
9452         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9453     | name, (FBytes|FUInt64) ->
9454         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9455     | name, FInt64 ->
9456         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9457     | name, FUInt32 ->
9458         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9459     | name, FInt32 ->
9460         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9461     | name, FOptPercent ->
9462         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9463     | name, FChar -> (* XXX wrong? *)
9464         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9465   ) cols;
9466   pr "  guestfs_free_%s (r);\n" typ;
9467   pr "  return rv;\n"
9468
9469 (* Ruby code to return a struct list. *)
9470 and generate_ruby_struct_list_code typ cols =
9471   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9472   pr "  int i;\n";
9473   pr "  for (i = 0; i < r->len; ++i) {\n";
9474   pr "    VALUE hv = rb_hash_new ();\n";
9475   List.iter (
9476     function
9477     | name, FString ->
9478         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9479     | name, FBuffer ->
9480         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
9481     | name, FUUID ->
9482         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9483     | name, (FBytes|FUInt64) ->
9484         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9485     | name, FInt64 ->
9486         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9487     | name, FUInt32 ->
9488         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9489     | name, FInt32 ->
9490         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9491     | name, FOptPercent ->
9492         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9493     | name, FChar -> (* XXX wrong? *)
9494         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9495   ) cols;
9496   pr "    rb_ary_push (rv, hv);\n";
9497   pr "  }\n";
9498   pr "  guestfs_free_%s_list (r);\n" typ;
9499   pr "  return rv;\n"
9500
9501 (* Generate Java bindings GuestFS.java file. *)
9502 and generate_java_java () =
9503   generate_header CStyle LGPLv2plus;
9504
9505   pr "\
9506 package com.redhat.et.libguestfs;
9507
9508 import java.util.HashMap;
9509 import com.redhat.et.libguestfs.LibGuestFSException;
9510 import com.redhat.et.libguestfs.PV;
9511 import com.redhat.et.libguestfs.VG;
9512 import com.redhat.et.libguestfs.LV;
9513 import com.redhat.et.libguestfs.Stat;
9514 import com.redhat.et.libguestfs.StatVFS;
9515 import com.redhat.et.libguestfs.IntBool;
9516 import com.redhat.et.libguestfs.Dirent;
9517
9518 /**
9519  * The GuestFS object is a libguestfs handle.
9520  *
9521  * @author rjones
9522  */
9523 public class GuestFS {
9524   // Load the native code.
9525   static {
9526     System.loadLibrary (\"guestfs_jni\");
9527   }
9528
9529   /**
9530    * The native guestfs_h pointer.
9531    */
9532   long g;
9533
9534   /**
9535    * Create a libguestfs handle.
9536    *
9537    * @throws LibGuestFSException
9538    */
9539   public GuestFS () throws LibGuestFSException
9540   {
9541     g = _create ();
9542   }
9543   private native long _create () throws LibGuestFSException;
9544
9545   /**
9546    * Close a libguestfs handle.
9547    *
9548    * You can also leave handles to be collected by the garbage
9549    * collector, but this method ensures that the resources used
9550    * by the handle are freed up immediately.  If you call any
9551    * other methods after closing the handle, you will get an
9552    * exception.
9553    *
9554    * @throws LibGuestFSException
9555    */
9556   public void close () throws LibGuestFSException
9557   {
9558     if (g != 0)
9559       _close (g);
9560     g = 0;
9561   }
9562   private native void _close (long g) throws LibGuestFSException;
9563
9564   public void finalize () throws LibGuestFSException
9565   {
9566     close ();
9567   }
9568
9569 ";
9570
9571   List.iter (
9572     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9573       if not (List.mem NotInDocs flags); then (
9574         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9575         let doc =
9576           if List.mem ProtocolLimitWarning flags then
9577             doc ^ "\n\n" ^ protocol_limit_warning
9578           else doc in
9579         let doc =
9580           if List.mem DangerWillRobinson flags then
9581             doc ^ "\n\n" ^ danger_will_robinson
9582           else doc in
9583         let doc =
9584           match deprecation_notice flags with
9585           | None -> doc
9586           | Some txt -> doc ^ "\n\n" ^ txt in
9587         let doc = pod2text ~width:60 name doc in
9588         let doc = List.map (            (* RHBZ#501883 *)
9589           function
9590           | "" -> "<p>"
9591           | nonempty -> nonempty
9592         ) doc in
9593         let doc = String.concat "\n   * " doc in
9594
9595         pr "  /**\n";
9596         pr "   * %s\n" shortdesc;
9597         pr "   * <p>\n";
9598         pr "   * %s\n" doc;
9599         pr "   * @throws LibGuestFSException\n";
9600         pr "   */\n";
9601         pr "  ";
9602       );
9603       generate_java_prototype ~public:true ~semicolon:false name style;
9604       pr "\n";
9605       pr "  {\n";
9606       pr "    if (g == 0)\n";
9607       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9608         name;
9609       pr "    ";
9610       if fst style <> RErr then pr "return ";
9611       pr "_%s " name;
9612       generate_java_call_args ~handle:"g" (snd style);
9613       pr ";\n";
9614       pr "  }\n";
9615       pr "  ";
9616       generate_java_prototype ~privat:true ~native:true name style;
9617       pr "\n";
9618       pr "\n";
9619   ) all_functions;
9620
9621   pr "}\n"
9622
9623 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9624 and generate_java_call_args ~handle args =
9625   pr "(%s" handle;
9626   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9627   pr ")"
9628
9629 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9630     ?(semicolon=true) name style =
9631   if privat then pr "private ";
9632   if public then pr "public ";
9633   if native then pr "native ";
9634
9635   (* return type *)
9636   (match fst style with
9637    | RErr -> pr "void ";
9638    | RInt _ -> pr "int ";
9639    | RInt64 _ -> pr "long ";
9640    | RBool _ -> pr "boolean ";
9641    | RConstString _ | RConstOptString _ | RString _
9642    | RBufferOut _ -> pr "String ";
9643    | RStringList _ -> pr "String[] ";
9644    | RStruct (_, typ) ->
9645        let name = java_name_of_struct typ in
9646        pr "%s " name;
9647    | RStructList (_, typ) ->
9648        let name = java_name_of_struct typ in
9649        pr "%s[] " name;
9650    | RHashtable _ -> pr "HashMap<String,String> ";
9651   );
9652
9653   if native then pr "_%s " name else pr "%s " name;
9654   pr "(";
9655   let needs_comma = ref false in
9656   if native then (
9657     pr "long g";
9658     needs_comma := true
9659   );
9660
9661   (* args *)
9662   List.iter (
9663     fun arg ->
9664       if !needs_comma then pr ", ";
9665       needs_comma := true;
9666
9667       match arg with
9668       | Pathname n
9669       | Device n | Dev_or_Path n
9670       | String n
9671       | OptString n
9672       | FileIn n
9673       | FileOut n ->
9674           pr "String %s" n
9675       | StringList n | DeviceList n ->
9676           pr "String[] %s" n
9677       | Bool n ->
9678           pr "boolean %s" n
9679       | Int n ->
9680           pr "int %s" n
9681       | Int64 n ->
9682           pr "long %s" n
9683   ) (snd style);
9684
9685   pr ")\n";
9686   pr "    throws LibGuestFSException";
9687   if semicolon then pr ";"
9688
9689 and generate_java_struct jtyp cols () =
9690   generate_header CStyle LGPLv2plus;
9691
9692   pr "\
9693 package com.redhat.et.libguestfs;
9694
9695 /**
9696  * Libguestfs %s structure.
9697  *
9698  * @author rjones
9699  * @see GuestFS
9700  */
9701 public class %s {
9702 " jtyp jtyp;
9703
9704   List.iter (
9705     function
9706     | name, FString
9707     | name, FUUID
9708     | name, FBuffer -> pr "  public String %s;\n" name
9709     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9710     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9711     | name, FChar -> pr "  public char %s;\n" name
9712     | name, FOptPercent ->
9713         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9714         pr "  public float %s;\n" name
9715   ) cols;
9716
9717   pr "}\n"
9718
9719 and generate_java_c () =
9720   generate_header CStyle LGPLv2plus;
9721
9722   pr "\
9723 #include <stdio.h>
9724 #include <stdlib.h>
9725 #include <string.h>
9726
9727 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9728 #include \"guestfs.h\"
9729
9730 /* Note that this function returns.  The exception is not thrown
9731  * until after the wrapper function returns.
9732  */
9733 static void
9734 throw_exception (JNIEnv *env, const char *msg)
9735 {
9736   jclass cl;
9737   cl = (*env)->FindClass (env,
9738                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9739   (*env)->ThrowNew (env, cl, msg);
9740 }
9741
9742 JNIEXPORT jlong JNICALL
9743 Java_com_redhat_et_libguestfs_GuestFS__1create
9744   (JNIEnv *env, jobject obj)
9745 {
9746   guestfs_h *g;
9747
9748   g = guestfs_create ();
9749   if (g == NULL) {
9750     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9751     return 0;
9752   }
9753   guestfs_set_error_handler (g, NULL, NULL);
9754   return (jlong) (long) g;
9755 }
9756
9757 JNIEXPORT void JNICALL
9758 Java_com_redhat_et_libguestfs_GuestFS__1close
9759   (JNIEnv *env, jobject obj, jlong jg)
9760 {
9761   guestfs_h *g = (guestfs_h *) (long) jg;
9762   guestfs_close (g);
9763 }
9764
9765 ";
9766
9767   List.iter (
9768     fun (name, style, _, _, _, _, _) ->
9769       pr "JNIEXPORT ";
9770       (match fst style with
9771        | RErr -> pr "void ";
9772        | RInt _ -> pr "jint ";
9773        | RInt64 _ -> pr "jlong ";
9774        | RBool _ -> pr "jboolean ";
9775        | RConstString _ | RConstOptString _ | RString _
9776        | RBufferOut _ -> pr "jstring ";
9777        | RStruct _ | RHashtable _ ->
9778            pr "jobject ";
9779        | RStringList _ | RStructList _ ->
9780            pr "jobjectArray ";
9781       );
9782       pr "JNICALL\n";
9783       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9784       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9785       pr "\n";
9786       pr "  (JNIEnv *env, jobject obj, jlong jg";
9787       List.iter (
9788         function
9789         | Pathname n
9790         | Device n | Dev_or_Path n
9791         | String n
9792         | OptString n
9793         | FileIn n
9794         | FileOut n ->
9795             pr ", jstring j%s" n
9796         | StringList n | DeviceList n ->
9797             pr ", jobjectArray j%s" n
9798         | Bool n ->
9799             pr ", jboolean j%s" n
9800         | Int n ->
9801             pr ", jint j%s" n
9802         | Int64 n ->
9803             pr ", jlong j%s" n
9804       ) (snd style);
9805       pr ")\n";
9806       pr "{\n";
9807       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9808       let error_code, no_ret =
9809         match fst style with
9810         | RErr -> pr "  int r;\n"; "-1", ""
9811         | RBool _
9812         | RInt _ -> pr "  int r;\n"; "-1", "0"
9813         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9814         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9815         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9816         | RString _ ->
9817             pr "  jstring jr;\n";
9818             pr "  char *r;\n"; "NULL", "NULL"
9819         | RStringList _ ->
9820             pr "  jobjectArray jr;\n";
9821             pr "  int r_len;\n";
9822             pr "  jclass cl;\n";
9823             pr "  jstring jstr;\n";
9824             pr "  char **r;\n"; "NULL", "NULL"
9825         | RStruct (_, typ) ->
9826             pr "  jobject jr;\n";
9827             pr "  jclass cl;\n";
9828             pr "  jfieldID fl;\n";
9829             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9830         | RStructList (_, typ) ->
9831             pr "  jobjectArray jr;\n";
9832             pr "  jclass cl;\n";
9833             pr "  jfieldID fl;\n";
9834             pr "  jobject jfl;\n";
9835             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9836         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9837         | RBufferOut _ ->
9838             pr "  jstring jr;\n";
9839             pr "  char *r;\n";
9840             pr "  size_t size;\n";
9841             "NULL", "NULL" in
9842       List.iter (
9843         function
9844         | Pathname n
9845         | Device n | Dev_or_Path n
9846         | String n
9847         | OptString n
9848         | FileIn n
9849         | FileOut n ->
9850             pr "  const char *%s;\n" n
9851         | StringList n | DeviceList n ->
9852             pr "  int %s_len;\n" n;
9853             pr "  const char **%s;\n" n
9854         | Bool n
9855         | Int n ->
9856             pr "  int %s;\n" n
9857         | Int64 n ->
9858             pr "  int64_t %s;\n" n
9859       ) (snd style);
9860
9861       let needs_i =
9862         (match fst style with
9863          | RStringList _ | RStructList _ -> true
9864          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9865          | RConstOptString _
9866          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9867           List.exists (function
9868                        | StringList _ -> true
9869                        | DeviceList _ -> true
9870                        | _ -> false) (snd style) in
9871       if needs_i then
9872         pr "  int i;\n";
9873
9874       pr "\n";
9875
9876       (* Get the parameters. *)
9877       List.iter (
9878         function
9879         | Pathname n
9880         | Device n | Dev_or_Path n
9881         | String n
9882         | FileIn n
9883         | FileOut n ->
9884             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9885         | OptString n ->
9886             (* This is completely undocumented, but Java null becomes
9887              * a NULL parameter.
9888              *)
9889             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9890         | StringList n | DeviceList n ->
9891             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9892             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9893             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9894             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9895               n;
9896             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9897             pr "  }\n";
9898             pr "  %s[%s_len] = NULL;\n" n n;
9899         | Bool n
9900         | Int n
9901         | Int64 n ->
9902             pr "  %s = j%s;\n" n n
9903       ) (snd style);
9904
9905       (* Make the call. *)
9906       pr "  r = guestfs_%s " name;
9907       generate_c_call_args ~handle:"g" style;
9908       pr ";\n";
9909
9910       (* Release the parameters. *)
9911       List.iter (
9912         function
9913         | Pathname n
9914         | Device n | Dev_or_Path n
9915         | String n
9916         | FileIn n
9917         | FileOut n ->
9918             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9919         | OptString n ->
9920             pr "  if (j%s)\n" n;
9921             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9922         | StringList n | DeviceList n ->
9923             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9924             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9925               n;
9926             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9927             pr "  }\n";
9928             pr "  free (%s);\n" n
9929         | Bool n
9930         | Int n
9931         | Int64 n -> ()
9932       ) (snd style);
9933
9934       (* Check for errors. *)
9935       pr "  if (r == %s) {\n" error_code;
9936       pr "    throw_exception (env, guestfs_last_error (g));\n";
9937       pr "    return %s;\n" no_ret;
9938       pr "  }\n";
9939
9940       (* Return value. *)
9941       (match fst style with
9942        | RErr -> ()
9943        | RInt _ -> pr "  return (jint) r;\n"
9944        | RBool _ -> pr "  return (jboolean) r;\n"
9945        | RInt64 _ -> pr "  return (jlong) r;\n"
9946        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9947        | RConstOptString _ ->
9948            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9949        | RString _ ->
9950            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9951            pr "  free (r);\n";
9952            pr "  return jr;\n"
9953        | RStringList _ ->
9954            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9955            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9956            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9957            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9958            pr "  for (i = 0; i < r_len; ++i) {\n";
9959            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9960            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9961            pr "    free (r[i]);\n";
9962            pr "  }\n";
9963            pr "  free (r);\n";
9964            pr "  return jr;\n"
9965        | RStruct (_, typ) ->
9966            let jtyp = java_name_of_struct typ in
9967            let cols = cols_of_struct typ in
9968            generate_java_struct_return typ jtyp cols
9969        | RStructList (_, typ) ->
9970            let jtyp = java_name_of_struct typ in
9971            let cols = cols_of_struct typ in
9972            generate_java_struct_list_return typ jtyp cols
9973        | RHashtable _ ->
9974            (* XXX *)
9975            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9976            pr "  return NULL;\n"
9977        | RBufferOut _ ->
9978            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9979            pr "  free (r);\n";
9980            pr "  return jr;\n"
9981       );
9982
9983       pr "}\n";
9984       pr "\n"
9985   ) all_functions
9986
9987 and generate_java_struct_return typ jtyp cols =
9988   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9989   pr "  jr = (*env)->AllocObject (env, cl);\n";
9990   List.iter (
9991     function
9992     | name, FString ->
9993         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9994         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9995     | name, FUUID ->
9996         pr "  {\n";
9997         pr "    char s[33];\n";
9998         pr "    memcpy (s, r->%s, 32);\n" name;
9999         pr "    s[32] = 0;\n";
10000         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10001         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10002         pr "  }\n";
10003     | name, FBuffer ->
10004         pr "  {\n";
10005         pr "    int len = r->%s_len;\n" name;
10006         pr "    char s[len+1];\n";
10007         pr "    memcpy (s, r->%s, len);\n" name;
10008         pr "    s[len] = 0;\n";
10009         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10010         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10011         pr "  }\n";
10012     | name, (FBytes|FUInt64|FInt64) ->
10013         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10014         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10015     | name, (FUInt32|FInt32) ->
10016         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10017         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10018     | name, FOptPercent ->
10019         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10020         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10021     | name, FChar ->
10022         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10023         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10024   ) cols;
10025   pr "  free (r);\n";
10026   pr "  return jr;\n"
10027
10028 and generate_java_struct_list_return typ jtyp cols =
10029   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10030   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10031   pr "  for (i = 0; i < r->len; ++i) {\n";
10032   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10033   List.iter (
10034     function
10035     | name, FString ->
10036         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10037         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10038     | name, FUUID ->
10039         pr "    {\n";
10040         pr "      char s[33];\n";
10041         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10042         pr "      s[32] = 0;\n";
10043         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10044         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10045         pr "    }\n";
10046     | name, FBuffer ->
10047         pr "    {\n";
10048         pr "      int len = r->val[i].%s_len;\n" name;
10049         pr "      char s[len+1];\n";
10050         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10051         pr "      s[len] = 0;\n";
10052         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10053         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10054         pr "    }\n";
10055     | name, (FBytes|FUInt64|FInt64) ->
10056         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10057         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10058     | name, (FUInt32|FInt32) ->
10059         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10060         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10061     | name, FOptPercent ->
10062         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10063         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10064     | name, FChar ->
10065         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10066         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10067   ) cols;
10068   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10069   pr "  }\n";
10070   pr "  guestfs_free_%s_list (r);\n" typ;
10071   pr "  return jr;\n"
10072
10073 and generate_java_makefile_inc () =
10074   generate_header HashStyle GPLv2plus;
10075
10076   pr "java_built_sources = \\\n";
10077   List.iter (
10078     fun (typ, jtyp) ->
10079         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10080   ) java_structs;
10081   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10082
10083 and generate_haskell_hs () =
10084   generate_header HaskellStyle LGPLv2plus;
10085
10086   (* XXX We only know how to generate partial FFI for Haskell
10087    * at the moment.  Please help out!
10088    *)
10089   let can_generate style =
10090     match style with
10091     | RErr, _
10092     | RInt _, _
10093     | RInt64 _, _ -> true
10094     | RBool _, _
10095     | RConstString _, _
10096     | RConstOptString _, _
10097     | RString _, _
10098     | RStringList _, _
10099     | RStruct _, _
10100     | RStructList _, _
10101     | RHashtable _, _
10102     | RBufferOut _, _ -> false in
10103
10104   pr "\
10105 {-# INCLUDE <guestfs.h> #-}
10106 {-# LANGUAGE ForeignFunctionInterface #-}
10107
10108 module Guestfs (
10109   create";
10110
10111   (* List out the names of the actions we want to export. *)
10112   List.iter (
10113     fun (name, style, _, _, _, _, _) ->
10114       if can_generate style then pr ",\n  %s" name
10115   ) all_functions;
10116
10117   pr "
10118   ) where
10119
10120 -- Unfortunately some symbols duplicate ones already present
10121 -- in Prelude.  We don't know which, so we hard-code a list
10122 -- here.
10123 import Prelude hiding (truncate)
10124
10125 import Foreign
10126 import Foreign.C
10127 import Foreign.C.Types
10128 import IO
10129 import Control.Exception
10130 import Data.Typeable
10131
10132 data GuestfsS = GuestfsS            -- represents the opaque C struct
10133 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10134 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10135
10136 -- XXX define properly later XXX
10137 data PV = PV
10138 data VG = VG
10139 data LV = LV
10140 data IntBool = IntBool
10141 data Stat = Stat
10142 data StatVFS = StatVFS
10143 data Hashtable = Hashtable
10144
10145 foreign import ccall unsafe \"guestfs_create\" c_create
10146   :: IO GuestfsP
10147 foreign import ccall unsafe \"&guestfs_close\" c_close
10148   :: FunPtr (GuestfsP -> IO ())
10149 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10150   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10151
10152 create :: IO GuestfsH
10153 create = do
10154   p <- c_create
10155   c_set_error_handler p nullPtr nullPtr
10156   h <- newForeignPtr c_close p
10157   return h
10158
10159 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10160   :: GuestfsP -> IO CString
10161
10162 -- last_error :: GuestfsH -> IO (Maybe String)
10163 -- last_error h = do
10164 --   str <- withForeignPtr h (\\p -> c_last_error p)
10165 --   maybePeek peekCString str
10166
10167 last_error :: GuestfsH -> IO (String)
10168 last_error h = do
10169   str <- withForeignPtr h (\\p -> c_last_error p)
10170   if (str == nullPtr)
10171     then return \"no error\"
10172     else peekCString str
10173
10174 ";
10175
10176   (* Generate wrappers for each foreign function. *)
10177   List.iter (
10178     fun (name, style, _, _, _, _, _) ->
10179       if can_generate style then (
10180         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10181         pr "  :: ";
10182         generate_haskell_prototype ~handle:"GuestfsP" style;
10183         pr "\n";
10184         pr "\n";
10185         pr "%s :: " name;
10186         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10187         pr "\n";
10188         pr "%s %s = do\n" name
10189           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10190         pr "  r <- ";
10191         (* Convert pointer arguments using with* functions. *)
10192         List.iter (
10193           function
10194           | FileIn n
10195           | FileOut n
10196           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10197           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10198           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10199           | Bool _ | Int _ | Int64 _ -> ()
10200         ) (snd style);
10201         (* Convert integer arguments. *)
10202         let args =
10203           List.map (
10204             function
10205             | Bool n -> sprintf "(fromBool %s)" n
10206             | Int n -> sprintf "(fromIntegral %s)" n
10207             | Int64 n -> sprintf "(fromIntegral %s)" n
10208             | FileIn n | FileOut n
10209             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10210           ) (snd style) in
10211         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10212           (String.concat " " ("p" :: args));
10213         (match fst style with
10214          | RErr | RInt _ | RInt64 _ | RBool _ ->
10215              pr "  if (r == -1)\n";
10216              pr "    then do\n";
10217              pr "      err <- last_error h\n";
10218              pr "      fail err\n";
10219          | RConstString _ | RConstOptString _ | RString _
10220          | RStringList _ | RStruct _
10221          | RStructList _ | RHashtable _ | RBufferOut _ ->
10222              pr "  if (r == nullPtr)\n";
10223              pr "    then do\n";
10224              pr "      err <- last_error h\n";
10225              pr "      fail err\n";
10226         );
10227         (match fst style with
10228          | RErr ->
10229              pr "    else return ()\n"
10230          | RInt _ ->
10231              pr "    else return (fromIntegral r)\n"
10232          | RInt64 _ ->
10233              pr "    else return (fromIntegral r)\n"
10234          | RBool _ ->
10235              pr "    else return (toBool r)\n"
10236          | RConstString _
10237          | RConstOptString _
10238          | RString _
10239          | RStringList _
10240          | RStruct _
10241          | RStructList _
10242          | RHashtable _
10243          | RBufferOut _ ->
10244              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10245         );
10246         pr "\n";
10247       )
10248   ) all_functions
10249
10250 and generate_haskell_prototype ~handle ?(hs = false) style =
10251   pr "%s -> " handle;
10252   let string = if hs then "String" else "CString" in
10253   let int = if hs then "Int" else "CInt" in
10254   let bool = if hs then "Bool" else "CInt" in
10255   let int64 = if hs then "Integer" else "Int64" in
10256   List.iter (
10257     fun arg ->
10258       (match arg with
10259        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10260        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10261        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10262        | Bool _ -> pr "%s" bool
10263        | Int _ -> pr "%s" int
10264        | Int64 _ -> pr "%s" int
10265        | FileIn _ -> pr "%s" string
10266        | FileOut _ -> pr "%s" string
10267       );
10268       pr " -> ";
10269   ) (snd style);
10270   pr "IO (";
10271   (match fst style with
10272    | RErr -> if not hs then pr "CInt"
10273    | RInt _ -> pr "%s" int
10274    | RInt64 _ -> pr "%s" int64
10275    | RBool _ -> pr "%s" bool
10276    | RConstString _ -> pr "%s" string
10277    | RConstOptString _ -> pr "Maybe %s" string
10278    | RString _ -> pr "%s" string
10279    | RStringList _ -> pr "[%s]" string
10280    | RStruct (_, typ) ->
10281        let name = java_name_of_struct typ in
10282        pr "%s" name
10283    | RStructList (_, typ) ->
10284        let name = java_name_of_struct typ in
10285        pr "[%s]" name
10286    | RHashtable _ -> pr "Hashtable"
10287    | RBufferOut _ -> pr "%s" string
10288   );
10289   pr ")"
10290
10291 and generate_csharp () =
10292   generate_header CPlusPlusStyle LGPLv2plus;
10293
10294   (* XXX Make this configurable by the C# assembly users. *)
10295   let library = "libguestfs.so.0" in
10296
10297   pr "\
10298 // These C# bindings are highly experimental at present.
10299 //
10300 // Firstly they only work on Linux (ie. Mono).  In order to get them
10301 // to work on Windows (ie. .Net) you would need to port the library
10302 // itself to Windows first.
10303 //
10304 // The second issue is that some calls are known to be incorrect and
10305 // can cause Mono to segfault.  Particularly: calls which pass or
10306 // return string[], or return any structure value.  This is because
10307 // we haven't worked out the correct way to do this from C#.
10308 //
10309 // The third issue is that when compiling you get a lot of warnings.
10310 // We are not sure whether the warnings are important or not.
10311 //
10312 // Fourthly we do not routinely build or test these bindings as part
10313 // of the make && make check cycle, which means that regressions might
10314 // go unnoticed.
10315 //
10316 // Suggestions and patches are welcome.
10317
10318 // To compile:
10319 //
10320 // gmcs Libguestfs.cs
10321 // mono Libguestfs.exe
10322 //
10323 // (You'll probably want to add a Test class / static main function
10324 // otherwise this won't do anything useful).
10325
10326 using System;
10327 using System.IO;
10328 using System.Runtime.InteropServices;
10329 using System.Runtime.Serialization;
10330 using System.Collections;
10331
10332 namespace Guestfs
10333 {
10334   class Error : System.ApplicationException
10335   {
10336     public Error (string message) : base (message) {}
10337     protected Error (SerializationInfo info, StreamingContext context) {}
10338   }
10339
10340   class Guestfs
10341   {
10342     IntPtr _handle;
10343
10344     [DllImport (\"%s\")]
10345     static extern IntPtr guestfs_create ();
10346
10347     public Guestfs ()
10348     {
10349       _handle = guestfs_create ();
10350       if (_handle == IntPtr.Zero)
10351         throw new Error (\"could not create guestfs handle\");
10352     }
10353
10354     [DllImport (\"%s\")]
10355     static extern void guestfs_close (IntPtr h);
10356
10357     ~Guestfs ()
10358     {
10359       guestfs_close (_handle);
10360     }
10361
10362     [DllImport (\"%s\")]
10363     static extern string guestfs_last_error (IntPtr h);
10364
10365 " library library library;
10366
10367   (* Generate C# structure bindings.  We prefix struct names with
10368    * underscore because C# cannot have conflicting struct names and
10369    * method names (eg. "class stat" and "stat").
10370    *)
10371   List.iter (
10372     fun (typ, cols) ->
10373       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10374       pr "    public class _%s {\n" typ;
10375       List.iter (
10376         function
10377         | name, FChar -> pr "      char %s;\n" name
10378         | name, FString -> pr "      string %s;\n" name
10379         | name, FBuffer ->
10380             pr "      uint %s_len;\n" name;
10381             pr "      string %s;\n" name
10382         | name, FUUID ->
10383             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10384             pr "      string %s;\n" name
10385         | name, FUInt32 -> pr "      uint %s;\n" name
10386         | name, FInt32 -> pr "      int %s;\n" name
10387         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10388         | name, FInt64 -> pr "      long %s;\n" name
10389         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10390       ) cols;
10391       pr "    }\n";
10392       pr "\n"
10393   ) structs;
10394
10395   (* Generate C# function bindings. *)
10396   List.iter (
10397     fun (name, style, _, _, _, shortdesc, _) ->
10398       let rec csharp_return_type () =
10399         match fst style with
10400         | RErr -> "void"
10401         | RBool n -> "bool"
10402         | RInt n -> "int"
10403         | RInt64 n -> "long"
10404         | RConstString n
10405         | RConstOptString n
10406         | RString n
10407         | RBufferOut n -> "string"
10408         | RStruct (_,n) -> "_" ^ n
10409         | RHashtable n -> "Hashtable"
10410         | RStringList n -> "string[]"
10411         | RStructList (_,n) -> sprintf "_%s[]" n
10412
10413       and c_return_type () =
10414         match fst style with
10415         | RErr
10416         | RBool _
10417         | RInt _ -> "int"
10418         | RInt64 _ -> "long"
10419         | RConstString _
10420         | RConstOptString _
10421         | RString _
10422         | RBufferOut _ -> "string"
10423         | RStruct (_,n) -> "_" ^ n
10424         | RHashtable _
10425         | RStringList _ -> "string[]"
10426         | RStructList (_,n) -> sprintf "_%s[]" n
10427
10428       and c_error_comparison () =
10429         match fst style with
10430         | RErr
10431         | RBool _
10432         | RInt _
10433         | RInt64 _ -> "== -1"
10434         | RConstString _
10435         | RConstOptString _
10436         | RString _
10437         | RBufferOut _
10438         | RStruct (_,_)
10439         | RHashtable _
10440         | RStringList _
10441         | RStructList (_,_) -> "== null"
10442
10443       and generate_extern_prototype () =
10444         pr "    static extern %s guestfs_%s (IntPtr h"
10445           (c_return_type ()) name;
10446         List.iter (
10447           function
10448           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10449           | FileIn n | FileOut n ->
10450               pr ", [In] string %s" n
10451           | StringList n | DeviceList n ->
10452               pr ", [In] string[] %s" n
10453           | Bool n ->
10454               pr ", bool %s" n
10455           | Int n ->
10456               pr ", int %s" n
10457           | Int64 n ->
10458               pr ", long %s" n
10459         ) (snd style);
10460         pr ");\n"
10461
10462       and generate_public_prototype () =
10463         pr "    public %s %s (" (csharp_return_type ()) name;
10464         let comma = ref false in
10465         let next () =
10466           if !comma then pr ", ";
10467           comma := true
10468         in
10469         List.iter (
10470           function
10471           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10472           | FileIn n | FileOut n ->
10473               next (); pr "string %s" n
10474           | StringList n | DeviceList n ->
10475               next (); pr "string[] %s" n
10476           | Bool n ->
10477               next (); pr "bool %s" n
10478           | Int n ->
10479               next (); pr "int %s" n
10480           | Int64 n ->
10481               next (); pr "long %s" n
10482         ) (snd style);
10483         pr ")\n"
10484
10485       and generate_call () =
10486         pr "guestfs_%s (_handle" name;
10487         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10488         pr ");\n";
10489       in
10490
10491       pr "    [DllImport (\"%s\")]\n" library;
10492       generate_extern_prototype ();
10493       pr "\n";
10494       pr "    /// <summary>\n";
10495       pr "    /// %s\n" shortdesc;
10496       pr "    /// </summary>\n";
10497       generate_public_prototype ();
10498       pr "    {\n";
10499       pr "      %s r;\n" (c_return_type ());
10500       pr "      r = ";
10501       generate_call ();
10502       pr "      if (r %s)\n" (c_error_comparison ());
10503       pr "        throw new Error (guestfs_last_error (_handle));\n";
10504       (match fst style with
10505        | RErr -> ()
10506        | RBool _ ->
10507            pr "      return r != 0 ? true : false;\n"
10508        | RHashtable _ ->
10509            pr "      Hashtable rr = new Hashtable ();\n";
10510            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10511            pr "        rr.Add (r[i], r[i+1]);\n";
10512            pr "      return rr;\n"
10513        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10514        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10515        | RStructList _ ->
10516            pr "      return r;\n"
10517       );
10518       pr "    }\n";
10519       pr "\n";
10520   ) all_functions_sorted;
10521
10522   pr "  }
10523 }
10524 "
10525
10526 and generate_bindtests () =
10527   generate_header CStyle LGPLv2plus;
10528
10529   pr "\
10530 #include <stdio.h>
10531 #include <stdlib.h>
10532 #include <inttypes.h>
10533 #include <string.h>
10534
10535 #include \"guestfs.h\"
10536 #include \"guestfs-internal.h\"
10537 #include \"guestfs-internal-actions.h\"
10538 #include \"guestfs_protocol.h\"
10539
10540 #define error guestfs_error
10541 #define safe_calloc guestfs_safe_calloc
10542 #define safe_malloc guestfs_safe_malloc
10543
10544 static void
10545 print_strings (char *const *argv)
10546 {
10547   int argc;
10548
10549   printf (\"[\");
10550   for (argc = 0; argv[argc] != NULL; ++argc) {
10551     if (argc > 0) printf (\", \");
10552     printf (\"\\\"%%s\\\"\", argv[argc]);
10553   }
10554   printf (\"]\\n\");
10555 }
10556
10557 /* The test0 function prints its parameters to stdout. */
10558 ";
10559
10560   let test0, tests =
10561     match test_functions with
10562     | [] -> assert false
10563     | test0 :: tests -> test0, tests in
10564
10565   let () =
10566     let (name, style, _, _, _, _, _) = test0 in
10567     generate_prototype ~extern:false ~semicolon:false ~newline:true
10568       ~handle:"g" ~prefix:"guestfs__" name style;
10569     pr "{\n";
10570     List.iter (
10571       function
10572       | Pathname n
10573       | Device n | Dev_or_Path n
10574       | String n
10575       | FileIn n
10576       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10577       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10578       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10579       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10580       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10581       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10582     ) (snd style);
10583     pr "  /* Java changes stdout line buffering so we need this: */\n";
10584     pr "  fflush (stdout);\n";
10585     pr "  return 0;\n";
10586     pr "}\n";
10587     pr "\n" in
10588
10589   List.iter (
10590     fun (name, style, _, _, _, _, _) ->
10591       if String.sub name (String.length name - 3) 3 <> "err" then (
10592         pr "/* Test normal return. */\n";
10593         generate_prototype ~extern:false ~semicolon:false ~newline:true
10594           ~handle:"g" ~prefix:"guestfs__" name style;
10595         pr "{\n";
10596         (match fst style with
10597          | RErr ->
10598              pr "  return 0;\n"
10599          | RInt _ ->
10600              pr "  int r;\n";
10601              pr "  sscanf (val, \"%%d\", &r);\n";
10602              pr "  return r;\n"
10603          | RInt64 _ ->
10604              pr "  int64_t r;\n";
10605              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10606              pr "  return r;\n"
10607          | RBool _ ->
10608              pr "  return STREQ (val, \"true\");\n"
10609          | RConstString _
10610          | RConstOptString _ ->
10611              (* Can't return the input string here.  Return a static
10612               * string so we ensure we get a segfault if the caller
10613               * tries to free it.
10614               *)
10615              pr "  return \"static string\";\n"
10616          | RString _ ->
10617              pr "  return strdup (val);\n"
10618          | RStringList _ ->
10619              pr "  char **strs;\n";
10620              pr "  int n, i;\n";
10621              pr "  sscanf (val, \"%%d\", &n);\n";
10622              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10623              pr "  for (i = 0; i < n; ++i) {\n";
10624              pr "    strs[i] = safe_malloc (g, 16);\n";
10625              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10626              pr "  }\n";
10627              pr "  strs[n] = NULL;\n";
10628              pr "  return strs;\n"
10629          | RStruct (_, typ) ->
10630              pr "  struct guestfs_%s *r;\n" typ;
10631              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10632              pr "  return r;\n"
10633          | RStructList (_, typ) ->
10634              pr "  struct guestfs_%s_list *r;\n" typ;
10635              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10636              pr "  sscanf (val, \"%%d\", &r->len);\n";
10637              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10638              pr "  return r;\n"
10639          | RHashtable _ ->
10640              pr "  char **strs;\n";
10641              pr "  int n, i;\n";
10642              pr "  sscanf (val, \"%%d\", &n);\n";
10643              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10644              pr "  for (i = 0; i < n; ++i) {\n";
10645              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10646              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10647              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10648              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10649              pr "  }\n";
10650              pr "  strs[n*2] = NULL;\n";
10651              pr "  return strs;\n"
10652          | RBufferOut _ ->
10653              pr "  return strdup (val);\n"
10654         );
10655         pr "}\n";
10656         pr "\n"
10657       ) else (
10658         pr "/* Test error return. */\n";
10659         generate_prototype ~extern:false ~semicolon:false ~newline:true
10660           ~handle:"g" ~prefix:"guestfs__" name style;
10661         pr "{\n";
10662         pr "  error (g, \"error\");\n";
10663         (match fst style with
10664          | RErr | RInt _ | RInt64 _ | RBool _ ->
10665              pr "  return -1;\n"
10666          | RConstString _ | RConstOptString _
10667          | RString _ | RStringList _ | RStruct _
10668          | RStructList _
10669          | RHashtable _
10670          | RBufferOut _ ->
10671              pr "  return NULL;\n"
10672         );
10673         pr "}\n";
10674         pr "\n"
10675       )
10676   ) tests
10677
10678 and generate_ocaml_bindtests () =
10679   generate_header OCamlStyle GPLv2plus;
10680
10681   pr "\
10682 let () =
10683   let g = Guestfs.create () in
10684 ";
10685
10686   let mkargs args =
10687     String.concat " " (
10688       List.map (
10689         function
10690         | CallString s -> "\"" ^ s ^ "\""
10691         | CallOptString None -> "None"
10692         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10693         | CallStringList xs ->
10694             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10695         | CallInt i when i >= 0 -> string_of_int i
10696         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10697         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10698         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10699         | CallBool b -> string_of_bool b
10700       ) args
10701     )
10702   in
10703
10704   generate_lang_bindtests (
10705     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10706   );
10707
10708   pr "print_endline \"EOF\"\n"
10709
10710 and generate_perl_bindtests () =
10711   pr "#!/usr/bin/perl -w\n";
10712   generate_header HashStyle GPLv2plus;
10713
10714   pr "\
10715 use strict;
10716
10717 use Sys::Guestfs;
10718
10719 my $g = Sys::Guestfs->new ();
10720 ";
10721
10722   let mkargs args =
10723     String.concat ", " (
10724       List.map (
10725         function
10726         | CallString s -> "\"" ^ s ^ "\""
10727         | CallOptString None -> "undef"
10728         | CallOptString (Some s) -> sprintf "\"%s\"" s
10729         | CallStringList xs ->
10730             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10731         | CallInt i -> string_of_int i
10732         | CallInt64 i -> Int64.to_string i
10733         | CallBool b -> if b then "1" else "0"
10734       ) args
10735     )
10736   in
10737
10738   generate_lang_bindtests (
10739     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10740   );
10741
10742   pr "print \"EOF\\n\"\n"
10743
10744 and generate_python_bindtests () =
10745   generate_header HashStyle GPLv2plus;
10746
10747   pr "\
10748 import guestfs
10749
10750 g = guestfs.GuestFS ()
10751 ";
10752
10753   let mkargs args =
10754     String.concat ", " (
10755       List.map (
10756         function
10757         | CallString s -> "\"" ^ s ^ "\""
10758         | CallOptString None -> "None"
10759         | CallOptString (Some s) -> sprintf "\"%s\"" s
10760         | CallStringList xs ->
10761             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10762         | CallInt i -> string_of_int i
10763         | CallInt64 i -> Int64.to_string i
10764         | CallBool b -> if b then "1" else "0"
10765       ) args
10766     )
10767   in
10768
10769   generate_lang_bindtests (
10770     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10771   );
10772
10773   pr "print \"EOF\"\n"
10774
10775 and generate_ruby_bindtests () =
10776   generate_header HashStyle GPLv2plus;
10777
10778   pr "\
10779 require 'guestfs'
10780
10781 g = Guestfs::create()
10782 ";
10783
10784   let mkargs args =
10785     String.concat ", " (
10786       List.map (
10787         function
10788         | CallString s -> "\"" ^ s ^ "\""
10789         | CallOptString None -> "nil"
10790         | CallOptString (Some s) -> sprintf "\"%s\"" s
10791         | CallStringList xs ->
10792             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10793         | CallInt i -> string_of_int i
10794         | CallInt64 i -> Int64.to_string i
10795         | CallBool b -> string_of_bool b
10796       ) args
10797     )
10798   in
10799
10800   generate_lang_bindtests (
10801     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10802   );
10803
10804   pr "print \"EOF\\n\"\n"
10805
10806 and generate_java_bindtests () =
10807   generate_header CStyle GPLv2plus;
10808
10809   pr "\
10810 import com.redhat.et.libguestfs.*;
10811
10812 public class Bindtests {
10813     public static void main (String[] argv)
10814     {
10815         try {
10816             GuestFS g = new GuestFS ();
10817 ";
10818
10819   let mkargs args =
10820     String.concat ", " (
10821       List.map (
10822         function
10823         | CallString s -> "\"" ^ s ^ "\""
10824         | CallOptString None -> "null"
10825         | CallOptString (Some s) -> sprintf "\"%s\"" s
10826         | CallStringList xs ->
10827             "new String[]{" ^
10828               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10829         | CallInt i -> string_of_int i
10830         | CallInt64 i -> Int64.to_string i
10831         | CallBool b -> string_of_bool b
10832       ) args
10833     )
10834   in
10835
10836   generate_lang_bindtests (
10837     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10838   );
10839
10840   pr "
10841             System.out.println (\"EOF\");
10842         }
10843         catch (Exception exn) {
10844             System.err.println (exn);
10845             System.exit (1);
10846         }
10847     }
10848 }
10849 "
10850
10851 and generate_haskell_bindtests () =
10852   generate_header HaskellStyle GPLv2plus;
10853
10854   pr "\
10855 module Bindtests where
10856 import qualified Guestfs
10857
10858 main = do
10859   g <- Guestfs.create
10860 ";
10861
10862   let mkargs args =
10863     String.concat " " (
10864       List.map (
10865         function
10866         | CallString s -> "\"" ^ s ^ "\""
10867         | CallOptString None -> "Nothing"
10868         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10869         | CallStringList xs ->
10870             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10871         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10872         | CallInt i -> string_of_int i
10873         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10874         | CallInt64 i -> Int64.to_string i
10875         | CallBool true -> "True"
10876         | CallBool false -> "False"
10877       ) args
10878     )
10879   in
10880
10881   generate_lang_bindtests (
10882     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10883   );
10884
10885   pr "  putStrLn \"EOF\"\n"
10886
10887 (* Language-independent bindings tests - we do it this way to
10888  * ensure there is parity in testing bindings across all languages.
10889  *)
10890 and generate_lang_bindtests call =
10891   call "test0" [CallString "abc"; CallOptString (Some "def");
10892                 CallStringList []; CallBool false;
10893                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10894   call "test0" [CallString "abc"; CallOptString None;
10895                 CallStringList []; CallBool false;
10896                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10897   call "test0" [CallString ""; CallOptString (Some "def");
10898                 CallStringList []; CallBool false;
10899                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10900   call "test0" [CallString ""; CallOptString (Some "");
10901                 CallStringList []; CallBool false;
10902                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10903   call "test0" [CallString "abc"; CallOptString (Some "def");
10904                 CallStringList ["1"]; CallBool false;
10905                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10906   call "test0" [CallString "abc"; CallOptString (Some "def");
10907                 CallStringList ["1"; "2"]; CallBool false;
10908                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10909   call "test0" [CallString "abc"; CallOptString (Some "def");
10910                 CallStringList ["1"]; CallBool true;
10911                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10912   call "test0" [CallString "abc"; CallOptString (Some "def");
10913                 CallStringList ["1"]; CallBool false;
10914                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10915   call "test0" [CallString "abc"; CallOptString (Some "def");
10916                 CallStringList ["1"]; CallBool false;
10917                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10918   call "test0" [CallString "abc"; CallOptString (Some "def");
10919                 CallStringList ["1"]; CallBool false;
10920                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10921   call "test0" [CallString "abc"; CallOptString (Some "def");
10922                 CallStringList ["1"]; CallBool false;
10923                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10924   call "test0" [CallString "abc"; CallOptString (Some "def");
10925                 CallStringList ["1"]; CallBool false;
10926                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10927   call "test0" [CallString "abc"; CallOptString (Some "def");
10928                 CallStringList ["1"]; CallBool false;
10929                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10930
10931 (* XXX Add here tests of the return and error functions. *)
10932
10933 (* Code to generator bindings for virt-inspector.  Currently only
10934  * implemented for OCaml code (for virt-p2v 2.0).
10935  *)
10936 let rng_input = "inspector/virt-inspector.rng"
10937
10938 (* Read the input file and parse it into internal structures.  This is
10939  * by no means a complete RELAX NG parser, but is just enough to be
10940  * able to parse the specific input file.
10941  *)
10942 type rng =
10943   | Element of string * rng list        (* <element name=name/> *)
10944   | Attribute of string * rng list        (* <attribute name=name/> *)
10945   | Interleave of rng list                (* <interleave/> *)
10946   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10947   | OneOrMore of rng                        (* <oneOrMore/> *)
10948   | Optional of rng                        (* <optional/> *)
10949   | Choice of string list                (* <choice><value/>*</choice> *)
10950   | Value of string                        (* <value>str</value> *)
10951   | Text                                (* <text/> *)
10952
10953 let rec string_of_rng = function
10954   | Element (name, xs) ->
10955       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10956   | Attribute (name, xs) ->
10957       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10958   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10959   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10960   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10961   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10962   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10963   | Value value -> "Value \"" ^ value ^ "\""
10964   | Text -> "Text"
10965
10966 and string_of_rng_list xs =
10967   String.concat ", " (List.map string_of_rng xs)
10968
10969 let rec parse_rng ?defines context = function
10970   | [] -> []
10971   | Xml.Element ("element", ["name", name], children) :: rest ->
10972       Element (name, parse_rng ?defines context children)
10973       :: parse_rng ?defines context rest
10974   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10975       Attribute (name, parse_rng ?defines context children)
10976       :: parse_rng ?defines context rest
10977   | Xml.Element ("interleave", [], children) :: rest ->
10978       Interleave (parse_rng ?defines context children)
10979       :: parse_rng ?defines context rest
10980   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10981       let rng = parse_rng ?defines context [child] in
10982       (match rng with
10983        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10984        | _ ->
10985            failwithf "%s: <zeroOrMore> contains more than one child element"
10986              context
10987       )
10988   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10989       let rng = parse_rng ?defines context [child] in
10990       (match rng with
10991        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10992        | _ ->
10993            failwithf "%s: <oneOrMore> contains more than one child element"
10994              context
10995       )
10996   | Xml.Element ("optional", [], [child]) :: rest ->
10997       let rng = parse_rng ?defines context [child] in
10998       (match rng with
10999        | [child] -> Optional child :: parse_rng ?defines context rest
11000        | _ ->
11001            failwithf "%s: <optional> contains more than one child element"
11002              context
11003       )
11004   | Xml.Element ("choice", [], children) :: rest ->
11005       let values = List.map (
11006         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11007         | _ ->
11008             failwithf "%s: can't handle anything except <value> in <choice>"
11009               context
11010       ) children in
11011       Choice values
11012       :: parse_rng ?defines context rest
11013   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11014       Value value :: parse_rng ?defines context rest
11015   | Xml.Element ("text", [], []) :: rest ->
11016       Text :: parse_rng ?defines context rest
11017   | Xml.Element ("ref", ["name", name], []) :: rest ->
11018       (* Look up the reference.  Because of limitations in this parser,
11019        * we can't handle arbitrarily nested <ref> yet.  You can only
11020        * use <ref> from inside <start>.
11021        *)
11022       (match defines with
11023        | None ->
11024            failwithf "%s: contains <ref>, but no refs are defined yet" context
11025        | Some map ->
11026            let rng = StringMap.find name map in
11027            rng @ parse_rng ?defines context rest
11028       )
11029   | x :: _ ->
11030       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11031
11032 let grammar =
11033   let xml = Xml.parse_file rng_input in
11034   match xml with
11035   | Xml.Element ("grammar", _,
11036                  Xml.Element ("start", _, gram) :: defines) ->
11037       (* The <define/> elements are referenced in the <start> section,
11038        * so build a map of those first.
11039        *)
11040       let defines = List.fold_left (
11041         fun map ->
11042           function Xml.Element ("define", ["name", name], defn) ->
11043             StringMap.add name defn map
11044           | _ ->
11045               failwithf "%s: expected <define name=name/>" rng_input
11046       ) StringMap.empty defines in
11047       let defines = StringMap.mapi parse_rng defines in
11048
11049       (* Parse the <start> clause, passing the defines. *)
11050       parse_rng ~defines "<start>" gram
11051   | _ ->
11052       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11053         rng_input
11054
11055 let name_of_field = function
11056   | Element (name, _) | Attribute (name, _)
11057   | ZeroOrMore (Element (name, _))
11058   | OneOrMore (Element (name, _))
11059   | Optional (Element (name, _)) -> name
11060   | Optional (Attribute (name, _)) -> name
11061   | Text -> (* an unnamed field in an element *)
11062       "data"
11063   | rng ->
11064       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11065
11066 (* At the moment this function only generates OCaml types.  However we
11067  * should parameterize it later so it can generate types/structs in a
11068  * variety of languages.
11069  *)
11070 let generate_types xs =
11071   (* A simple type is one that can be printed out directly, eg.
11072    * "string option".  A complex type is one which has a name and has
11073    * to be defined via another toplevel definition, eg. a struct.
11074    *
11075    * generate_type generates code for either simple or complex types.
11076    * In the simple case, it returns the string ("string option").  In
11077    * the complex case, it returns the name ("mountpoint").  In the
11078    * complex case it has to print out the definition before returning,
11079    * so it should only be called when we are at the beginning of a
11080    * new line (BOL context).
11081    *)
11082   let rec generate_type = function
11083     | Text ->                                (* string *)
11084         "string", true
11085     | Choice values ->                        (* [`val1|`val2|...] *)
11086         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11087     | ZeroOrMore rng ->                        (* <rng> list *)
11088         let t, is_simple = generate_type rng in
11089         t ^ " list (* 0 or more *)", is_simple
11090     | OneOrMore rng ->                        (* <rng> list *)
11091         let t, is_simple = generate_type rng in
11092         t ^ " list (* 1 or more *)", is_simple
11093                                         (* virt-inspector hack: bool *)
11094     | Optional (Attribute (name, [Value "1"])) ->
11095         "bool", true
11096     | Optional rng ->                        (* <rng> list *)
11097         let t, is_simple = generate_type rng in
11098         t ^ " option", is_simple
11099                                         (* type name = { fields ... } *)
11100     | Element (name, fields) when is_attrs_interleave fields ->
11101         generate_type_struct name (get_attrs_interleave fields)
11102     | Element (name, [field])                (* type name = field *)
11103     | Attribute (name, [field]) ->
11104         let t, is_simple = generate_type field in
11105         if is_simple then (t, true)
11106         else (
11107           pr "type %s = %s\n" name t;
11108           name, false
11109         )
11110     | Element (name, fields) ->              (* type name = { fields ... } *)
11111         generate_type_struct name fields
11112     | rng ->
11113         failwithf "generate_type failed at: %s" (string_of_rng rng)
11114
11115   and is_attrs_interleave = function
11116     | [Interleave _] -> true
11117     | Attribute _ :: fields -> is_attrs_interleave fields
11118     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11119     | _ -> false
11120
11121   and get_attrs_interleave = function
11122     | [Interleave fields] -> fields
11123     | ((Attribute _) as field) :: fields
11124     | ((Optional (Attribute _)) as field) :: fields ->
11125         field :: get_attrs_interleave fields
11126     | _ -> assert false
11127
11128   and generate_types xs =
11129     List.iter (fun x -> ignore (generate_type x)) xs
11130
11131   and generate_type_struct name fields =
11132     (* Calculate the types of the fields first.  We have to do this
11133      * before printing anything so we are still in BOL context.
11134      *)
11135     let types = List.map fst (List.map generate_type fields) in
11136
11137     (* Special case of a struct containing just a string and another
11138      * field.  Turn it into an assoc list.
11139      *)
11140     match types with
11141     | ["string"; other] ->
11142         let fname1, fname2 =
11143           match fields with
11144           | [f1; f2] -> name_of_field f1, name_of_field f2
11145           | _ -> assert false in
11146         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11147         name, false
11148
11149     | types ->
11150         pr "type %s = {\n" name;
11151         List.iter (
11152           fun (field, ftype) ->
11153             let fname = name_of_field field in
11154             pr "  %s_%s : %s;\n" name fname ftype
11155         ) (List.combine fields types);
11156         pr "}\n";
11157         (* Return the name of this type, and
11158          * false because it's not a simple type.
11159          *)
11160         name, false
11161   in
11162
11163   generate_types xs
11164
11165 let generate_parsers xs =
11166   (* As for generate_type above, generate_parser makes a parser for
11167    * some type, and returns the name of the parser it has generated.
11168    * Because it (may) need to print something, it should always be
11169    * called in BOL context.
11170    *)
11171   let rec generate_parser = function
11172     | Text ->                                (* string *)
11173         "string_child_or_empty"
11174     | Choice values ->                        (* [`val1|`val2|...] *)
11175         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11176           (String.concat "|"
11177              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11178     | ZeroOrMore rng ->                        (* <rng> list *)
11179         let pa = generate_parser rng in
11180         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11181     | OneOrMore rng ->                        (* <rng> list *)
11182         let pa = generate_parser rng in
11183         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11184                                         (* virt-inspector hack: bool *)
11185     | Optional (Attribute (name, [Value "1"])) ->
11186         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11187     | Optional rng ->                        (* <rng> list *)
11188         let pa = generate_parser rng in
11189         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11190                                         (* type name = { fields ... } *)
11191     | Element (name, fields) when is_attrs_interleave fields ->
11192         generate_parser_struct name (get_attrs_interleave fields)
11193     | Element (name, [field]) ->        (* type name = field *)
11194         let pa = generate_parser field in
11195         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11196         pr "let %s =\n" parser_name;
11197         pr "  %s\n" pa;
11198         pr "let parse_%s = %s\n" name parser_name;
11199         parser_name
11200     | Attribute (name, [field]) ->
11201         let pa = generate_parser field in
11202         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11203         pr "let %s =\n" parser_name;
11204         pr "  %s\n" pa;
11205         pr "let parse_%s = %s\n" name parser_name;
11206         parser_name
11207     | Element (name, fields) ->              (* type name = { fields ... } *)
11208         generate_parser_struct name ([], fields)
11209     | rng ->
11210         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11211
11212   and is_attrs_interleave = function
11213     | [Interleave _] -> true
11214     | Attribute _ :: fields -> is_attrs_interleave fields
11215     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11216     | _ -> false
11217
11218   and get_attrs_interleave = function
11219     | [Interleave fields] -> [], fields
11220     | ((Attribute _) as field) :: fields
11221     | ((Optional (Attribute _)) as field) :: fields ->
11222         let attrs, interleaves = get_attrs_interleave fields in
11223         (field :: attrs), interleaves
11224     | _ -> assert false
11225
11226   and generate_parsers xs =
11227     List.iter (fun x -> ignore (generate_parser x)) xs
11228
11229   and generate_parser_struct name (attrs, interleaves) =
11230     (* Generate parsers for the fields first.  We have to do this
11231      * before printing anything so we are still in BOL context.
11232      *)
11233     let fields = attrs @ interleaves in
11234     let pas = List.map generate_parser fields in
11235
11236     (* Generate an intermediate tuple from all the fields first.
11237      * If the type is just a string + another field, then we will
11238      * return this directly, otherwise it is turned into a record.
11239      *
11240      * RELAX NG note: This code treats <interleave> and plain lists of
11241      * fields the same.  In other words, it doesn't bother enforcing
11242      * any ordering of fields in the XML.
11243      *)
11244     pr "let parse_%s x =\n" name;
11245     pr "  let t = (\n    ";
11246     let comma = ref false in
11247     List.iter (
11248       fun x ->
11249         if !comma then pr ",\n    ";
11250         comma := true;
11251         match x with
11252         | Optional (Attribute (fname, [field])), pa ->
11253             pr "%s x" pa
11254         | Optional (Element (fname, [field])), pa ->
11255             pr "%s (optional_child %S x)" pa fname
11256         | Attribute (fname, [Text]), _ ->
11257             pr "attribute %S x" fname
11258         | (ZeroOrMore _ | OneOrMore _), pa ->
11259             pr "%s x" pa
11260         | Text, pa ->
11261             pr "%s x" pa
11262         | (field, pa) ->
11263             let fname = name_of_field field in
11264             pr "%s (child %S x)" pa fname
11265     ) (List.combine fields pas);
11266     pr "\n  ) in\n";
11267
11268     (match fields with
11269      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11270          pr "  t\n"
11271
11272      | _ ->
11273          pr "  (Obj.magic t : %s)\n" name
11274 (*
11275          List.iter (
11276            function
11277            | (Optional (Attribute (fname, [field])), pa) ->
11278                pr "  %s_%s =\n" name fname;
11279                pr "    %s x;\n" pa
11280            | (Optional (Element (fname, [field])), pa) ->
11281                pr "  %s_%s =\n" name fname;
11282                pr "    (let x = optional_child %S x in\n" fname;
11283                pr "     %s x);\n" pa
11284            | (field, pa) ->
11285                let fname = name_of_field field in
11286                pr "  %s_%s =\n" name fname;
11287                pr "    (let x = child %S x in\n" fname;
11288                pr "     %s x);\n" pa
11289          ) (List.combine fields pas);
11290          pr "}\n"
11291 *)
11292     );
11293     sprintf "parse_%s" name
11294   in
11295
11296   generate_parsers xs
11297
11298 (* Generate ocaml/guestfs_inspector.mli. *)
11299 let generate_ocaml_inspector_mli () =
11300   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11301
11302   pr "\
11303 (** This is an OCaml language binding to the external [virt-inspector]
11304     program.
11305
11306     For more information, please read the man page [virt-inspector(1)].
11307 *)
11308
11309 ";
11310
11311   generate_types grammar;
11312   pr "(** The nested information returned from the {!inspect} function. *)\n";
11313   pr "\n";
11314
11315   pr "\
11316 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11317 (** To inspect a libvirt domain called [name], pass a singleton
11318     list: [inspect [name]].  When using libvirt only, you may
11319     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11320
11321     To inspect a disk image or images, pass a list of the filenames
11322     of the disk images: [inspect filenames]
11323
11324     This function inspects the given guest or disk images and
11325     returns a list of operating system(s) found and a large amount
11326     of information about them.  In the vast majority of cases,
11327     a virtual machine only contains a single operating system.
11328
11329     If the optional [~xml] parameter is given, then this function
11330     skips running the external virt-inspector program and just
11331     parses the given XML directly (which is expected to be XML
11332     produced from a previous run of virt-inspector).  The list of
11333     names and connect URI are ignored in this case.
11334
11335     This function can throw a wide variety of exceptions, for example
11336     if the external virt-inspector program cannot be found, or if
11337     it doesn't generate valid XML.
11338 *)
11339 "
11340
11341 (* Generate ocaml/guestfs_inspector.ml. *)
11342 let generate_ocaml_inspector_ml () =
11343   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11344
11345   pr "open Unix\n";
11346   pr "\n";
11347
11348   generate_types grammar;
11349   pr "\n";
11350
11351   pr "\
11352 (* Misc functions which are used by the parser code below. *)
11353 let first_child = function
11354   | Xml.Element (_, _, c::_) -> c
11355   | Xml.Element (name, _, []) ->
11356       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11357   | Xml.PCData str ->
11358       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11359
11360 let string_child_or_empty = function
11361   | Xml.Element (_, _, [Xml.PCData s]) -> s
11362   | Xml.Element (_, _, []) -> \"\"
11363   | Xml.Element (x, _, _) ->
11364       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11365                 x ^ \" instead\")
11366   | Xml.PCData str ->
11367       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11368
11369 let optional_child name xml =
11370   let children = Xml.children xml in
11371   try
11372     Some (List.find (function
11373                      | Xml.Element (n, _, _) when n = name -> true
11374                      | _ -> false) children)
11375   with
11376     Not_found -> None
11377
11378 let child name xml =
11379   match optional_child name xml with
11380   | Some c -> c
11381   | None ->
11382       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11383
11384 let attribute name xml =
11385   try Xml.attrib xml name
11386   with Xml.No_attribute _ ->
11387     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11388
11389 ";
11390
11391   generate_parsers grammar;
11392   pr "\n";
11393
11394   pr "\
11395 (* Run external virt-inspector, then use parser to parse the XML. *)
11396 let inspect ?connect ?xml names =
11397   let xml =
11398     match xml with
11399     | None ->
11400         if names = [] then invalid_arg \"inspect: no names given\";
11401         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11402           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11403           names in
11404         let cmd = List.map Filename.quote cmd in
11405         let cmd = String.concat \" \" cmd in
11406         let chan = open_process_in cmd in
11407         let xml = Xml.parse_in chan in
11408         (match close_process_in chan with
11409          | WEXITED 0 -> ()
11410          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11411          | WSIGNALED i | WSTOPPED i ->
11412              failwith (\"external virt-inspector command died or stopped on sig \" ^
11413                        string_of_int i)
11414         );
11415         xml
11416     | Some doc ->
11417         Xml.parse_string doc in
11418   parse_operatingsystems xml
11419 "
11420
11421 (* This is used to generate the src/MAX_PROC_NR file which
11422  * contains the maximum procedure number, a surrogate for the
11423  * ABI version number.  See src/Makefile.am for the details.
11424  *)
11425 and generate_max_proc_nr () =
11426   let proc_nrs = List.map (
11427     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11428   ) daemon_functions in
11429
11430   let max_proc_nr = List.fold_left max 0 proc_nrs in
11431
11432   pr "%d\n" max_proc_nr
11433
11434 let output_to filename k =
11435   let filename_new = filename ^ ".new" in
11436   chan := open_out filename_new;
11437   k ();
11438   close_out !chan;
11439   chan := Pervasives.stdout;
11440
11441   (* Is the new file different from the current file? *)
11442   if Sys.file_exists filename && files_equal filename filename_new then
11443     unlink filename_new                 (* same, so skip it *)
11444   else (
11445     (* different, overwrite old one *)
11446     (try chmod filename 0o644 with Unix_error _ -> ());
11447     rename filename_new filename;
11448     chmod filename 0o444;
11449     printf "written %s\n%!" filename;
11450   )
11451
11452 let perror msg = function
11453   | Unix_error (err, _, _) ->
11454       eprintf "%s: %s\n" msg (error_message err)
11455   | exn ->
11456       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11457
11458 (* Main program. *)
11459 let () =
11460   let lock_fd =
11461     try openfile "HACKING" [O_RDWR] 0
11462     with
11463     | Unix_error (ENOENT, _, _) ->
11464         eprintf "\
11465 You are probably running this from the wrong directory.
11466 Run it from the top source directory using the command
11467   src/generator.ml
11468 ";
11469         exit 1
11470     | exn ->
11471         perror "open: HACKING" exn;
11472         exit 1 in
11473
11474   (* Acquire a lock so parallel builds won't try to run the generator
11475    * twice at the same time.  Subsequent builds will wait for the first
11476    * one to finish.  Note the lock is released implicitly when the
11477    * program exits.
11478    *)
11479   (try lockf lock_fd F_LOCK 1
11480    with exn ->
11481      perror "lock: HACKING" exn;
11482      exit 1);
11483
11484   check_functions ();
11485
11486   output_to "src/guestfs_protocol.x" generate_xdr;
11487   output_to "src/guestfs-structs.h" generate_structs_h;
11488   output_to "src/guestfs-actions.h" generate_actions_h;
11489   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11490   output_to "src/guestfs-actions.c" generate_client_actions;
11491   output_to "src/guestfs-bindtests.c" generate_bindtests;
11492   output_to "src/guestfs-structs.pod" generate_structs_pod;
11493   output_to "src/guestfs-actions.pod" generate_actions_pod;
11494   output_to "src/guestfs-availability.pod" generate_availability_pod;
11495   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11496   output_to "src/libguestfs.syms" generate_linker_script;
11497   output_to "daemon/actions.h" generate_daemon_actions_h;
11498   output_to "daemon/stubs.c" generate_daemon_actions;
11499   output_to "daemon/names.c" generate_daemon_names;
11500   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11501   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11502   output_to "capitests/tests.c" generate_tests;
11503   output_to "fish/cmds.c" generate_fish_cmds;
11504   output_to "fish/completion.c" generate_fish_completion;
11505   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11506   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11507   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11508   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11509   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11510   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11511   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11512   output_to "perl/Guestfs.xs" generate_perl_xs;
11513   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11514   output_to "perl/bindtests.pl" generate_perl_bindtests;
11515   output_to "python/guestfs-py.c" generate_python_c;
11516   output_to "python/guestfs.py" generate_python_py;
11517   output_to "python/bindtests.py" generate_python_bindtests;
11518   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11519   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11520   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11521
11522   List.iter (
11523     fun (typ, jtyp) ->
11524       let cols = cols_of_struct typ in
11525       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11526       output_to filename (generate_java_struct jtyp cols);
11527   ) java_structs;
11528
11529   output_to "java/Makefile.inc" generate_java_makefile_inc;
11530   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11531   output_to "java/Bindtests.java" generate_java_bindtests;
11532   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11533   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11534   output_to "csharp/Libguestfs.cs" generate_csharp;
11535
11536   (* Always generate this file last, and unconditionally.  It's used
11537    * by the Makefile to know when we must re-run the generator.
11538    *)
11539   let chan = open_out "src/stamp-generator" in
11540   fprintf chan "1\n";
11541   close_out chan;
11542
11543   printf "generated %d lines of code\n" !lines