Documentation: Use 'g' instead of 'handle' in documentation.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.
1384
1385 The mode actually set is affected by the umask.");
1386
1387   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1388    [], (* XXX Need stat command to test *)
1389    "change file owner and group",
1390    "\
1391 Change the file owner to C<owner> and group to C<group>.
1392
1393 Only numeric uid and gid are supported.  If you want to use
1394 names, you will need to locate and parse the password file
1395 yourself (Augeas support makes this relatively easy).");
1396
1397   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1398    [InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/empty"]]);
1400     InitISOFS, Always, TestOutputTrue (
1401       [["exists"; "/directory"]])],
1402    "test if file or directory exists",
1403    "\
1404 This returns C<true> if and only if there is a file, directory
1405 (or anything) with the given C<path> name.
1406
1407 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1408
1409   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1410    [InitISOFS, Always, TestOutputTrue (
1411       [["is_file"; "/known-1"]]);
1412     InitISOFS, Always, TestOutputFalse (
1413       [["is_file"; "/directory"]])],
1414    "test if file exists",
1415    "\
1416 This returns C<true> if and only if there is a file
1417 with the given C<path> name.  Note that it returns false for
1418 other objects like directories.
1419
1420 See also C<guestfs_stat>.");
1421
1422   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1423    [InitISOFS, Always, TestOutputFalse (
1424       [["is_dir"; "/known-3"]]);
1425     InitISOFS, Always, TestOutputTrue (
1426       [["is_dir"; "/directory"]])],
1427    "test if file exists",
1428    "\
1429 This returns C<true> if and only if there is a directory
1430 with the given C<path> name.  Note that it returns false for
1431 other objects like files.
1432
1433 See also C<guestfs_stat>.");
1434
1435   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1436    [InitEmpty, Always, TestOutputListOfDevices (
1437       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1438        ["pvcreate"; "/dev/sda1"];
1439        ["pvcreate"; "/dev/sda2"];
1440        ["pvcreate"; "/dev/sda3"];
1441        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1442    "create an LVM physical volume",
1443    "\
1444 This creates an LVM physical volume on the named C<device>,
1445 where C<device> should usually be a partition name such
1446 as C</dev/sda1>.");
1447
1448   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1449    [InitEmpty, Always, TestOutputList (
1450       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1451        ["pvcreate"; "/dev/sda1"];
1452        ["pvcreate"; "/dev/sda2"];
1453        ["pvcreate"; "/dev/sda3"];
1454        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1455        ["vgcreate"; "VG2"; "/dev/sda3"];
1456        ["vgs"]], ["VG1"; "VG2"])],
1457    "create an LVM volume group",
1458    "\
1459 This creates an LVM volume group called C<volgroup>
1460 from the non-empty list of physical volumes C<physvols>.");
1461
1462   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1463    [InitEmpty, Always, TestOutputList (
1464       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1465        ["pvcreate"; "/dev/sda1"];
1466        ["pvcreate"; "/dev/sda2"];
1467        ["pvcreate"; "/dev/sda3"];
1468        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1469        ["vgcreate"; "VG2"; "/dev/sda3"];
1470        ["lvcreate"; "LV1"; "VG1"; "50"];
1471        ["lvcreate"; "LV2"; "VG1"; "50"];
1472        ["lvcreate"; "LV3"; "VG2"; "50"];
1473        ["lvcreate"; "LV4"; "VG2"; "50"];
1474        ["lvcreate"; "LV5"; "VG2"; "50"];
1475        ["lvs"]],
1476       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1477        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1478    "create an LVM logical volume",
1479    "\
1480 This creates an LVM logical volume called C<logvol>
1481 on the volume group C<volgroup>, with C<size> megabytes.");
1482
1483   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1484    [InitEmpty, Always, TestOutput (
1485       [["part_disk"; "/dev/sda"; "mbr"];
1486        ["mkfs"; "ext2"; "/dev/sda1"];
1487        ["mount_options"; ""; "/dev/sda1"; "/"];
1488        ["write_file"; "/new"; "new file contents"; "0"];
1489        ["cat"; "/new"]], "new file contents")],
1490    "make a filesystem",
1491    "\
1492 This creates a filesystem on C<device> (usually a partition
1493 or LVM logical volume).  The filesystem type is C<fstype>, for
1494 example C<ext3>.");
1495
1496   ("sfdisk", (RErr, [Device "device";
1497                      Int "cyls"; Int "heads"; Int "sectors";
1498                      StringList "lines"]), 43, [DangerWillRobinson],
1499    [],
1500    "create partitions on a block device",
1501    "\
1502 This is a direct interface to the L<sfdisk(8)> program for creating
1503 partitions on block devices.
1504
1505 C<device> should be a block device, for example C</dev/sda>.
1506
1507 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1508 and sectors on the device, which are passed directly to sfdisk as
1509 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1510 of these, then the corresponding parameter is omitted.  Usually for
1511 'large' disks, you can just pass C<0> for these, but for small
1512 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1513 out the right geometry and you will need to tell it.
1514
1515 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1516 information refer to the L<sfdisk(8)> manpage.
1517
1518 To create a single partition occupying the whole disk, you would
1519 pass C<lines> as a single element list, when the single element being
1520 the string C<,> (comma).
1521
1522 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1523 C<guestfs_part_init>");
1524
1525   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1526    [InitBasicFS, Always, TestOutput (
1527       [["write_file"; "/new"; "new file contents"; "0"];
1528        ["cat"; "/new"]], "new file contents");
1529     InitBasicFS, Always, TestOutput (
1530       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1531        ["cat"; "/new"]], "\nnew file contents\n");
1532     InitBasicFS, Always, TestOutput (
1533       [["write_file"; "/new"; "\n\n"; "0"];
1534        ["cat"; "/new"]], "\n\n");
1535     InitBasicFS, Always, TestOutput (
1536       [["write_file"; "/new"; ""; "0"];
1537        ["cat"; "/new"]], "");
1538     InitBasicFS, Always, TestOutput (
1539       [["write_file"; "/new"; "\n\n\n"; "0"];
1540        ["cat"; "/new"]], "\n\n\n");
1541     InitBasicFS, Always, TestOutput (
1542       [["write_file"; "/new"; "\n"; "0"];
1543        ["cat"; "/new"]], "\n")],
1544    "create a file",
1545    "\
1546 This call creates a file called C<path>.  The contents of the
1547 file is the string C<content> (which can contain any 8 bit data),
1548 with length C<size>.
1549
1550 As a special case, if C<size> is C<0>
1551 then the length is calculated using C<strlen> (so in this case
1552 the content cannot contain embedded ASCII NULs).
1553
1554 I<NB.> Owing to a bug, writing content containing ASCII NUL
1555 characters does I<not> work, even if the length is specified.
1556 We hope to resolve this bug in a future version.  In the meantime
1557 use C<guestfs_upload>.");
1558
1559   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1560    [InitEmpty, Always, TestOutputListOfDevices (
1561       [["part_disk"; "/dev/sda"; "mbr"];
1562        ["mkfs"; "ext2"; "/dev/sda1"];
1563        ["mount_options"; ""; "/dev/sda1"; "/"];
1564        ["mounts"]], ["/dev/sda1"]);
1565     InitEmpty, Always, TestOutputList (
1566       [["part_disk"; "/dev/sda"; "mbr"];
1567        ["mkfs"; "ext2"; "/dev/sda1"];
1568        ["mount_options"; ""; "/dev/sda1"; "/"];
1569        ["umount"; "/"];
1570        ["mounts"]], [])],
1571    "unmount a filesystem",
1572    "\
1573 This unmounts the given filesystem.  The filesystem may be
1574 specified either by its mountpoint (path) or the device which
1575 contains the filesystem.");
1576
1577   ("mounts", (RStringList "devices", []), 46, [],
1578    [InitBasicFS, Always, TestOutputListOfDevices (
1579       [["mounts"]], ["/dev/sda1"])],
1580    "show mounted filesystems",
1581    "\
1582 This returns the list of currently mounted filesystems.  It returns
1583 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1584
1585 Some internal mounts are not shown.
1586
1587 See also: C<guestfs_mountpoints>");
1588
1589   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1590    [InitBasicFS, Always, TestOutputList (
1591       [["umount_all"];
1592        ["mounts"]], []);
1593     (* check that umount_all can unmount nested mounts correctly: *)
1594     InitEmpty, Always, TestOutputList (
1595       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1596        ["mkfs"; "ext2"; "/dev/sda1"];
1597        ["mkfs"; "ext2"; "/dev/sda2"];
1598        ["mkfs"; "ext2"; "/dev/sda3"];
1599        ["mount_options"; ""; "/dev/sda1"; "/"];
1600        ["mkdir"; "/mp1"];
1601        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1602        ["mkdir"; "/mp1/mp2"];
1603        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1604        ["mkdir"; "/mp1/mp2/mp3"];
1605        ["umount_all"];
1606        ["mounts"]], [])],
1607    "unmount all filesystems",
1608    "\
1609 This unmounts all mounted filesystems.
1610
1611 Some internal mounts are not unmounted by this call.");
1612
1613   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1614    [],
1615    "remove all LVM LVs, VGs and PVs",
1616    "\
1617 This command removes all LVM logical volumes, volume groups
1618 and physical volumes.");
1619
1620   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1621    [InitISOFS, Always, TestOutput (
1622       [["file"; "/empty"]], "empty");
1623     InitISOFS, Always, TestOutput (
1624       [["file"; "/known-1"]], "ASCII text");
1625     InitISOFS, Always, TestLastFail (
1626       [["file"; "/notexists"]])],
1627    "determine file type",
1628    "\
1629 This call uses the standard L<file(1)> command to determine
1630 the type or contents of the file.  This also works on devices,
1631 for example to find out whether a partition contains a filesystem.
1632
1633 This call will also transparently look inside various types
1634 of compressed file.
1635
1636 The exact command which runs is C<file -zbsL path>.  Note in
1637 particular that the filename is not prepended to the output
1638 (the C<-b> option).");
1639
1640   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1641    [InitBasicFS, Always, TestOutput (
1642       [["upload"; "test-command"; "/test-command"];
1643        ["chmod"; "0o755"; "/test-command"];
1644        ["command"; "/test-command 1"]], "Result1");
1645     InitBasicFS, Always, TestOutput (
1646       [["upload"; "test-command"; "/test-command"];
1647        ["chmod"; "0o755"; "/test-command"];
1648        ["command"; "/test-command 2"]], "Result2\n");
1649     InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 3"]], "\nResult3");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 4"]], "\nResult4\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 5"]], "\nResult5\n\n");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 7"]], "");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 8"]], "\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 9"]], "\n\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1685     InitBasicFS, Always, TestLastFail (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command"]])],
1689    "run a command from the guest filesystem",
1690    "\
1691 This call runs a command from the guest filesystem.  The
1692 filesystem must be mounted, and must contain a compatible
1693 operating system (ie. something Linux, with the same
1694 or compatible processor architecture).
1695
1696 The single parameter is an argv-style list of arguments.
1697 The first element is the name of the program to run.
1698 Subsequent elements are parameters.  The list must be
1699 non-empty (ie. must contain a program name).  Note that
1700 the command runs directly, and is I<not> invoked via
1701 the shell (see C<guestfs_sh>).
1702
1703 The return value is anything printed to I<stdout> by
1704 the command.
1705
1706 If the command returns a non-zero exit status, then
1707 this function returns an error message.  The error message
1708 string is the content of I<stderr> from the command.
1709
1710 The C<$PATH> environment variable will contain at least
1711 C</usr/bin> and C</bin>.  If you require a program from
1712 another location, you should provide the full path in the
1713 first parameter.
1714
1715 Shared libraries and data files required by the program
1716 must be available on filesystems which are mounted in the
1717 correct places.  It is the caller's responsibility to ensure
1718 all filesystems that are needed are mounted at the right
1719 locations.");
1720
1721   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1722    [InitBasicFS, Always, TestOutputList (
1723       [["upload"; "test-command"; "/test-command"];
1724        ["chmod"; "0o755"; "/test-command"];
1725        ["command_lines"; "/test-command 1"]], ["Result1"]);
1726     InitBasicFS, Always, TestOutputList (
1727       [["upload"; "test-command"; "/test-command"];
1728        ["chmod"; "0o755"; "/test-command"];
1729        ["command_lines"; "/test-command 2"]], ["Result2"]);
1730     InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 7"]], []);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 8"]], [""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 9"]], ["";""]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1766    "run a command, returning lines",
1767    "\
1768 This is the same as C<guestfs_command>, but splits the
1769 result into a list of lines.
1770
1771 See also: C<guestfs_sh_lines>");
1772
1773   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1774    [InitISOFS, Always, TestOutputStruct (
1775       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1776    "get file information",
1777    "\
1778 Returns file information for the given C<path>.
1779
1780 This is the same as the C<stat(2)> system call.");
1781
1782   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1783    [InitISOFS, Always, TestOutputStruct (
1784       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1785    "get file information for a symbolic link",
1786    "\
1787 Returns file information for the given C<path>.
1788
1789 This is the same as C<guestfs_stat> except that if C<path>
1790 is a symbolic link, then the link is stat-ed, not the file it
1791 refers to.
1792
1793 This is the same as the C<lstat(2)> system call.");
1794
1795   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1796    [InitISOFS, Always, TestOutputStruct (
1797       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1798    "get file system statistics",
1799    "\
1800 Returns file system statistics for any mounted file system.
1801 C<path> should be a file or directory in the mounted file system
1802 (typically it is the mount point itself, but it doesn't need to be).
1803
1804 This is the same as the C<statvfs(2)> system call.");
1805
1806   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1807    [], (* XXX test *)
1808    "get ext2/ext3/ext4 superblock details",
1809    "\
1810 This returns the contents of the ext2, ext3 or ext4 filesystem
1811 superblock on C<device>.
1812
1813 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1814 manpage for more details.  The list of fields returned isn't
1815 clearly defined, and depends on both the version of C<tune2fs>
1816 that libguestfs was built against, and the filesystem itself.");
1817
1818   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1819    [InitEmpty, Always, TestOutputTrue (
1820       [["blockdev_setro"; "/dev/sda"];
1821        ["blockdev_getro"; "/dev/sda"]])],
1822    "set block device to read-only",
1823    "\
1824 Sets the block device named C<device> to read-only.
1825
1826 This uses the L<blockdev(8)> command.");
1827
1828   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1829    [InitEmpty, Always, TestOutputFalse (
1830       [["blockdev_setrw"; "/dev/sda"];
1831        ["blockdev_getro"; "/dev/sda"]])],
1832    "set block device to read-write",
1833    "\
1834 Sets the block device named C<device> to read-write.
1835
1836 This uses the L<blockdev(8)> command.");
1837
1838   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1839    [InitEmpty, Always, TestOutputTrue (
1840       [["blockdev_setro"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "is block device set to read-only",
1843    "\
1844 Returns a boolean indicating if the block device is read-only
1845 (true if read-only, false if not).
1846
1847 This uses the L<blockdev(8)> command.");
1848
1849   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1850    [InitEmpty, Always, TestOutputInt (
1851       [["blockdev_getss"; "/dev/sda"]], 512)],
1852    "get sectorsize of block device",
1853    "\
1854 This returns the size of sectors on a block device.
1855 Usually 512, but can be larger for modern devices.
1856
1857 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1858 for that).
1859
1860 This uses the L<blockdev(8)> command.");
1861
1862   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1863    [InitEmpty, Always, TestOutputInt (
1864       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1865    "get blocksize of block device",
1866    "\
1867 This returns the block size of a device.
1868
1869 (Note this is different from both I<size in blocks> and
1870 I<filesystem block size>).
1871
1872 This uses the L<blockdev(8)> command.");
1873
1874   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1875    [], (* XXX test *)
1876    "set blocksize of block device",
1877    "\
1878 This sets the block size of a device.
1879
1880 (Note this is different from both I<size in blocks> and
1881 I<filesystem block size>).
1882
1883 This uses the L<blockdev(8)> command.");
1884
1885   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1886    [InitEmpty, Always, TestOutputInt (
1887       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1888    "get total size of device in 512-byte sectors",
1889    "\
1890 This returns the size of the device in units of 512-byte sectors
1891 (even if the sectorsize isn't 512 bytes ... weird).
1892
1893 See also C<guestfs_blockdev_getss> for the real sector size of
1894 the device, and C<guestfs_blockdev_getsize64> for the more
1895 useful I<size in bytes>.
1896
1897 This uses the L<blockdev(8)> command.");
1898
1899   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1900    [InitEmpty, Always, TestOutputInt (
1901       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1902    "get total size of device in bytes",
1903    "\
1904 This returns the size of the device in bytes.
1905
1906 See also C<guestfs_blockdev_getsz>.
1907
1908 This uses the L<blockdev(8)> command.");
1909
1910   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1911    [InitEmpty, Always, TestRun
1912       [["blockdev_flushbufs"; "/dev/sda"]]],
1913    "flush device buffers",
1914    "\
1915 This tells the kernel to flush internal buffers associated
1916 with C<device>.
1917
1918 This uses the L<blockdev(8)> command.");
1919
1920   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1921    [InitEmpty, Always, TestRun
1922       [["blockdev_rereadpt"; "/dev/sda"]]],
1923    "reread partition table",
1924    "\
1925 Reread the partition table on C<device>.
1926
1927 This uses the L<blockdev(8)> command.");
1928
1929   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1930    [InitBasicFS, Always, TestOutput (
1931       (* Pick a file from cwd which isn't likely to change. *)
1932       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1933        ["checksum"; "md5"; "/COPYING.LIB"]],
1934       Digest.to_hex (Digest.file "COPYING.LIB"))],
1935    "upload a file from the local machine",
1936    "\
1937 Upload local file C<filename> to C<remotefilename> on the
1938 filesystem.
1939
1940 C<filename> can also be a named pipe.
1941
1942 See also C<guestfs_download>.");
1943
1944   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1945    [InitBasicFS, Always, TestOutput (
1946       (* Pick a file from cwd which isn't likely to change. *)
1947       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1948        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1949        ["upload"; "testdownload.tmp"; "/upload"];
1950        ["checksum"; "md5"; "/upload"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "download a file to the local machine",
1953    "\
1954 Download file C<remotefilename> and save it as C<filename>
1955 on the local machine.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_upload>, C<guestfs_cat>.");
1960
1961   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1962    [InitISOFS, Always, TestOutput (
1963       [["checksum"; "crc"; "/known-3"]], "2891671662");
1964     InitISOFS, Always, TestLastFail (
1965       [["checksum"; "crc"; "/notexists"]]);
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1978    "compute MD5, SHAx or CRC checksum of file",
1979    "\
1980 This call computes the MD5, SHAx or CRC checksum of the
1981 file named C<path>.
1982
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1985
1986 =over 4
1987
1988 =item C<crc>
1989
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1992
1993 =item C<md5>
1994
1995 Compute the MD5 hash (using the C<md5sum> program).
1996
1997 =item C<sha1>
1998
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2000
2001 =item C<sha224>
2002
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2004
2005 =item C<sha256>
2006
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2008
2009 =item C<sha384>
2010
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2012
2013 =item C<sha512>
2014
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2016
2017 =back
2018
2019 The checksum is returned as a printable string.");
2020
2021   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2022    [InitBasicFS, Always, TestOutput (
2023       [["tar_in"; "../images/helloworld.tar"; "/"];
2024        ["cat"; "/hello"]], "hello\n")],
2025    "unpack tarfile to directory",
2026    "\
2027 This command uploads and unpacks local file C<tarfile> (an
2028 I<uncompressed> tar file) into C<directory>.
2029
2030 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2031
2032   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2033    [],
2034    "pack directory into tarfile",
2035    "\
2036 This command packs the contents of C<directory> and downloads
2037 it to local file C<tarfile>.
2038
2039 To download a compressed tarball, use C<guestfs_tgz_out>.");
2040
2041   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042    [InitBasicFS, Always, TestOutput (
2043       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044        ["cat"; "/hello"]], "hello\n")],
2045    "unpack compressed tarball to directory",
2046    "\
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2049
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2051
2052   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2053    [],
2054    "pack directory into compressed tarball",
2055    "\
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2058
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2060
2061   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062    [InitBasicFS, Always, TestLastFail (
2063       [["umount"; "/"];
2064        ["mount_ro"; "/dev/sda1"; "/"];
2065        ["touch"; "/new"]]);
2066     InitBasicFS, Always, TestOutput (
2067       [["write_file"; "/new"; "data"; "0"];
2068        ["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["cat"; "/new"]], "data")],
2071    "mount a guest disk, read-only",
2072    "\
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2075
2076   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2077    [],
2078    "mount a guest disk with mount options",
2079    "\
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2083
2084   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2085    [],
2086    "mount a guest disk with mount options and vfstype",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2091
2092   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2093    [],
2094    "debugging and internals",
2095    "\
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2098 qemu subprocess.
2099
2100 There is no comprehensive help for this command.  You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2103
2104   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105    [InitEmpty, Always, TestOutputList (
2106       [["part_disk"; "/dev/sda"; "mbr"];
2107        ["pvcreate"; "/dev/sda1"];
2108        ["vgcreate"; "VG"; "/dev/sda1"];
2109        ["lvcreate"; "LV1"; "VG"; "50"];
2110        ["lvcreate"; "LV2"; "VG"; "50"];
2111        ["lvremove"; "/dev/VG/LV1"];
2112        ["lvs"]], ["/dev/VG/LV2"]);
2113     InitEmpty, Always, TestOutputList (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["lvremove"; "/dev/VG"];
2120        ["lvs"]], []);
2121     InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG"];
2128        ["vgs"]], ["VG"])],
2129    "remove an LVM logical volume",
2130    "\
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2133
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2136
2137   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["vgremove"; "VG"];
2145        ["lvs"]], []);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["vgremove"; "VG"];
2153        ["vgs"]], [])],
2154    "remove an LVM volume group",
2155    "\
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2157
2158 This also forcibly removes all logical volumes in the volume
2159 group (if any).");
2160
2161   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162    [InitEmpty, Always, TestOutputListOfDevices (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["pvremove"; "/dev/sda1"];
2170        ["lvs"]], []);
2171     InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["vgs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["pvs"]], [])],
2189    "remove an LVM physical volume",
2190    "\
2191 This wipes a physical volume C<device> so that LVM will no longer
2192 recognise it.
2193
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2197
2198   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199    [InitBasicFS, Always, TestOutput (
2200       [["set_e2label"; "/dev/sda1"; "testlabel"];
2201        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202    "set the ext2/3/4 filesystem label",
2203    "\
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>.  Filesystem labels are limited to
2206 16 characters.
2207
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2210
2211   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2212    [],
2213    "get the ext2/3/4 filesystem label",
2214    "\
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2216 C<device>.");
2217
2218   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219    (let uuid = uuidgen () in
2220     [InitBasicFS, Always, TestOutput (
2221        [["set_e2uuid"; "/dev/sda1"; uuid];
2222         ["get_e2uuid"; "/dev/sda1"]], uuid);
2223      InitBasicFS, Always, TestOutput (
2224        [["set_e2uuid"; "/dev/sda1"; "clear"];
2225         ["get_e2uuid"; "/dev/sda1"]], "");
2226      (* We can't predict what UUIDs will be, so just check the commands run. *)
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229      InitBasicFS, Always, TestRun (
2230        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231    "set the ext2/3/4 filesystem UUID",
2232    "\
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>.  The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2240
2241   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2242    [],
2243    "get the ext2/3/4 filesystem UUID",
2244    "\
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device>.");
2247
2248   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249    [InitBasicFS, Always, TestOutputInt (
2250       [["umount"; "/dev/sda1"];
2251        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252     InitBasicFS, Always, TestOutputInt (
2253       [["umount"; "/dev/sda1"];
2254        ["zero"; "/dev/sda1"];
2255        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256    "run the filesystem checker",
2257    "\
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2260
2261 The returned integer is the status.  See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2263
2264 Notes:
2265
2266 =over 4
2267
2268 =item *
2269
2270 Multiple status codes can be summed together.
2271
2272 =item *
2273
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2276
2277 =item *
2278
2279 Checking or repairing NTFS volumes is not supported
2280 (by linux-ntfs).
2281
2282 =back
2283
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2285
2286   ("zero", (RErr, [Device "device"]), 85, [],
2287    [InitBasicFS, Always, TestOutput (
2288       [["umount"; "/dev/sda1"];
2289        ["zero"; "/dev/sda1"];
2290        ["file"; "/dev/sda1"]], "data")],
2291    "write zeroes to the device",
2292    "\
2293 This command writes zeroes over the first few blocks of C<device>.
2294
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device).  It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2298
2299 See also: C<guestfs_scrub_device>.");
2300
2301   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302    (* Test disabled because grub-install incompatible with virtio-blk driver.
2303     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2304     *)
2305    [InitBasicFS, Disabled, TestOutputTrue (
2306       [["grub_install"; "/"; "/dev/sda1"];
2307        ["is_dir"; "/boot"]])],
2308    "install GRUB",
2309    "\
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2312
2313   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["write_file"; "/old"; "file content"; "0"];
2316        ["cp"; "/old"; "/new"];
2317        ["cat"; "/new"]], "file content");
2318     InitBasicFS, Always, TestOutputTrue (
2319       [["write_file"; "/old"; "file content"; "0"];
2320        ["cp"; "/old"; "/new"];
2321        ["is_file"; "/old"]]);
2322     InitBasicFS, Always, TestOutput (
2323       [["write_file"; "/old"; "file content"; "0"];
2324        ["mkdir"; "/dir"];
2325        ["cp"; "/old"; "/dir/new"];
2326        ["cat"; "/dir/new"]], "file content")],
2327    "copy a file",
2328    "\
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2331
2332   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333    [InitBasicFS, Always, TestOutput (
2334       [["mkdir"; "/olddir"];
2335        ["mkdir"; "/newdir"];
2336        ["write_file"; "/olddir/file"; "file content"; "0"];
2337        ["cp_a"; "/olddir"; "/newdir"];
2338        ["cat"; "/newdir/olddir/file"]], "file content")],
2339    "copy a file or directory recursively",
2340    "\
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2343
2344   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["mv"; "/old"; "/new"];
2348        ["cat"; "/new"]], "file content");
2349     InitBasicFS, Always, TestOutputFalse (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mv"; "/old"; "/new"];
2352        ["is_file"; "/old"]])],
2353    "move a file",
2354    "\
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2357
2358   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359    [InitEmpty, Always, TestRun (
2360       [["drop_caches"; "3"]])],
2361    "drop kernel page cache, dentries and inodes",
2362    "\
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches.  The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2367
2368 Setting C<whattodrop> to 3 should drop everything.
2369
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2372
2373   ("dmesg", (RString "kmsgs", []), 91, [],
2374    [InitEmpty, Always, TestRun (
2375       [["dmesg"]])],
2376    "return kernel messages",
2377    "\
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel.  This is sometimes useful for extended
2380 debugging of problems.
2381
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2386
2387   ("ping_daemon", (RErr, []), 92, [],
2388    [InitEmpty, Always, TestRun (
2389       [["ping_daemon"]])],
2390    "ping the guest daemon",
2391    "\
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess.  Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2396
2397   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398    [InitBasicFS, Always, TestOutputTrue (
2399       [["write_file"; "/file1"; "contents of a file"; "0"];
2400        ["cp"; "/file1"; "/file2"];
2401        ["equal"; "/file1"; "/file2"]]);
2402     InitBasicFS, Always, TestOutputFalse (
2403       [["write_file"; "/file1"; "contents of a file"; "0"];
2404        ["write_file"; "/file2"; "contents of another file"; "0"];
2405        ["equal"; "/file1"; "/file2"]]);
2406     InitBasicFS, Always, TestLastFail (
2407       [["equal"; "/file1"; "/file2"]])],
2408    "test if two files have equal contents",
2409    "\
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2412
2413 The external L<cmp(1)> program is used for the comparison.");
2414
2415   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416    [InitISOFS, Always, TestOutputList (
2417       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418     InitISOFS, Always, TestOutputList (
2419       [["strings"; "/empty"]], [])],
2420    "print the printable strings in a file",
2421    "\
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2424
2425   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings_e"; "b"; "/known-5"]], []);
2428     InitBasicFS, Disabled, TestOutputList (
2429       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431    "print the printable strings in a file",
2432    "\
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2435
2436 See the L<strings(1)> manpage for the full list of encodings.
2437
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2440
2441 The returned strings are transcoded to UTF-8.");
2442
2443   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444    [InitISOFS, Always, TestOutput (
2445       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2446     (* Test for RHBZ#501888c2 regression which caused large hexdump
2447      * commands to segfault.
2448      *)
2449     InitISOFS, Always, TestRun (
2450       [["hexdump"; "/100krandom"]])],
2451    "dump a file in hexadecimal",
2452    "\
2453 This runs C<hexdump -C> on the given C<path>.  The result is
2454 the human-readable, canonical hex dump of the file.");
2455
2456   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457    [InitNone, Always, TestOutput (
2458       [["part_disk"; "/dev/sda"; "mbr"];
2459        ["mkfs"; "ext3"; "/dev/sda1"];
2460        ["mount_options"; ""; "/dev/sda1"; "/"];
2461        ["write_file"; "/new"; "test file"; "0"];
2462        ["umount"; "/dev/sda1"];
2463        ["zerofree"; "/dev/sda1"];
2464        ["mount_options"; ""; "/dev/sda1"; "/"];
2465        ["cat"; "/new"]], "test file")],
2466    "zero unused inodes and disk blocks on ext2/3 filesystem",
2467    "\
2468 This runs the I<zerofree> program on C<device>.  This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2471 more effectively.
2472
2473 You should B<not> run this program if the filesystem is
2474 mounted.
2475
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2478
2479   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2480    [],
2481    "resize an LVM physical volume",
2482    "\
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2485
2486   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487                        Int "cyls"; Int "heads"; Int "sectors";
2488                        String "line"]), 99, [DangerWillRobinson],
2489    [],
2490    "modify a single partition on a block device",
2491    "\
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2494
2495 For other parameters, see C<guestfs_sfdisk>.  You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2497
2498 See also: C<guestfs_part_add>");
2499
2500   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2501    [],
2502    "display the partition table",
2503    "\
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command.  It is
2506 not intended to be parsed.
2507
2508 See also: C<guestfs_part_list>");
2509
2510   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2511    [],
2512    "display the kernel geometry",
2513    "\
2514 This displays the kernel's idea of the geometry of C<device>.
2515
2516 The result is in human-readable format, and not designed to
2517 be parsed.");
2518
2519   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2520    [],
2521    "display the disk geometry from the partition table",
2522    "\
2523 This displays the disk geometry of C<device> read from the
2524 partition table.  Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2532    [],
2533    "activate or deactivate all volume groups",
2534    "\
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2539 then those devices disappear.
2540
2541 This command is the same as running C<vgchange -a y|n>");
2542
2543   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate some volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2554
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2557
2558   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559    [InitNone, Always, TestOutput (
2560       [["part_disk"; "/dev/sda"; "mbr"];
2561        ["pvcreate"; "/dev/sda1"];
2562        ["vgcreate"; "VG"; "/dev/sda1"];
2563        ["lvcreate"; "LV"; "VG"; "10"];
2564        ["mkfs"; "ext2"; "/dev/VG/LV"];
2565        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566        ["write_file"; "/new"; "test content"; "0"];
2567        ["umount"; "/"];
2568        ["lvresize"; "/dev/VG/LV"; "20"];
2569        ["e2fsck_f"; "/dev/VG/LV"];
2570        ["resize2fs"; "/dev/VG/LV"];
2571        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572        ["cat"; "/new"]], "test content")],
2573    "resize an LVM logical volume",
2574    "\
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>.  When reducing, data in the reduced part
2577 is lost.");
2578
2579   ("resize2fs", (RErr, [Device "device"]), 106, [],
2580    [], (* lvresize tests this *)
2581    "resize an ext2/ext3 filesystem",
2582    "\
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2585
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command.  For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2591
2592   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593    [InitBasicFS, Always, TestOutputList (
2594       [["find"; "/"]], ["lost+found"]);
2595     InitBasicFS, Always, TestOutputList (
2596       [["touch"; "/a"];
2597        ["mkdir"; "/b"];
2598        ["touch"; "/b/c"];
2599        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600     InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["find"; "/a/b/"]], ["c"; "c/d"])],
2604    "find all files and directories",
2605    "\
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>.  It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2610
2611 This returns a list of strings I<without any prefix>.  Thus
2612 if the directory structure was:
2613
2614  /tmp/a
2615  /tmp/b
2616  /tmp/c/d
2617
2618 then the returned list from C<guestfs_find> C</tmp> would be
2619 4 elements:
2620
2621  a
2622  b
2623  c
2624  c/d
2625
2626 If C<directory> is not a directory, then this command returns
2627 an error.
2628
2629 The returned list is sorted.
2630
2631 See also C<guestfs_find0>.");
2632
2633   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634    [], (* lvresize tests this *)
2635    "check an ext2/ext3 filesystem",
2636    "\
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2640
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.).  Normally you should use C<guestfs_fsck>.");
2643
2644   ("sleep", (RErr, [Int "secs"]), 109, [],
2645    [InitNone, Always, TestRun (
2646       [["sleep"; "1"]])],
2647    "sleep for some seconds",
2648    "\
2649 Sleep for C<secs> seconds.");
2650
2651   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652    [InitNone, Always, TestOutputInt (
2653       [["part_disk"; "/dev/sda"; "mbr"];
2654        ["mkfs"; "ntfs"; "/dev/sda1"];
2655        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656     InitNone, Always, TestOutputInt (
2657       [["part_disk"; "/dev/sda"; "mbr"];
2658        ["mkfs"; "ext2"; "/dev/sda1"];
2659        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660    "probe NTFS volume",
2661    "\
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2665
2666 C<rw> is a boolean flag.  Set it to true if you want to test
2667 if the volume can be mounted read-write.  Set it to false if
2668 you want to test if the volume can be mounted read-only.
2669
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2673
2674   ("sh", (RString "output", [String "command"]), 111, [],
2675    [], (* XXX needs tests *)
2676    "run a command via the shell",
2677    "\
2678 This call runs a command from the guest filesystem via the
2679 guest's C</bin/sh>.
2680
2681 This is like C<guestfs_command>, but passes the command to:
2682
2683  /bin/sh -c \"command\"
2684
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2687 and so on.
2688
2689 All the provisos about C<guestfs_command> apply to this call.");
2690
2691   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692    [], (* XXX needs tests *)
2693    "run a command via the shell returning lines",
2694    "\
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2697
2698 See also: C<guestfs_command_lines>");
2699
2700   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702     * code in stubs.c, since all valid glob patterns must start with "/".
2703     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2704     *)
2705    [InitBasicFS, Always, TestOutputList (
2706       [["mkdir_p"; "/a/b/c"];
2707        ["touch"; "/a/b/c/d"];
2708        ["touch"; "/a/b/c/e"];
2709        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710     InitBasicFS, Always, TestOutputList (
2711       [["mkdir_p"; "/a/b/c"];
2712        ["touch"; "/a/b/c/d"];
2713        ["touch"; "/a/b/c/e"];
2714        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715     InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/*/x/*"]], [])],
2720    "expand a wildcard path",
2721    "\
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2724 used by the shell.
2725
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2728
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2732
2733   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735       [["scrub_device"; "/dev/sdc"]])],
2736    "scrub (securely wipe) a device",
2737    "\
2738 This command writes patterns over C<device> to make data retrieval
2739 more difficult.
2740
2741 It is an interface to the L<scrub(1)> program.  See that
2742 manual page for more details.");
2743
2744   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745    [InitBasicFS, Always, TestRun (
2746       [["write_file"; "/file"; "content"; "0"];
2747        ["scrub_file"; "/file"]])],
2748    "scrub (securely wipe) a file",
2749    "\
2750 This command writes patterns over a file to make data retrieval
2751 more difficult.
2752
2753 The file is I<removed> after scrubbing.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759    [], (* XXX needs testing *)
2760    "scrub (securely wipe) free space",
2761    "\
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2766 containing C<dir>.
2767
2768 It is an interface to the L<scrub(1)> program.  See that
2769 manual page for more details.");
2770
2771   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772    [InitBasicFS, Always, TestRun (
2773       [["mkdir"; "/tmp"];
2774        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775    "create a temporary directory",
2776    "\
2777 This command creates a temporary directory.  The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2780 \"XXXXXX\".
2781
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2784
2785 The name of the temporary directory that was created
2786 is returned.
2787
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2790
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2793
2794 See also: L<mkdtemp(3)>");
2795
2796   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["wc_l"; "/10klines"]], 10000)],
2799    "count lines in a file",
2800    "\
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2803
2804   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805    [InitISOFS, Always, TestOutputInt (
2806       [["wc_w"; "/10klines"]], 10000)],
2807    "count words in a file",
2808    "\
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2811
2812   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813    [InitISOFS, Always, TestOutputInt (
2814       [["wc_c"; "/100kallspaces"]], 102400)],
2815    "count characters in a file",
2816    "\
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2819
2820   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821    [InitISOFS, Always, TestOutputList (
2822       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823    "return first 10 lines of a file",
2824    "\
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2827
2828   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829    [InitISOFS, Always, TestOutputList (
2830       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833     InitISOFS, Always, TestOutputList (
2834       [["head_n"; "0"; "/10klines"]], [])],
2835    "return first N lines of a file",
2836    "\
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2839
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2842
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2844
2845   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846    [InitISOFS, Always, TestOutputList (
2847       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848    "return last 10 lines of a file",
2849    "\
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2852
2853   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854    [InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858     InitISOFS, Always, TestOutputList (
2859       [["tail_n"; "0"; "/10klines"]], [])],
2860    "return last N lines of a file",
2861    "\
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2864
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2867
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2869
2870   ("df", (RString "output", []), 125, [],
2871    [], (* XXX Tricky to test because it depends on the exact format
2872         * of the 'df' command and other imponderables.
2873         *)
2874    "report file system disk space usage",
2875    "\
2876 This command runs the C<df> command to report disk space used.
2877
2878 This command is mostly useful for interactive sessions.  It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2881
2882   ("df_h", (RString "output", []), 126, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage (human readable)",
2887    "\
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2890
2891 This command is mostly useful for interactive sessions.  It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2894
2895   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896    [InitISOFS, Always, TestOutputInt (
2897       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898    "estimate file space usage",
2899    "\
2900 This command runs the C<du -s> command to estimate file space
2901 usage for C<path>.
2902
2903 C<path> can be a file or a directory.  If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2906
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2909
2910   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911    [InitISOFS, Always, TestOutputList (
2912       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913    "list files in an initrd",
2914    "\
2915 This command lists out files contained in an initrd.
2916
2917 The files are listed without any initial C</> character.  The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical).  Directory names are listed as separate items.
2920
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd.  We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2924
2925   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2926    [],
2927    "mount a file using the loop device",
2928    "\
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point.  It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2932
2933   ("mkswap", (RErr, [Device "device"]), 130, [],
2934    [InitEmpty, Always, TestRun (
2935       [["part_disk"; "/dev/sda"; "mbr"];
2936        ["mkswap"; "/dev/sda1"]])],
2937    "create a swap partition",
2938    "\
2939 Create a swap partition on C<device>.");
2940
2941   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942    [InitEmpty, Always, TestRun (
2943       [["part_disk"; "/dev/sda"; "mbr"];
2944        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945    "create a swap partition with a label",
2946    "\
2947 Create a swap partition on C<device> with label C<label>.
2948
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition.  This appears to be
2951 a limitation of the kernel or swap tools.");
2952
2953   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954    (let uuid = uuidgen () in
2955     [InitEmpty, Always, TestRun (
2956        [["part_disk"; "/dev/sda"; "mbr"];
2957         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958    "create a swap partition with an explicit UUID",
2959    "\
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2961
2962   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963    [InitBasicFS, Always, TestOutputStruct (
2964       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967     InitBasicFS, Always, TestOutputStruct (
2968       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970    "make block, character or FIFO devices",
2971    "\
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2974
2975 The C<mode> parameter should be the mode, using the standard
2976 constants.  C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.
2979
2980 The mode actually set is affected by the umask.");
2981
2982   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2983    [InitBasicFS, Always, TestOutputStruct (
2984       [["mkfifo"; "0o777"; "/node"];
2985        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2986    "make FIFO (named pipe)",
2987    "\
2988 This call creates a FIFO (named pipe) called C<path> with
2989 mode C<mode>.  It is just a convenient wrapper around
2990 C<guestfs_mknod>.
2991
2992 The mode actually set is affected by the umask.");
2993
2994   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2995    [InitBasicFS, Always, TestOutputStruct (
2996       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2997        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2998    "make block device node",
2999    "\
3000 This call creates a block device node called C<path> with
3001 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3002 It is just a convenient wrapper around C<guestfs_mknod>.
3003
3004 The mode actually set is affected by the umask.");
3005
3006   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3007    [InitBasicFS, Always, TestOutputStruct (
3008       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3009        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3010    "make char device node",
3011    "\
3012 This call creates a char device node called C<path> with
3013 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3014 It is just a convenient wrapper around C<guestfs_mknod>.
3015
3016 The mode actually set is affected by the umask.");
3017
3018   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3019    [InitEmpty, Always, TestOutputInt (
3020       [["umask"; "0o22"]], 0o22)],
3021    "set file mode creation mask (umask)",
3022    "\
3023 This function sets the mask used for creating new files and
3024 device nodes to C<mask & 0777>.
3025
3026 Typical umask values would be C<022> which creates new files
3027 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3028 C<002> which creates new files with permissions like
3029 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3030
3031 The default umask is C<022>.  This is important because it
3032 means that directories and device nodes will be created with
3033 C<0644> or C<0755> mode even if you specify C<0777>.
3034
3035 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3036
3037 This call returns the previous umask.");
3038
3039   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3040    [],
3041    "read directories entries",
3042    "\
3043 This returns the list of directory entries in directory C<dir>.
3044
3045 All entries in the directory are returned, including C<.> and
3046 C<..>.  The entries are I<not> sorted, but returned in the same
3047 order as the underlying filesystem.
3048
3049 Also this call returns basic file type information about each
3050 file.  The C<ftyp> field will contain one of the following characters:
3051
3052 =over 4
3053
3054 =item 'b'
3055
3056 Block special
3057
3058 =item 'c'
3059
3060 Char special
3061
3062 =item 'd'
3063
3064 Directory
3065
3066 =item 'f'
3067
3068 FIFO (named pipe)
3069
3070 =item 'l'
3071
3072 Symbolic link
3073
3074 =item 'r'
3075
3076 Regular file
3077
3078 =item 's'
3079
3080 Socket
3081
3082 =item 'u'
3083
3084 Unknown file type
3085
3086 =item '?'
3087
3088 The L<readdir(3)> returned a C<d_type> field with an
3089 unexpected value
3090
3091 =back
3092
3093 This function is primarily intended for use by programs.  To
3094 get a simple list of names, use C<guestfs_ls>.  To get a printable
3095 directory for human consumption, use C<guestfs_ll>.");
3096
3097   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3098    [],
3099    "create partitions on a block device",
3100    "\
3101 This is a simplified interface to the C<guestfs_sfdisk>
3102 command, where partition sizes are specified in megabytes
3103 only (rounded to the nearest cylinder) and you don't need
3104 to specify the cyls, heads and sectors parameters which
3105 were rarely if ever used anyway.
3106
3107 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3108 and C<guestfs_part_disk>");
3109
3110   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3111    [],
3112    "determine file type inside a compressed file",
3113    "\
3114 This command runs C<file> after first decompressing C<path>
3115 using C<method>.
3116
3117 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3118
3119 Since 1.0.63, use C<guestfs_file> instead which can now
3120 process compressed files.");
3121
3122   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3123    [],
3124    "list extended attributes of a file or directory",
3125    "\
3126 This call lists the extended attributes of the file or directory
3127 C<path>.
3128
3129 At the system call level, this is a combination of the
3130 L<listxattr(2)> and L<getxattr(2)> calls.
3131
3132 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3133
3134   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3135    [],
3136    "list extended attributes of a file or directory",
3137    "\
3138 This is the same as C<guestfs_getxattrs>, but if C<path>
3139 is a symbolic link, then it returns the extended attributes
3140 of the link itself.");
3141
3142   ("setxattr", (RErr, [String "xattr";
3143                        String "val"; Int "vallen"; (* will be BufferIn *)
3144                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3145    [],
3146    "set extended attribute of a file or directory",
3147    "\
3148 This call sets the extended attribute named C<xattr>
3149 of the file C<path> to the value C<val> (of length C<vallen>).
3150 The value is arbitrary 8 bit data.
3151
3152 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3153
3154   ("lsetxattr", (RErr, [String "xattr";
3155                         String "val"; Int "vallen"; (* will be BufferIn *)
3156                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3157    [],
3158    "set extended attribute of a file or directory",
3159    "\
3160 This is the same as C<guestfs_setxattr>, but if C<path>
3161 is a symbolic link, then it sets an extended attribute
3162 of the link itself.");
3163
3164   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3165    [],
3166    "remove extended attribute of a file or directory",
3167    "\
3168 This call removes the extended attribute named C<xattr>
3169 of the file C<path>.
3170
3171 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3172
3173   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3174    [],
3175    "remove extended attribute of a file or directory",
3176    "\
3177 This is the same as C<guestfs_removexattr>, but if C<path>
3178 is a symbolic link, then it removes an extended attribute
3179 of the link itself.");
3180
3181   ("mountpoints", (RHashtable "mps", []), 147, [],
3182    [],
3183    "show mountpoints",
3184    "\
3185 This call is similar to C<guestfs_mounts>.  That call returns
3186 a list of devices.  This one returns a hash table (map) of
3187 device name to directory where the device is mounted.");
3188
3189   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3190    (* This is a special case: while you would expect a parameter
3191     * of type "Pathname", that doesn't work, because it implies
3192     * NEED_ROOT in the generated calling code in stubs.c, and
3193     * this function cannot use NEED_ROOT.
3194     *)
3195    [],
3196    "create a mountpoint",
3197    "\
3198 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3199 specialized calls that can be used to create extra mountpoints
3200 before mounting the first filesystem.
3201
3202 These calls are I<only> necessary in some very limited circumstances,
3203 mainly the case where you want to mount a mix of unrelated and/or
3204 read-only filesystems together.
3205
3206 For example, live CDs often contain a \"Russian doll\" nest of
3207 filesystems, an ISO outer layer, with a squashfs image inside, with
3208 an ext2/3 image inside that.  You can unpack this as follows
3209 in guestfish:
3210
3211  add-ro Fedora-11-i686-Live.iso
3212  run
3213  mkmountpoint /cd
3214  mkmountpoint /squash
3215  mkmountpoint /ext3
3216  mount /dev/sda /cd
3217  mount-loop /cd/LiveOS/squashfs.img /squash
3218  mount-loop /squash/LiveOS/ext3fs.img /ext3
3219
3220 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3221
3222   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3223    [],
3224    "remove a mountpoint",
3225    "\
3226 This calls removes a mountpoint that was previously created
3227 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3228 for full details.");
3229
3230   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3231    [InitISOFS, Always, TestOutputBuffer (
3232       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3233    "read a file",
3234    "\
3235 This calls returns the contents of the file C<path> as a
3236 buffer.
3237
3238 Unlike C<guestfs_cat>, this function can correctly
3239 handle files that contain embedded ASCII NUL characters.
3240 However unlike C<guestfs_download>, this function is limited
3241 in the total size of file that can be handled.");
3242
3243   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3244    [InitISOFS, Always, TestOutputList (
3245       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3246     InitISOFS, Always, TestOutputList (
3247       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3248    "return lines matching a pattern",
3249    "\
3250 This calls the external C<grep> program and returns the
3251 matching lines.");
3252
3253   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3254    [InitISOFS, Always, TestOutputList (
3255       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3256    "return lines matching a pattern",
3257    "\
3258 This calls the external C<egrep> program and returns the
3259 matching lines.");
3260
3261   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3262    [InitISOFS, Always, TestOutputList (
3263       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3264    "return lines matching a pattern",
3265    "\
3266 This calls the external C<fgrep> program and returns the
3267 matching lines.");
3268
3269   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3270    [InitISOFS, Always, TestOutputList (
3271       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3272    "return lines matching a pattern",
3273    "\
3274 This calls the external C<grep -i> program and returns the
3275 matching lines.");
3276
3277   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3278    [InitISOFS, Always, TestOutputList (
3279       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3280    "return lines matching a pattern",
3281    "\
3282 This calls the external C<egrep -i> program and returns the
3283 matching lines.");
3284
3285   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3286    [InitISOFS, Always, TestOutputList (
3287       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3288    "return lines matching a pattern",
3289    "\
3290 This calls the external C<fgrep -i> program and returns the
3291 matching lines.");
3292
3293   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3294    [InitISOFS, Always, TestOutputList (
3295       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3296    "return lines matching a pattern",
3297    "\
3298 This calls the external C<zgrep> program and returns the
3299 matching lines.");
3300
3301   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3302    [InitISOFS, Always, TestOutputList (
3303       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3304    "return lines matching a pattern",
3305    "\
3306 This calls the external C<zegrep> program and returns the
3307 matching lines.");
3308
3309   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3310    [InitISOFS, Always, TestOutputList (
3311       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3312    "return lines matching a pattern",
3313    "\
3314 This calls the external C<zfgrep> program and returns the
3315 matching lines.");
3316
3317   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3318    [InitISOFS, Always, TestOutputList (
3319       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3320    "return lines matching a pattern",
3321    "\
3322 This calls the external C<zgrep -i> program and returns the
3323 matching lines.");
3324
3325   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3326    [InitISOFS, Always, TestOutputList (
3327       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3328    "return lines matching a pattern",
3329    "\
3330 This calls the external C<zegrep -i> program and returns the
3331 matching lines.");
3332
3333   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3334    [InitISOFS, Always, TestOutputList (
3335       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3336    "return lines matching a pattern",
3337    "\
3338 This calls the external C<zfgrep -i> program and returns the
3339 matching lines.");
3340
3341   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3342    [InitISOFS, Always, TestOutput (
3343       [["realpath"; "/../directory"]], "/directory")],
3344    "canonicalized absolute pathname",
3345    "\
3346 Return the canonicalized absolute pathname of C<path>.  The
3347 returned path has no C<.>, C<..> or symbolic link path elements.");
3348
3349   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3350    [InitBasicFS, Always, TestOutputStruct (
3351       [["touch"; "/a"];
3352        ["ln"; "/a"; "/b"];
3353        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3354    "create a hard link",
3355    "\
3356 This command creates a hard link using the C<ln> command.");
3357
3358   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3359    [InitBasicFS, Always, TestOutputStruct (
3360       [["touch"; "/a"];
3361        ["touch"; "/b"];
3362        ["ln_f"; "/a"; "/b"];
3363        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3364    "create a hard link",
3365    "\
3366 This command creates a hard link using the C<ln -f> command.
3367 The C<-f> option removes the link (C<linkname>) if it exists already.");
3368
3369   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3370    [InitBasicFS, Always, TestOutputStruct (
3371       [["touch"; "/a"];
3372        ["ln_s"; "a"; "/b"];
3373        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3374    "create a symbolic link",
3375    "\
3376 This command creates a symbolic link using the C<ln -s> command.");
3377
3378   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3379    [InitBasicFS, Always, TestOutput (
3380       [["mkdir_p"; "/a/b"];
3381        ["touch"; "/a/b/c"];
3382        ["ln_sf"; "../d"; "/a/b/c"];
3383        ["readlink"; "/a/b/c"]], "../d")],
3384    "create a symbolic link",
3385    "\
3386 This command creates a symbolic link using the C<ln -sf> command,
3387 The C<-f> option removes the link (C<linkname>) if it exists already.");
3388
3389   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3390    [] (* XXX tested above *),
3391    "read the target of a symbolic link",
3392    "\
3393 This command reads the target of a symbolic link.");
3394
3395   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3396    [InitBasicFS, Always, TestOutputStruct (
3397       [["fallocate"; "/a"; "1000000"];
3398        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3399    "preallocate a file in the guest filesystem",
3400    "\
3401 This command preallocates a file (containing zero bytes) named
3402 C<path> of size C<len> bytes.  If the file exists already, it
3403 is overwritten.
3404
3405 Do not confuse this with the guestfish-specific
3406 C<alloc> command which allocates a file in the host and
3407 attaches it as a device.");
3408
3409   ("swapon_device", (RErr, [Device "device"]), 170, [],
3410    [InitPartition, Always, TestRun (
3411       [["mkswap"; "/dev/sda1"];
3412        ["swapon_device"; "/dev/sda1"];
3413        ["swapoff_device"; "/dev/sda1"]])],
3414    "enable swap on device",
3415    "\
3416 This command enables the libguestfs appliance to use the
3417 swap device or partition named C<device>.  The increased
3418 memory is made available for all commands, for example
3419 those run using C<guestfs_command> or C<guestfs_sh>.
3420
3421 Note that you should not swap to existing guest swap
3422 partitions unless you know what you are doing.  They may
3423 contain hibernation information, or other information that
3424 the guest doesn't want you to trash.  You also risk leaking
3425 information about the host to the guest this way.  Instead,
3426 attach a new host device to the guest and swap on that.");
3427
3428   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3429    [], (* XXX tested by swapon_device *)
3430    "disable swap on device",
3431    "\
3432 This command disables the libguestfs appliance swap
3433 device or partition named C<device>.
3434 See C<guestfs_swapon_device>.");
3435
3436   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3437    [InitBasicFS, Always, TestRun (
3438       [["fallocate"; "/swap"; "8388608"];
3439        ["mkswap_file"; "/swap"];
3440        ["swapon_file"; "/swap"];
3441        ["swapoff_file"; "/swap"]])],
3442    "enable swap on file",
3443    "\
3444 This command enables swap to a file.
3445 See C<guestfs_swapon_device> for other notes.");
3446
3447   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3448    [], (* XXX tested by swapon_file *)
3449    "disable swap on file",
3450    "\
3451 This command disables the libguestfs appliance swap on file.");
3452
3453   ("swapon_label", (RErr, [String "label"]), 174, [],
3454    [InitEmpty, Always, TestRun (
3455       [["part_disk"; "/dev/sdb"; "mbr"];
3456        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3457        ["swapon_label"; "swapit"];
3458        ["swapoff_label"; "swapit"];
3459        ["zero"; "/dev/sdb"];
3460        ["blockdev_rereadpt"; "/dev/sdb"]])],
3461    "enable swap on labeled swap partition",
3462    "\
3463 This command enables swap to a labeled swap partition.
3464 See C<guestfs_swapon_device> for other notes.");
3465
3466   ("swapoff_label", (RErr, [String "label"]), 175, [],
3467    [], (* XXX tested by swapon_label *)
3468    "disable swap on labeled swap partition",
3469    "\
3470 This command disables the libguestfs appliance swap on
3471 labeled swap partition.");
3472
3473   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3474    (let uuid = uuidgen () in
3475     [InitEmpty, Always, TestRun (
3476        [["mkswap_U"; uuid; "/dev/sdb"];
3477         ["swapon_uuid"; uuid];
3478         ["swapoff_uuid"; uuid]])]),
3479    "enable swap on swap partition by UUID",
3480    "\
3481 This command enables swap to a swap partition with the given UUID.
3482 See C<guestfs_swapon_device> for other notes.");
3483
3484   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3485    [], (* XXX tested by swapon_uuid *)
3486    "disable swap on swap partition by UUID",
3487    "\
3488 This command disables the libguestfs appliance swap partition
3489 with the given UUID.");
3490
3491   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3492    [InitBasicFS, Always, TestRun (
3493       [["fallocate"; "/swap"; "8388608"];
3494        ["mkswap_file"; "/swap"]])],
3495    "create a swap file",
3496    "\
3497 Create a swap file.
3498
3499 This command just writes a swap file signature to an existing
3500 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3501
3502   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3503    [InitISOFS, Always, TestRun (
3504       [["inotify_init"; "0"]])],
3505    "create an inotify handle",
3506    "\
3507 This command creates a new inotify handle.
3508 The inotify subsystem can be used to notify events which happen to
3509 objects in the guest filesystem.
3510
3511 C<maxevents> is the maximum number of events which will be
3512 queued up between calls to C<guestfs_inotify_read> or
3513 C<guestfs_inotify_files>.
3514 If this is passed as C<0>, then the kernel (or previously set)
3515 default is used.  For Linux 2.6.29 the default was 16384 events.
3516 Beyond this limit, the kernel throws away events, but records
3517 the fact that it threw them away by setting a flag
3518 C<IN_Q_OVERFLOW> in the returned structure list (see
3519 C<guestfs_inotify_read>).
3520
3521 Before any events are generated, you have to add some
3522 watches to the internal watch list.  See:
3523 C<guestfs_inotify_add_watch>,
3524 C<guestfs_inotify_rm_watch> and
3525 C<guestfs_inotify_watch_all>.
3526
3527 Queued up events should be read periodically by calling
3528 C<guestfs_inotify_read>
3529 (or C<guestfs_inotify_files> which is just a helpful
3530 wrapper around C<guestfs_inotify_read>).  If you don't
3531 read the events out often enough then you risk the internal
3532 queue overflowing.
3533
3534 The handle should be closed after use by calling
3535 C<guestfs_inotify_close>.  This also removes any
3536 watches automatically.
3537
3538 See also L<inotify(7)> for an overview of the inotify interface
3539 as exposed by the Linux kernel, which is roughly what we expose
3540 via libguestfs.  Note that there is one global inotify handle
3541 per libguestfs instance.");
3542
3543   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3544    [InitBasicFS, Always, TestOutputList (
3545       [["inotify_init"; "0"];
3546        ["inotify_add_watch"; "/"; "1073741823"];
3547        ["touch"; "/a"];
3548        ["touch"; "/b"];
3549        ["inotify_files"]], ["a"; "b"])],
3550    "add an inotify watch",
3551    "\
3552 Watch C<path> for the events listed in C<mask>.
3553
3554 Note that if C<path> is a directory then events within that
3555 directory are watched, but this does I<not> happen recursively
3556 (in subdirectories).
3557
3558 Note for non-C or non-Linux callers: the inotify events are
3559 defined by the Linux kernel ABI and are listed in
3560 C</usr/include/sys/inotify.h>.");
3561
3562   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3563    [],
3564    "remove an inotify watch",
3565    "\
3566 Remove a previously defined inotify watch.
3567 See C<guestfs_inotify_add_watch>.");
3568
3569   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3570    [],
3571    "return list of inotify events",
3572    "\
3573 Return the complete queue of events that have happened
3574 since the previous read call.
3575
3576 If no events have happened, this returns an empty list.
3577
3578 I<Note>: In order to make sure that all events have been
3579 read, you must call this function repeatedly until it
3580 returns an empty list.  The reason is that the call will
3581 read events up to the maximum appliance-to-host message
3582 size and leave remaining events in the queue.");
3583
3584   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3585    [],
3586    "return list of watched files that had events",
3587    "\
3588 This function is a helpful wrapper around C<guestfs_inotify_read>
3589 which just returns a list of pathnames of objects that were
3590 touched.  The returned pathnames are sorted and deduplicated.");
3591
3592   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3593    [],
3594    "close the inotify handle",
3595    "\
3596 This closes the inotify handle which was previously
3597 opened by inotify_init.  It removes all watches, throws
3598 away any pending events, and deallocates all resources.");
3599
3600   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3601    [],
3602    "set SELinux security context",
3603    "\
3604 This sets the SELinux security context of the daemon
3605 to the string C<context>.
3606
3607 See the documentation about SELINUX in L<guestfs(3)>.");
3608
3609   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3610    [],
3611    "get SELinux security context",
3612    "\
3613 This gets the SELinux security context of the daemon.
3614
3615 See the documentation about SELINUX in L<guestfs(3)>,
3616 and C<guestfs_setcon>");
3617
3618   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3619    [InitEmpty, Always, TestOutput (
3620       [["part_disk"; "/dev/sda"; "mbr"];
3621        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3622        ["mount_options"; ""; "/dev/sda1"; "/"];
3623        ["write_file"; "/new"; "new file contents"; "0"];
3624        ["cat"; "/new"]], "new file contents")],
3625    "make a filesystem with block size",
3626    "\
3627 This call is similar to C<guestfs_mkfs>, but it allows you to
3628 control the block size of the resulting filesystem.  Supported
3629 block sizes depend on the filesystem type, but typically they
3630 are C<1024>, C<2048> or C<4096> only.");
3631
3632   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3633    [InitEmpty, Always, TestOutput (
3634       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3635        ["mke2journal"; "4096"; "/dev/sda1"];
3636        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3637        ["mount_options"; ""; "/dev/sda2"; "/"];
3638        ["write_file"; "/new"; "new file contents"; "0"];
3639        ["cat"; "/new"]], "new file contents")],
3640    "make ext2/3/4 external journal",
3641    "\
3642 This creates an ext2 external journal on C<device>.  It is equivalent
3643 to the command:
3644
3645  mke2fs -O journal_dev -b blocksize device");
3646
3647   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3648    [InitEmpty, Always, TestOutput (
3649       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3650        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3651        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3652        ["mount_options"; ""; "/dev/sda2"; "/"];
3653        ["write_file"; "/new"; "new file contents"; "0"];
3654        ["cat"; "/new"]], "new file contents")],
3655    "make ext2/3/4 external journal with label",
3656    "\
3657 This creates an ext2 external journal on C<device> with label C<label>.");
3658
3659   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3660    (let uuid = uuidgen () in
3661     [InitEmpty, Always, TestOutput (
3662        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3663         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3664         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3665         ["mount_options"; ""; "/dev/sda2"; "/"];
3666         ["write_file"; "/new"; "new file contents"; "0"];
3667         ["cat"; "/new"]], "new file contents")]),
3668    "make ext2/3/4 external journal with UUID",
3669    "\
3670 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3671
3672   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3673    [],
3674    "make ext2/3/4 filesystem with external journal",
3675    "\
3676 This creates an ext2/3/4 filesystem on C<device> with
3677 an external journal on C<journal>.  It is equivalent
3678 to the command:
3679
3680  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3681
3682 See also C<guestfs_mke2journal>.");
3683
3684   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3685    [],
3686    "make ext2/3/4 filesystem with external journal",
3687    "\
3688 This creates an ext2/3/4 filesystem on C<device> with
3689 an external journal on the journal labeled C<label>.
3690
3691 See also C<guestfs_mke2journal_L>.");
3692
3693   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3694    [],
3695    "make ext2/3/4 filesystem with external journal",
3696    "\
3697 This creates an ext2/3/4 filesystem on C<device> with
3698 an external journal on the journal with UUID C<uuid>.
3699
3700 See also C<guestfs_mke2journal_U>.");
3701
3702   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3703    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3704    "load a kernel module",
3705    "\
3706 This loads a kernel module in the appliance.
3707
3708 The kernel module must have been whitelisted when libguestfs
3709 was built (see C<appliance/kmod.whitelist.in> in the source).");
3710
3711   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3712    [InitNone, Always, TestOutput (
3713       [["echo_daemon"; "This is a test"]], "This is a test"
3714     )],
3715    "echo arguments back to the client",
3716    "\
3717 This command concatenate the list of C<words> passed with single spaces between
3718 them and returns the resulting string.
3719
3720 You can use this command to test the connection through to the daemon.
3721
3722 See also C<guestfs_ping_daemon>.");
3723
3724   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3725    [], (* There is a regression test for this. *)
3726    "find all files and directories, returning NUL-separated list",
3727    "\
3728 This command lists out all files and directories, recursively,
3729 starting at C<directory>, placing the resulting list in the
3730 external file called C<files>.
3731
3732 This command works the same way as C<guestfs_find> with the
3733 following exceptions:
3734
3735 =over 4
3736
3737 =item *
3738
3739 The resulting list is written to an external file.
3740
3741 =item *
3742
3743 Items (filenames) in the result are separated
3744 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3745
3746 =item *
3747
3748 This command is not limited in the number of names that it
3749 can return.
3750
3751 =item *
3752
3753 The result list is not sorted.
3754
3755 =back");
3756
3757   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3758    [InitISOFS, Always, TestOutput (
3759       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3760     InitISOFS, Always, TestOutput (
3761       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3762     InitISOFS, Always, TestOutput (
3763       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3764     InitISOFS, Always, TestLastFail (
3765       [["case_sensitive_path"; "/Known-1/"]]);
3766     InitBasicFS, Always, TestOutput (
3767       [["mkdir"; "/a"];
3768        ["mkdir"; "/a/bbb"];
3769        ["touch"; "/a/bbb/c"];
3770        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3771     InitBasicFS, Always, TestOutput (
3772       [["mkdir"; "/a"];
3773        ["mkdir"; "/a/bbb"];
3774        ["touch"; "/a/bbb/c"];
3775        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3776     InitBasicFS, Always, TestLastFail (
3777       [["mkdir"; "/a"];
3778        ["mkdir"; "/a/bbb"];
3779        ["touch"; "/a/bbb/c"];
3780        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3781    "return true path on case-insensitive filesystem",
3782    "\
3783 This can be used to resolve case insensitive paths on
3784 a filesystem which is case sensitive.  The use case is
3785 to resolve paths which you have read from Windows configuration
3786 files or the Windows Registry, to the true path.
3787
3788 The command handles a peculiarity of the Linux ntfs-3g
3789 filesystem driver (and probably others), which is that although
3790 the underlying filesystem is case-insensitive, the driver
3791 exports the filesystem to Linux as case-sensitive.
3792
3793 One consequence of this is that special directories such
3794 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3795 (or other things) depending on the precise details of how
3796 they were created.  In Windows itself this would not be
3797 a problem.
3798
3799 Bug or feature?  You decide:
3800 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3801
3802 This function resolves the true case of each element in the
3803 path and returns the case-sensitive path.
3804
3805 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3806 might return C<\"/WINDOWS/system32\"> (the exact return value
3807 would depend on details of how the directories were originally
3808 created under Windows).
3809
3810 I<Note>:
3811 This function does not handle drive names, backslashes etc.
3812
3813 See also C<guestfs_realpath>.");
3814
3815   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3816    [InitBasicFS, Always, TestOutput (
3817       [["vfs_type"; "/dev/sda1"]], "ext2")],
3818    "get the Linux VFS type corresponding to a mounted device",
3819    "\
3820 This command gets the block device type corresponding to
3821 a mounted device called C<device>.
3822
3823 Usually the result is the name of the Linux VFS module that
3824 is used to mount this device (probably determined automatically
3825 if you used the C<guestfs_mount> call).");
3826
3827   ("truncate", (RErr, [Pathname "path"]), 199, [],
3828    [InitBasicFS, Always, TestOutputStruct (
3829       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3830        ["truncate"; "/test"];
3831        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3832    "truncate a file to zero size",
3833    "\
3834 This command truncates C<path> to a zero-length file.  The
3835 file must exist already.");
3836
3837   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3838    [InitBasicFS, Always, TestOutputStruct (
3839       [["touch"; "/test"];
3840        ["truncate_size"; "/test"; "1000"];
3841        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3842    "truncate a file to a particular size",
3843    "\
3844 This command truncates C<path> to size C<size> bytes.  The file
3845 must exist already.  If the file is smaller than C<size> then
3846 the file is extended to the required size with null bytes.");
3847
3848   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3849    [InitBasicFS, Always, TestOutputStruct (
3850       [["touch"; "/test"];
3851        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3852        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3853    "set timestamp of a file with nanosecond precision",
3854    "\
3855 This command sets the timestamps of a file with nanosecond
3856 precision.
3857
3858 C<atsecs, atnsecs> are the last access time (atime) in secs and
3859 nanoseconds from the epoch.
3860
3861 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3862 secs and nanoseconds from the epoch.
3863
3864 If the C<*nsecs> field contains the special value C<-1> then
3865 the corresponding timestamp is set to the current time.  (The
3866 C<*secs> field is ignored in this case).
3867
3868 If the C<*nsecs> field contains the special value C<-2> then
3869 the corresponding timestamp is left unchanged.  (The
3870 C<*secs> field is ignored in this case).");
3871
3872   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3873    [InitBasicFS, Always, TestOutputStruct (
3874       [["mkdir_mode"; "/test"; "0o111"];
3875        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3876    "create a directory with a particular mode",
3877    "\
3878 This command creates a directory, setting the initial permissions
3879 of the directory to C<mode>.
3880
3881 For common Linux filesystems, the actual mode which is set will
3882 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3883 interpret the mode in other ways.
3884
3885 See also C<guestfs_mkdir>, C<guestfs_umask>");
3886
3887   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3888    [], (* XXX *)
3889    "change file owner and group",
3890    "\
3891 Change the file owner to C<owner> and group to C<group>.
3892 This is like C<guestfs_chown> but if C<path> is a symlink then
3893 the link itself is changed, not the target.
3894
3895 Only numeric uid and gid are supported.  If you want to use
3896 names, you will need to locate and parse the password file
3897 yourself (Augeas support makes this relatively easy).");
3898
3899   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3900    [], (* XXX *)
3901    "lstat on multiple files",
3902    "\
3903 This call allows you to perform the C<guestfs_lstat> operation
3904 on multiple files, where all files are in the directory C<path>.
3905 C<names> is the list of files from this directory.
3906
3907 On return you get a list of stat structs, with a one-to-one
3908 correspondence to the C<names> list.  If any name did not exist
3909 or could not be lstat'd, then the C<ino> field of that structure
3910 is set to C<-1>.
3911
3912 This call is intended for programs that want to efficiently
3913 list a directory contents without making many round-trips.
3914 See also C<guestfs_lxattrlist> for a similarly efficient call
3915 for getting extended attributes.  Very long directory listings
3916 might cause the protocol message size to be exceeded, causing
3917 this call to fail.  The caller must split up such requests
3918 into smaller groups of names.");
3919
3920   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3921    [], (* XXX *)
3922    "lgetxattr on multiple files",
3923    "\
3924 This call allows you to get the extended attributes
3925 of multiple files, where all files are in the directory C<path>.
3926 C<names> is the list of files from this directory.
3927
3928 On return you get a flat list of xattr structs which must be
3929 interpreted sequentially.  The first xattr struct always has a zero-length
3930 C<attrname>.  C<attrval> in this struct is zero-length
3931 to indicate there was an error doing C<lgetxattr> for this
3932 file, I<or> is a C string which is a decimal number
3933 (the number of following attributes for this file, which could
3934 be C<\"0\">).  Then after the first xattr struct are the
3935 zero or more attributes for the first named file.
3936 This repeats for the second and subsequent files.
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_lstatlist> for a similarly efficient call
3941 for getting standard stats.  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   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3947    [], (* XXX *)
3948    "readlink on multiple files",
3949    "\
3950 This call allows you to do a C<readlink> operation
3951 on 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 list of strings, with a one-to-one
3955 correspondence to the C<names> list.  Each string is the
3956 value of the symbol link.
3957
3958 If the C<readlink(2)> operation fails on any name, then
3959 the corresponding result string is the empty string C<\"\">.
3960 However the whole operation is completed even if there
3961 were C<readlink(2)> errors, and so you can call this
3962 function with names where you don't know if they are
3963 symbolic links already (albeit slightly less efficient).
3964
3965 This call is intended for programs that want to efficiently
3966 list a directory contents without making many round-trips.
3967 Very long directory listings might cause the protocol
3968 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   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3973    [InitISOFS, Always, TestOutputBuffer (
3974       [["pread"; "/known-4"; "1"; "3"]], "\n");
3975     InitISOFS, Always, TestOutputBuffer (
3976       [["pread"; "/empty"; "0"; "100"]], "")],
3977    "read part of a file",
3978    "\
3979 This command lets you read part of a file.  It reads C<count>
3980 bytes of the file, starting at C<offset>, from file C<path>.
3981
3982 This may read fewer bytes than requested.  For further details
3983 see the L<pread(2)> system call.");
3984
3985   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3986    [InitEmpty, Always, TestRun (
3987       [["part_init"; "/dev/sda"; "gpt"]])],
3988    "create an empty partition table",
3989    "\
3990 This creates an empty partition table on C<device> of one of the
3991 partition types listed below.  Usually C<parttype> should be
3992 either C<msdos> or C<gpt> (for large disks).
3993
3994 Initially there are no partitions.  Following this, you should
3995 call C<guestfs_part_add> for each partition required.
3996
3997 Possible values for C<parttype> are:
3998
3999 =over 4
4000
4001 =item B<efi> | B<gpt>
4002
4003 Intel EFI / GPT partition table.
4004
4005 This is recommended for >= 2 TB partitions that will be accessed
4006 from Linux and Intel-based Mac OS X.  It also has limited backwards
4007 compatibility with the C<mbr> format.
4008
4009 =item B<mbr> | B<msdos>
4010
4011 The standard PC \"Master Boot Record\" (MBR) format used
4012 by MS-DOS and Windows.  This partition type will B<only> work
4013 for device sizes up to 2 TB.  For large disks we recommend
4014 using C<gpt>.
4015
4016 =back
4017
4018 Other partition table types that may work but are not
4019 supported include:
4020
4021 =over 4
4022
4023 =item B<aix>
4024
4025 AIX disk labels.
4026
4027 =item B<amiga> | B<rdb>
4028
4029 Amiga \"Rigid Disk Block\" format.
4030
4031 =item B<bsd>
4032
4033 BSD disk labels.
4034
4035 =item B<dasd>
4036
4037 DASD, used on IBM mainframes.
4038
4039 =item B<dvh>
4040
4041 MIPS/SGI volumes.
4042
4043 =item B<mac>
4044
4045 Old Mac partition format.  Modern Macs use C<gpt>.
4046
4047 =item B<pc98>
4048
4049 NEC PC-98 format, common in Japan apparently.
4050
4051 =item B<sun>
4052
4053 Sun disk labels.
4054
4055 =back");
4056
4057   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4058    [InitEmpty, Always, TestRun (
4059       [["part_init"; "/dev/sda"; "mbr"];
4060        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4061     InitEmpty, Always, TestRun (
4062       [["part_init"; "/dev/sda"; "gpt"];
4063        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4064        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4065     InitEmpty, Always, TestRun (
4066       [["part_init"; "/dev/sda"; "mbr"];
4067        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4068        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4069        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4070        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4071    "add a partition to the device",
4072    "\
4073 This command adds a partition to C<device>.  If there is no partition
4074 table on the device, call C<guestfs_part_init> first.
4075
4076 The C<prlogex> parameter is the type of partition.  Normally you
4077 should pass C<p> or C<primary> here, but MBR partition tables also
4078 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4079 types.
4080
4081 C<startsect> and C<endsect> are the start and end of the partition
4082 in I<sectors>.  C<endsect> may be negative, which means it counts
4083 backwards from the end of the disk (C<-1> is the last sector).
4084
4085 Creating a partition which covers the whole disk is not so easy.
4086 Use C<guestfs_part_disk> to do that.");
4087
4088   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4089    [InitEmpty, Always, TestRun (
4090       [["part_disk"; "/dev/sda"; "mbr"]]);
4091     InitEmpty, Always, TestRun (
4092       [["part_disk"; "/dev/sda"; "gpt"]])],
4093    "partition whole disk with a single primary partition",
4094    "\
4095 This command is simply a combination of C<guestfs_part_init>
4096 followed by C<guestfs_part_add> to create a single primary partition
4097 covering the whole disk.
4098
4099 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4100 but other possible values are described in C<guestfs_part_init>.");
4101
4102   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4103    [InitEmpty, Always, TestRun (
4104       [["part_disk"; "/dev/sda"; "mbr"];
4105        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4106    "make a partition bootable",
4107    "\
4108 This sets the bootable flag on partition numbered C<partnum> on
4109 device C<device>.  Note that partitions are numbered from 1.
4110
4111 The bootable flag is used by some operating systems (notably
4112 Windows) to determine which partition to boot from.  It is by
4113 no means universally recognized.");
4114
4115   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4116    [InitEmpty, Always, TestRun (
4117       [["part_disk"; "/dev/sda"; "gpt"];
4118        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4119    "set partition name",
4120    "\
4121 This sets the partition name on partition numbered C<partnum> on
4122 device C<device>.  Note that partitions are numbered from 1.
4123
4124 The partition name can only be set on certain types of partition
4125 table.  This works on C<gpt> but not on C<mbr> partitions.");
4126
4127   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4128    [], (* XXX Add a regression test for this. *)
4129    "list partitions on a device",
4130    "\
4131 This command parses the partition table on C<device> and
4132 returns the list of partitions found.
4133
4134 The fields in the returned structure are:
4135
4136 =over 4
4137
4138 =item B<part_num>
4139
4140 Partition number, counting from 1.
4141
4142 =item B<part_start>
4143
4144 Start of the partition I<in bytes>.  To get sectors you have to
4145 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4146
4147 =item B<part_end>
4148
4149 End of the partition in bytes.
4150
4151 =item B<part_size>
4152
4153 Size of the partition in bytes.
4154
4155 =back");
4156
4157   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4158    [InitEmpty, Always, TestOutput (
4159       [["part_disk"; "/dev/sda"; "gpt"];
4160        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4161    "get the partition table type",
4162    "\
4163 This command examines the partition table on C<device> and
4164 returns the partition table type (format) being used.
4165
4166 Common return values include: C<msdos> (a DOS/Windows style MBR
4167 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4168 values are possible, although unusual.  See C<guestfs_part_init>
4169 for a full list.");
4170
4171   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4172    [InitBasicFS, Always, TestOutputBuffer (
4173       [["fill"; "0x63"; "10"; "/test"];
4174        ["read_file"; "/test"]], "cccccccccc")],
4175    "fill a file with octets",
4176    "\
4177 This command creates a new file called C<path>.  The initial
4178 content of the file is C<len> octets of C<c>, where C<c>
4179 must be a number in the range C<[0..255]>.
4180
4181 To fill a file with zero bytes (sparsely), it is
4182 much more efficient to use C<guestfs_truncate_size>.");
4183
4184   ("available", (RErr, [StringList "groups"]), 216, [],
4185    [InitNone, Always, TestRun [["available"; ""]]],
4186    "test availability of some parts of the API",
4187    "\
4188 This command is used to check the availability of some
4189 groups of functionality in the appliance, which not all builds of
4190 the libguestfs appliance will be able to provide.
4191
4192 The libguestfs groups, and the functions that those
4193 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4194
4195 The argument C<groups> is a list of group names, eg:
4196 C<[\"inotify\", \"augeas\"]> would check for the availability of
4197 the Linux inotify functions and Augeas (configuration file
4198 editing) functions.
4199
4200 The command returns no error if I<all> requested groups are available.
4201
4202 It fails with an error if one or more of the requested
4203 groups is unavailable in the appliance.
4204
4205 If an unknown group name is included in the
4206 list of groups then an error is always returned.
4207
4208 I<Notes:>
4209
4210 =over 4
4211
4212 =item *
4213
4214 You must call C<guestfs_launch> before calling this function.
4215
4216 The reason is because we don't know what groups are
4217 supported by the appliance/daemon until it is running and can
4218 be queried.
4219
4220 =item *
4221
4222 If a group of functions is available, this does not necessarily
4223 mean that they will work.  You still have to check for errors
4224 when calling individual API functions even if they are
4225 available.
4226
4227 =item *
4228
4229 It is usually the job of distro packagers to build
4230 complete functionality into the libguestfs appliance.
4231 Upstream libguestfs, if built from source with all
4232 requirements satisfied, will support everything.
4233
4234 =item *
4235
4236 This call was added in version C<1.0.80>.  In previous
4237 versions of libguestfs all you could do would be to speculatively
4238 execute a command to find out if the daemon implemented it.
4239 See also C<guestfs_version>.
4240
4241 =back");
4242
4243   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4244    [InitBasicFS, Always, TestOutputBuffer (
4245       [["write_file"; "/src"; "hello, world"; "0"];
4246        ["dd"; "/src"; "/dest"];
4247        ["read_file"; "/dest"]], "hello, world")],
4248    "copy from source to destination using dd",
4249    "\
4250 This command copies from one source device or file C<src>
4251 to another destination device or file C<dest>.  Normally you
4252 would use this to copy to or from a device or partition, for
4253 example to duplicate a filesystem.
4254
4255 If the destination is a device, it must be as large or larger
4256 than the source file or device, otherwise the copy will fail.
4257 This command cannot do partial copies (see C<guestfs_copy_size>).");
4258
4259   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4260    [InitBasicFS, Always, TestOutputInt (
4261       [["write_file"; "/file"; "hello, world"; "0"];
4262        ["filesize"; "/file"]], 12)],
4263    "return the size of the file in bytes",
4264    "\
4265 This command returns the size of C<file> in bytes.
4266
4267 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4268 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4269 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4270
4271   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4272    [InitBasicFSonLVM, Always, TestOutputList (
4273       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4274        ["lvs"]], ["/dev/VG/LV2"])],
4275    "rename an LVM logical volume",
4276    "\
4277 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4278
4279   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4280    [InitBasicFSonLVM, Always, TestOutputList (
4281       [["umount"; "/"];
4282        ["vg_activate"; "false"; "VG"];
4283        ["vgrename"; "VG"; "VG2"];
4284        ["vg_activate"; "true"; "VG2"];
4285        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4286        ["vgs"]], ["VG2"])],
4287    "rename an LVM volume group",
4288    "\
4289 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4290
4291   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4292    [InitISOFS, Always, TestOutputBuffer (
4293       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4294    "list the contents of a single file in an initrd",
4295    "\
4296 This command unpacks the file C<filename> from the initrd file
4297 called C<initrdpath>.  The filename must be given I<without> the
4298 initial C</> character.
4299
4300 For example, in guestfish you could use the following command
4301 to examine the boot script (usually called C</init>)
4302 contained in a Linux initrd or initramfs image:
4303
4304  initrd-cat /boot/initrd-<version>.img init
4305
4306 See also C<guestfs_initrd_list>.");
4307
4308   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4309    [],
4310    "get the UUID of a physical volume",
4311    "\
4312 This command returns the UUID of the LVM PV C<device>.");
4313
4314   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4315    [],
4316    "get the UUID of a volume group",
4317    "\
4318 This command returns the UUID of the LVM VG named C<vgname>.");
4319
4320   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4321    [],
4322    "get the UUID of a logical volume",
4323    "\
4324 This command returns the UUID of the LVM LV C<device>.");
4325
4326   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4327    [],
4328    "get the PV UUIDs containing the volume group",
4329    "\
4330 Given a VG called C<vgname>, this returns the UUIDs of all
4331 the physical volumes that this volume group resides on.
4332
4333 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4334 calls to associate physical volumes and volume groups.
4335
4336 See also C<guestfs_vglvuuids>.");
4337
4338   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4339    [],
4340    "get the LV UUIDs of all LVs in the volume group",
4341    "\
4342 Given a VG called C<vgname>, this returns the UUIDs of all
4343 the logical volumes created in this volume group.
4344
4345 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4346 calls to associate logical volumes and volume groups.
4347
4348 See also C<guestfs_vgpvuuids>.");
4349
4350   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4351    [InitBasicFS, Always, TestOutputBuffer (
4352       [["write_file"; "/src"; "hello, world"; "0"];
4353        ["copy_size"; "/src"; "/dest"; "5"];
4354        ["read_file"; "/dest"]], "hello")],
4355    "copy size bytes from source to destination using dd",
4356    "\
4357 This command copies exactly C<size> bytes from one source device
4358 or file C<src> to another destination device or file C<dest>.
4359
4360 Note this will fail if the source is too short or if the destination
4361 is not large enough.");
4362
4363   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4364    [InitEmpty, Always, TestRun (
4365       [["part_init"; "/dev/sda"; "mbr"];
4366        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4367        ["part_del"; "/dev/sda"; "1"]])],
4368    "delete a partition",
4369    "\
4370 This command deletes the partition numbered C<partnum> on C<device>.
4371
4372 Note that in the case of MBR partitioning, deleting an
4373 extended partition also deletes any logical partitions
4374 it contains.");
4375
4376   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4377    [InitEmpty, Always, TestOutputTrue (
4378       [["part_init"; "/dev/sda"; "mbr"];
4379        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4380        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4381        ["part_get_bootable"; "/dev/sda"; "1"]])],
4382    "return true if a partition is bootable",
4383    "\
4384 This command returns true if the partition C<partnum> on
4385 C<device> has the bootable flag set.
4386
4387 See also C<guestfs_part_set_bootable>.");
4388
4389   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4390    [InitEmpty, Always, TestOutputInt (
4391       [["part_init"; "/dev/sda"; "mbr"];
4392        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4393        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4394        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4395    "get the MBR type byte (ID byte) from a partition",
4396    "\
4397 Returns the MBR type byte (also known as the ID byte) from
4398 the numbered partition C<partnum>.
4399
4400 Note that only MBR (old DOS-style) partitions have type bytes.
4401 You will get undefined results for other partition table
4402 types (see C<guestfs_part_get_parttype>).");
4403
4404   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4405    [], (* tested by part_get_mbr_id *)
4406    "set the MBR type byte (ID byte) of a partition",
4407    "\
4408 Sets the MBR type byte (also known as the ID byte) of
4409 the numbered partition C<partnum> to C<idbyte>.  Note
4410 that the type bytes quoted in most documentation are
4411 in fact hexadecimal numbers, but usually documented
4412 without any leading \"0x\" which might be confusing.
4413
4414 Note that only MBR (old DOS-style) partitions have type bytes.
4415 You will get undefined results for other partition table
4416 types (see C<guestfs_part_get_parttype>).");
4417
4418 ]
4419
4420 let all_functions = non_daemon_functions @ daemon_functions
4421
4422 (* In some places we want the functions to be displayed sorted
4423  * alphabetically, so this is useful:
4424  *)
4425 let all_functions_sorted =
4426   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4427                compare n1 n2) all_functions
4428
4429 (* Field types for structures. *)
4430 type field =
4431   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4432   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4433   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4434   | FUInt32
4435   | FInt32
4436   | FUInt64
4437   | FInt64
4438   | FBytes                      (* Any int measure that counts bytes. *)
4439   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4440   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4441
4442 (* Because we generate extra parsing code for LVM command line tools,
4443  * we have to pull out the LVM columns separately here.
4444  *)
4445 let lvm_pv_cols = [
4446   "pv_name", FString;
4447   "pv_uuid", FUUID;
4448   "pv_fmt", FString;
4449   "pv_size", FBytes;
4450   "dev_size", FBytes;
4451   "pv_free", FBytes;
4452   "pv_used", FBytes;
4453   "pv_attr", FString (* XXX *);
4454   "pv_pe_count", FInt64;
4455   "pv_pe_alloc_count", FInt64;
4456   "pv_tags", FString;
4457   "pe_start", FBytes;
4458   "pv_mda_count", FInt64;
4459   "pv_mda_free", FBytes;
4460   (* Not in Fedora 10:
4461      "pv_mda_size", FBytes;
4462   *)
4463 ]
4464 let lvm_vg_cols = [
4465   "vg_name", FString;
4466   "vg_uuid", FUUID;
4467   "vg_fmt", FString;
4468   "vg_attr", FString (* XXX *);
4469   "vg_size", FBytes;
4470   "vg_free", FBytes;
4471   "vg_sysid", FString;
4472   "vg_extent_size", FBytes;
4473   "vg_extent_count", FInt64;
4474   "vg_free_count", FInt64;
4475   "max_lv", FInt64;
4476   "max_pv", FInt64;
4477   "pv_count", FInt64;
4478   "lv_count", FInt64;
4479   "snap_count", FInt64;
4480   "vg_seqno", FInt64;
4481   "vg_tags", FString;
4482   "vg_mda_count", FInt64;
4483   "vg_mda_free", FBytes;
4484   (* Not in Fedora 10:
4485      "vg_mda_size", FBytes;
4486   *)
4487 ]
4488 let lvm_lv_cols = [
4489   "lv_name", FString;
4490   "lv_uuid", FUUID;
4491   "lv_attr", FString (* XXX *);
4492   "lv_major", FInt64;
4493   "lv_minor", FInt64;
4494   "lv_kernel_major", FInt64;
4495   "lv_kernel_minor", FInt64;
4496   "lv_size", FBytes;
4497   "seg_count", FInt64;
4498   "origin", FString;
4499   "snap_percent", FOptPercent;
4500   "copy_percent", FOptPercent;
4501   "move_pv", FString;
4502   "lv_tags", FString;
4503   "mirror_log", FString;
4504   "modules", FString;
4505 ]
4506
4507 (* Names and fields in all structures (in RStruct and RStructList)
4508  * that we support.
4509  *)
4510 let structs = [
4511   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4512    * not use this struct in any new code.
4513    *)
4514   "int_bool", [
4515     "i", FInt32;                (* for historical compatibility *)
4516     "b", FInt32;                (* for historical compatibility *)
4517   ];
4518
4519   (* LVM PVs, VGs, LVs. *)
4520   "lvm_pv", lvm_pv_cols;
4521   "lvm_vg", lvm_vg_cols;
4522   "lvm_lv", lvm_lv_cols;
4523
4524   (* Column names and types from stat structures.
4525    * NB. Can't use things like 'st_atime' because glibc header files
4526    * define some of these as macros.  Ugh.
4527    *)
4528   "stat", [
4529     "dev", FInt64;
4530     "ino", FInt64;
4531     "mode", FInt64;
4532     "nlink", FInt64;
4533     "uid", FInt64;
4534     "gid", FInt64;
4535     "rdev", FInt64;
4536     "size", FInt64;
4537     "blksize", FInt64;
4538     "blocks", FInt64;
4539     "atime", FInt64;
4540     "mtime", FInt64;
4541     "ctime", FInt64;
4542   ];
4543   "statvfs", [
4544     "bsize", FInt64;
4545     "frsize", FInt64;
4546     "blocks", FInt64;
4547     "bfree", FInt64;
4548     "bavail", FInt64;
4549     "files", FInt64;
4550     "ffree", FInt64;
4551     "favail", FInt64;
4552     "fsid", FInt64;
4553     "flag", FInt64;
4554     "namemax", FInt64;
4555   ];
4556
4557   (* Column names in dirent structure. *)
4558   "dirent", [
4559     "ino", FInt64;
4560     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4561     "ftyp", FChar;
4562     "name", FString;
4563   ];
4564
4565   (* Version numbers. *)
4566   "version", [
4567     "major", FInt64;
4568     "minor", FInt64;
4569     "release", FInt64;
4570     "extra", FString;
4571   ];
4572
4573   (* Extended attribute. *)
4574   "xattr", [
4575     "attrname", FString;
4576     "attrval", FBuffer;
4577   ];
4578
4579   (* Inotify events. *)
4580   "inotify_event", [
4581     "in_wd", FInt64;
4582     "in_mask", FUInt32;
4583     "in_cookie", FUInt32;
4584     "in_name", FString;
4585   ];
4586
4587   (* Partition table entry. *)
4588   "partition", [
4589     "part_num", FInt32;
4590     "part_start", FBytes;
4591     "part_end", FBytes;
4592     "part_size", FBytes;
4593   ];
4594 ] (* end of structs *)
4595
4596 (* Ugh, Java has to be different ..
4597  * These names are also used by the Haskell bindings.
4598  *)
4599 let java_structs = [
4600   "int_bool", "IntBool";
4601   "lvm_pv", "PV";
4602   "lvm_vg", "VG";
4603   "lvm_lv", "LV";
4604   "stat", "Stat";
4605   "statvfs", "StatVFS";
4606   "dirent", "Dirent";
4607   "version", "Version";
4608   "xattr", "XAttr";
4609   "inotify_event", "INotifyEvent";
4610   "partition", "Partition";
4611 ]
4612
4613 (* What structs are actually returned. *)
4614 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4615
4616 (* Returns a list of RStruct/RStructList structs that are returned
4617  * by any function.  Each element of returned list is a pair:
4618  *
4619  * (structname, RStructOnly)
4620  *    == there exists function which returns RStruct (_, structname)
4621  * (structname, RStructListOnly)
4622  *    == there exists function which returns RStructList (_, structname)
4623  * (structname, RStructAndList)
4624  *    == there are functions returning both RStruct (_, structname)
4625  *                                      and RStructList (_, structname)
4626  *)
4627 let rstructs_used_by functions =
4628   (* ||| is a "logical OR" for rstructs_used_t *)
4629   let (|||) a b =
4630     match a, b with
4631     | RStructAndList, _
4632     | _, RStructAndList -> RStructAndList
4633     | RStructOnly, RStructListOnly
4634     | RStructListOnly, RStructOnly -> RStructAndList
4635     | RStructOnly, RStructOnly -> RStructOnly
4636     | RStructListOnly, RStructListOnly -> RStructListOnly
4637   in
4638
4639   let h = Hashtbl.create 13 in
4640
4641   (* if elem->oldv exists, update entry using ||| operator,
4642    * else just add elem->newv to the hash
4643    *)
4644   let update elem newv =
4645     try  let oldv = Hashtbl.find h elem in
4646          Hashtbl.replace h elem (newv ||| oldv)
4647     with Not_found -> Hashtbl.add h elem newv
4648   in
4649
4650   List.iter (
4651     fun (_, style, _, _, _, _, _) ->
4652       match fst style with
4653       | RStruct (_, structname) -> update structname RStructOnly
4654       | RStructList (_, structname) -> update structname RStructListOnly
4655       | _ -> ()
4656   ) functions;
4657
4658   (* return key->values as a list of (key,value) *)
4659   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4660
4661 (* Used for testing language bindings. *)
4662 type callt =
4663   | CallString of string
4664   | CallOptString of string option
4665   | CallStringList of string list
4666   | CallInt of int
4667   | CallInt64 of int64
4668   | CallBool of bool
4669
4670 (* Used to memoize the result of pod2text. *)
4671 let pod2text_memo_filename = "src/.pod2text.data"
4672 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4673   try
4674     let chan = open_in pod2text_memo_filename in
4675     let v = input_value chan in
4676     close_in chan;
4677     v
4678   with
4679     _ -> Hashtbl.create 13
4680 let pod2text_memo_updated () =
4681   let chan = open_out pod2text_memo_filename in
4682   output_value chan pod2text_memo;
4683   close_out chan
4684
4685 (* Useful functions.
4686  * Note we don't want to use any external OCaml libraries which
4687  * makes this a bit harder than it should be.
4688  *)
4689 module StringMap = Map.Make (String)
4690
4691 let failwithf fs = ksprintf failwith fs
4692
4693 let unique = let i = ref 0 in fun () -> incr i; !i
4694
4695 let replace_char s c1 c2 =
4696   let s2 = String.copy s in
4697   let r = ref false in
4698   for i = 0 to String.length s2 - 1 do
4699     if String.unsafe_get s2 i = c1 then (
4700       String.unsafe_set s2 i c2;
4701       r := true
4702     )
4703   done;
4704   if not !r then s else s2
4705
4706 let isspace c =
4707   c = ' '
4708   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4709
4710 let triml ?(test = isspace) str =
4711   let i = ref 0 in
4712   let n = ref (String.length str) in
4713   while !n > 0 && test str.[!i]; do
4714     decr n;
4715     incr i
4716   done;
4717   if !i = 0 then str
4718   else String.sub str !i !n
4719
4720 let trimr ?(test = isspace) str =
4721   let n = ref (String.length str) in
4722   while !n > 0 && test str.[!n-1]; do
4723     decr n
4724   done;
4725   if !n = String.length str then str
4726   else String.sub str 0 !n
4727
4728 let trim ?(test = isspace) str =
4729   trimr ~test (triml ~test str)
4730
4731 let rec find s sub =
4732   let len = String.length s in
4733   let sublen = String.length sub in
4734   let rec loop i =
4735     if i <= len-sublen then (
4736       let rec loop2 j =
4737         if j < sublen then (
4738           if s.[i+j] = sub.[j] then loop2 (j+1)
4739           else -1
4740         ) else
4741           i (* found *)
4742       in
4743       let r = loop2 0 in
4744       if r = -1 then loop (i+1) else r
4745     ) else
4746       -1 (* not found *)
4747   in
4748   loop 0
4749
4750 let rec replace_str s s1 s2 =
4751   let len = String.length s in
4752   let sublen = String.length s1 in
4753   let i = find s s1 in
4754   if i = -1 then s
4755   else (
4756     let s' = String.sub s 0 i in
4757     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4758     s' ^ s2 ^ replace_str s'' s1 s2
4759   )
4760
4761 let rec string_split sep str =
4762   let len = String.length str in
4763   let seplen = String.length sep in
4764   let i = find str sep in
4765   if i = -1 then [str]
4766   else (
4767     let s' = String.sub str 0 i in
4768     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4769     s' :: string_split sep s''
4770   )
4771
4772 let files_equal n1 n2 =
4773   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4774   match Sys.command cmd with
4775   | 0 -> true
4776   | 1 -> false
4777   | i -> failwithf "%s: failed with error code %d" cmd i
4778
4779 let rec filter_map f = function
4780   | [] -> []
4781   | x :: xs ->
4782       match f x with
4783       | Some y -> y :: filter_map f xs
4784       | None -> filter_map f xs
4785
4786 let rec find_map f = function
4787   | [] -> raise Not_found
4788   | x :: xs ->
4789       match f x with
4790       | Some y -> y
4791       | None -> find_map f xs
4792
4793 let iteri f xs =
4794   let rec loop i = function
4795     | [] -> ()
4796     | x :: xs -> f i x; loop (i+1) xs
4797   in
4798   loop 0 xs
4799
4800 let mapi f xs =
4801   let rec loop i = function
4802     | [] -> []
4803     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4804   in
4805   loop 0 xs
4806
4807 let count_chars c str =
4808   let count = ref 0 in
4809   for i = 0 to String.length str - 1 do
4810     if c = String.unsafe_get str i then incr count
4811   done;
4812   !count
4813
4814 let name_of_argt = function
4815   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4816   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4817   | FileIn n | FileOut n -> n
4818
4819 let java_name_of_struct typ =
4820   try List.assoc typ java_structs
4821   with Not_found ->
4822     failwithf
4823       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4824
4825 let cols_of_struct typ =
4826   try List.assoc typ structs
4827   with Not_found ->
4828     failwithf "cols_of_struct: unknown struct %s" typ
4829
4830 let seq_of_test = function
4831   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4832   | TestOutputListOfDevices (s, _)
4833   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4834   | TestOutputTrue s | TestOutputFalse s
4835   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4836   | TestOutputStruct (s, _)
4837   | TestLastFail s -> s
4838
4839 (* Handling for function flags. *)
4840 let protocol_limit_warning =
4841   "Because of the message protocol, there is a transfer limit
4842 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4843
4844 let danger_will_robinson =
4845   "B<This command is dangerous.  Without careful use you
4846 can easily destroy all your data>."
4847
4848 let deprecation_notice flags =
4849   try
4850     let alt =
4851       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4852     let txt =
4853       sprintf "This function is deprecated.
4854 In new code, use the C<%s> call instead.
4855
4856 Deprecated functions will not be removed from the API, but the
4857 fact that they are deprecated indicates that there are problems
4858 with correct use of these functions." alt in
4859     Some txt
4860   with
4861     Not_found -> None
4862
4863 (* Create list of optional groups. *)
4864 let optgroups =
4865   let h = Hashtbl.create 13 in
4866   List.iter (
4867     fun (name, _, _, flags, _, _, _) ->
4868       List.iter (
4869         function
4870         | Optional group ->
4871             let names = try Hashtbl.find h group with Not_found -> [] in
4872             Hashtbl.replace h group (name :: names)
4873         | _ -> ()
4874       ) flags
4875   ) daemon_functions;
4876   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4877   let groups =
4878     List.map (
4879       fun group -> group, List.sort compare (Hashtbl.find h group)
4880     ) groups in
4881   List.sort (fun x y -> compare (fst x) (fst y)) groups
4882
4883 (* Check function names etc. for consistency. *)
4884 let check_functions () =
4885   let contains_uppercase str =
4886     let len = String.length str in
4887     let rec loop i =
4888       if i >= len then false
4889       else (
4890         let c = str.[i] in
4891         if c >= 'A' && c <= 'Z' then true
4892         else loop (i+1)
4893       )
4894     in
4895     loop 0
4896   in
4897
4898   (* Check function names. *)
4899   List.iter (
4900     fun (name, _, _, _, _, _, _) ->
4901       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4902         failwithf "function name %s does not need 'guestfs' prefix" name;
4903       if name = "" then
4904         failwithf "function name is empty";
4905       if name.[0] < 'a' || name.[0] > 'z' then
4906         failwithf "function name %s must start with lowercase a-z" name;
4907       if String.contains name '-' then
4908         failwithf "function name %s should not contain '-', use '_' instead."
4909           name
4910   ) all_functions;
4911
4912   (* Check function parameter/return names. *)
4913   List.iter (
4914     fun (name, style, _, _, _, _, _) ->
4915       let check_arg_ret_name n =
4916         if contains_uppercase n then
4917           failwithf "%s param/ret %s should not contain uppercase chars"
4918             name n;
4919         if String.contains n '-' || String.contains n '_' then
4920           failwithf "%s param/ret %s should not contain '-' or '_'"
4921             name n;
4922         if n = "value" then
4923           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;
4924         if n = "int" || n = "char" || n = "short" || n = "long" then
4925           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4926         if n = "i" || n = "n" then
4927           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4928         if n = "argv" || n = "args" then
4929           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4930
4931         (* List Haskell, OCaml and C keywords here.
4932          * http://www.haskell.org/haskellwiki/Keywords
4933          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4934          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4935          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4936          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4937          * Omitting _-containing words, since they're handled above.
4938          * Omitting the OCaml reserved word, "val", is ok,
4939          * and saves us from renaming several parameters.
4940          *)
4941         let reserved = [
4942           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4943           "char"; "class"; "const"; "constraint"; "continue"; "data";
4944           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4945           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4946           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4947           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4948           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4949           "interface";
4950           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4951           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4952           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4953           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4954           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4955           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4956           "volatile"; "when"; "where"; "while";
4957           ] in
4958         if List.mem n reserved then
4959           failwithf "%s has param/ret using reserved word %s" name n;
4960       in
4961
4962       (match fst style with
4963        | RErr -> ()
4964        | RInt n | RInt64 n | RBool n
4965        | RConstString n | RConstOptString n | RString n
4966        | RStringList n | RStruct (n, _) | RStructList (n, _)
4967        | RHashtable n | RBufferOut n ->
4968            check_arg_ret_name n
4969       );
4970       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4971   ) all_functions;
4972
4973   (* Check short descriptions. *)
4974   List.iter (
4975     fun (name, _, _, _, _, shortdesc, _) ->
4976       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4977         failwithf "short description of %s should begin with lowercase." name;
4978       let c = shortdesc.[String.length shortdesc-1] in
4979       if c = '\n' || c = '.' then
4980         failwithf "short description of %s should not end with . or \\n." name
4981   ) all_functions;
4982
4983   (* Check long descriptions. *)
4984   List.iter (
4985     fun (name, _, _, _, _, _, longdesc) ->
4986       if longdesc.[String.length longdesc-1] = '\n' then
4987         failwithf "long description of %s should not end with \\n." name
4988   ) all_functions;
4989
4990   (* Check proc_nrs. *)
4991   List.iter (
4992     fun (name, _, proc_nr, _, _, _, _) ->
4993       if proc_nr <= 0 then
4994         failwithf "daemon function %s should have proc_nr > 0" name
4995   ) daemon_functions;
4996
4997   List.iter (
4998     fun (name, _, proc_nr, _, _, _, _) ->
4999       if proc_nr <> -1 then
5000         failwithf "non-daemon function %s should have proc_nr -1" name
5001   ) non_daemon_functions;
5002
5003   let proc_nrs =
5004     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5005       daemon_functions in
5006   let proc_nrs =
5007     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5008   let rec loop = function
5009     | [] -> ()
5010     | [_] -> ()
5011     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5012         loop rest
5013     | (name1,nr1) :: (name2,nr2) :: _ ->
5014         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5015           name1 name2 nr1 nr2
5016   in
5017   loop proc_nrs;
5018
5019   (* Check tests. *)
5020   List.iter (
5021     function
5022       (* Ignore functions that have no tests.  We generate a
5023        * warning when the user does 'make check' instead.
5024        *)
5025     | name, _, _, _, [], _, _ -> ()
5026     | name, _, _, _, tests, _, _ ->
5027         let funcs =
5028           List.map (
5029             fun (_, _, test) ->
5030               match seq_of_test test with
5031               | [] ->
5032                   failwithf "%s has a test containing an empty sequence" name
5033               | cmds -> List.map List.hd cmds
5034           ) tests in
5035         let funcs = List.flatten funcs in
5036
5037         let tested = List.mem name funcs in
5038
5039         if not tested then
5040           failwithf "function %s has tests but does not test itself" name
5041   ) all_functions
5042
5043 (* 'pr' prints to the current output file. *)
5044 let chan = ref Pervasives.stdout
5045 let lines = ref 0
5046 let pr fs =
5047   ksprintf
5048     (fun str ->
5049        let i = count_chars '\n' str in
5050        lines := !lines + i;
5051        output_string !chan str
5052     ) fs
5053
5054 let copyright_years =
5055   let this_year = 1900 + (localtime (time ())).tm_year in
5056   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5057
5058 (* Generate a header block in a number of standard styles. *)
5059 type comment_style =
5060     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5061 type license = GPLv2plus | LGPLv2plus
5062
5063 let generate_header ?(extra_inputs = []) comment license =
5064   let inputs = "src/generator.ml" :: extra_inputs in
5065   let c = match comment with
5066     | CStyle ->         pr "/* "; " *"
5067     | CPlusPlusStyle -> pr "// "; "//"
5068     | HashStyle ->      pr "# ";  "#"
5069     | OCamlStyle ->     pr "(* "; " *"
5070     | HaskellStyle ->   pr "{- "; "  " in
5071   pr "libguestfs generated file\n";
5072   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5073   List.iter (pr "%s   %s\n" c) inputs;
5074   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5075   pr "%s\n" c;
5076   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5077   pr "%s\n" c;
5078   (match license with
5079    | GPLv2plus ->
5080        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5081        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5082        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5083        pr "%s (at your option) any later version.\n" c;
5084        pr "%s\n" c;
5085        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5086        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5087        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5088        pr "%s GNU General Public License for more details.\n" c;
5089        pr "%s\n" c;
5090        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5091        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5092        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5093
5094    | LGPLv2plus ->
5095        pr "%s This library is free software; you can redistribute it and/or\n" c;
5096        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5097        pr "%s License as published by the Free Software Foundation; either\n" c;
5098        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5099        pr "%s\n" c;
5100        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5101        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5102        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5103        pr "%s Lesser General Public License for more details.\n" c;
5104        pr "%s\n" c;
5105        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5106        pr "%s License along with this library; if not, write to the Free Software\n" c;
5107        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5108   );
5109   (match comment with
5110    | CStyle -> pr " */\n"
5111    | CPlusPlusStyle
5112    | HashStyle -> ()
5113    | OCamlStyle -> pr " *)\n"
5114    | HaskellStyle -> pr "-}\n"
5115   );
5116   pr "\n"
5117
5118 (* Start of main code generation functions below this line. *)
5119
5120 (* Generate the pod documentation for the C API. *)
5121 let rec generate_actions_pod () =
5122   List.iter (
5123     fun (shortname, style, _, flags, _, _, longdesc) ->
5124       if not (List.mem NotInDocs flags) then (
5125         let name = "guestfs_" ^ shortname in
5126         pr "=head2 %s\n\n" name;
5127         pr " ";
5128         generate_prototype ~extern:false ~handle:"g" name style;
5129         pr "\n\n";
5130         pr "%s\n\n" longdesc;
5131         (match fst style with
5132          | RErr ->
5133              pr "This function returns 0 on success or -1 on error.\n\n"
5134          | RInt _ ->
5135              pr "On error this function returns -1.\n\n"
5136          | RInt64 _ ->
5137              pr "On error this function returns -1.\n\n"
5138          | RBool _ ->
5139              pr "This function returns a C truth value on success or -1 on error.\n\n"
5140          | RConstString _ ->
5141              pr "This function returns a string, or NULL on error.
5142 The string is owned by the guest handle and must I<not> be freed.\n\n"
5143          | RConstOptString _ ->
5144              pr "This function returns a string which may be NULL.
5145 There is way to return an error from this function.
5146 The string is owned by the guest handle and must I<not> be freed.\n\n"
5147          | RString _ ->
5148              pr "This function returns a string, or NULL on error.
5149 I<The caller must free the returned string after use>.\n\n"
5150          | RStringList _ ->
5151              pr "This function returns a NULL-terminated array of strings
5152 (like L<environ(3)>), or NULL if there was an error.
5153 I<The caller must free the strings and the array after use>.\n\n"
5154          | RStruct (_, typ) ->
5155              pr "This function returns a C<struct guestfs_%s *>,
5156 or NULL if there was an error.
5157 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5158          | RStructList (_, typ) ->
5159              pr "This function returns a C<struct guestfs_%s_list *>
5160 (see E<lt>guestfs-structs.hE<gt>),
5161 or NULL if there was an error.
5162 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5163          | RHashtable _ ->
5164              pr "This function returns a NULL-terminated array of
5165 strings, or NULL if there was an error.
5166 The array of strings will always have length C<2n+1>, where
5167 C<n> keys and values alternate, followed by the trailing NULL entry.
5168 I<The caller must free the strings and the array after use>.\n\n"
5169          | RBufferOut _ ->
5170              pr "This function returns a buffer, or NULL on error.
5171 The size of the returned buffer is written to C<*size_r>.
5172 I<The caller must free the returned buffer after use>.\n\n"
5173         );
5174         if List.mem ProtocolLimitWarning flags then
5175           pr "%s\n\n" protocol_limit_warning;
5176         if List.mem DangerWillRobinson flags then
5177           pr "%s\n\n" danger_will_robinson;
5178         match deprecation_notice flags with
5179         | None -> ()
5180         | Some txt -> pr "%s\n\n" txt
5181       )
5182   ) all_functions_sorted
5183
5184 and generate_structs_pod () =
5185   (* Structs documentation. *)
5186   List.iter (
5187     fun (typ, cols) ->
5188       pr "=head2 guestfs_%s\n" typ;
5189       pr "\n";
5190       pr " struct guestfs_%s {\n" typ;
5191       List.iter (
5192         function
5193         | name, FChar -> pr "   char %s;\n" name
5194         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5195         | name, FInt32 -> pr "   int32_t %s;\n" name
5196         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5197         | name, FInt64 -> pr "   int64_t %s;\n" name
5198         | name, FString -> pr "   char *%s;\n" name
5199         | name, FBuffer ->
5200             pr "   /* The next two fields describe a byte array. */\n";
5201             pr "   uint32_t %s_len;\n" name;
5202             pr "   char *%s;\n" name
5203         | name, FUUID ->
5204             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5205             pr "   char %s[32];\n" name
5206         | name, FOptPercent ->
5207             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5208             pr "   float %s;\n" name
5209       ) cols;
5210       pr " };\n";
5211       pr " \n";
5212       pr " struct guestfs_%s_list {\n" typ;
5213       pr "   uint32_t len; /* Number of elements in list. */\n";
5214       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5215       pr " };\n";
5216       pr " \n";
5217       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5218       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5219         typ typ;
5220       pr "\n"
5221   ) structs
5222
5223 and generate_availability_pod () =
5224   (* Availability documentation. *)
5225   pr "=over 4\n";
5226   pr "\n";
5227   List.iter (
5228     fun (group, functions) ->
5229       pr "=item B<%s>\n" group;
5230       pr "\n";
5231       pr "The following functions:\n";
5232       List.iter (pr "L</guestfs_%s>\n") functions;
5233       pr "\n"
5234   ) optgroups;
5235   pr "=back\n";
5236   pr "\n"
5237
5238 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5239  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5240  *
5241  * We have to use an underscore instead of a dash because otherwise
5242  * rpcgen generates incorrect code.
5243  *
5244  * This header is NOT exported to clients, but see also generate_structs_h.
5245  *)
5246 and generate_xdr () =
5247   generate_header CStyle LGPLv2plus;
5248
5249   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5250   pr "typedef string str<>;\n";
5251   pr "\n";
5252
5253   (* Internal structures. *)
5254   List.iter (
5255     function
5256     | typ, cols ->
5257         pr "struct guestfs_int_%s {\n" typ;
5258         List.iter (function
5259                    | name, FChar -> pr "  char %s;\n" name
5260                    | name, FString -> pr "  string %s<>;\n" name
5261                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5262                    | name, FUUID -> pr "  opaque %s[32];\n" name
5263                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5264                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5265                    | name, FOptPercent -> pr "  float %s;\n" name
5266                   ) cols;
5267         pr "};\n";
5268         pr "\n";
5269         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5270         pr "\n";
5271   ) structs;
5272
5273   List.iter (
5274     fun (shortname, style, _, _, _, _, _) ->
5275       let name = "guestfs_" ^ shortname in
5276
5277       (match snd style with
5278        | [] -> ()
5279        | args ->
5280            pr "struct %s_args {\n" name;
5281            List.iter (
5282              function
5283              | Pathname n | Device n | Dev_or_Path n | String n ->
5284                  pr "  string %s<>;\n" n
5285              | OptString n -> pr "  str *%s;\n" n
5286              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5287              | Bool n -> pr "  bool %s;\n" n
5288              | Int n -> pr "  int %s;\n" n
5289              | Int64 n -> pr "  hyper %s;\n" n
5290              | FileIn _ | FileOut _ -> ()
5291            ) args;
5292            pr "};\n\n"
5293       );
5294       (match fst style with
5295        | RErr -> ()
5296        | RInt n ->
5297            pr "struct %s_ret {\n" name;
5298            pr "  int %s;\n" n;
5299            pr "};\n\n"
5300        | RInt64 n ->
5301            pr "struct %s_ret {\n" name;
5302            pr "  hyper %s;\n" n;
5303            pr "};\n\n"
5304        | RBool n ->
5305            pr "struct %s_ret {\n" name;
5306            pr "  bool %s;\n" n;
5307            pr "};\n\n"
5308        | RConstString _ | RConstOptString _ ->
5309            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5310        | RString n ->
5311            pr "struct %s_ret {\n" name;
5312            pr "  string %s<>;\n" n;
5313            pr "};\n\n"
5314        | RStringList n ->
5315            pr "struct %s_ret {\n" name;
5316            pr "  str %s<>;\n" n;
5317            pr "};\n\n"
5318        | RStruct (n, typ) ->
5319            pr "struct %s_ret {\n" name;
5320            pr "  guestfs_int_%s %s;\n" typ n;
5321            pr "};\n\n"
5322        | RStructList (n, typ) ->
5323            pr "struct %s_ret {\n" name;
5324            pr "  guestfs_int_%s_list %s;\n" typ n;
5325            pr "};\n\n"
5326        | RHashtable n ->
5327            pr "struct %s_ret {\n" name;
5328            pr "  str %s<>;\n" n;
5329            pr "};\n\n"
5330        | RBufferOut n ->
5331            pr "struct %s_ret {\n" name;
5332            pr "  opaque %s<>;\n" n;
5333            pr "};\n\n"
5334       );
5335   ) daemon_functions;
5336
5337   (* Table of procedure numbers. *)
5338   pr "enum guestfs_procedure {\n";
5339   List.iter (
5340     fun (shortname, _, proc_nr, _, _, _, _) ->
5341       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5342   ) daemon_functions;
5343   pr "  GUESTFS_PROC_NR_PROCS\n";
5344   pr "};\n";
5345   pr "\n";
5346
5347   (* Having to choose a maximum message size is annoying for several
5348    * reasons (it limits what we can do in the API), but it (a) makes
5349    * the protocol a lot simpler, and (b) provides a bound on the size
5350    * of the daemon which operates in limited memory space.
5351    *)
5352   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5353   pr "\n";
5354
5355   (* Message header, etc. *)
5356   pr "\
5357 /* The communication protocol is now documented in the guestfs(3)
5358  * manpage.
5359  */
5360
5361 const GUESTFS_PROGRAM = 0x2000F5F5;
5362 const GUESTFS_PROTOCOL_VERSION = 1;
5363
5364 /* These constants must be larger than any possible message length. */
5365 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5366 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5367
5368 enum guestfs_message_direction {
5369   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5370   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5371 };
5372
5373 enum guestfs_message_status {
5374   GUESTFS_STATUS_OK = 0,
5375   GUESTFS_STATUS_ERROR = 1
5376 };
5377
5378 const GUESTFS_ERROR_LEN = 256;
5379
5380 struct guestfs_message_error {
5381   string error_message<GUESTFS_ERROR_LEN>;
5382 };
5383
5384 struct guestfs_message_header {
5385   unsigned prog;                     /* GUESTFS_PROGRAM */
5386   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5387   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5388   guestfs_message_direction direction;
5389   unsigned serial;                   /* message serial number */
5390   guestfs_message_status status;
5391 };
5392
5393 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5394
5395 struct guestfs_chunk {
5396   int cancel;                        /* if non-zero, transfer is cancelled */
5397   /* data size is 0 bytes if the transfer has finished successfully */
5398   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5399 };
5400 "
5401
5402 (* Generate the guestfs-structs.h file. *)
5403 and generate_structs_h () =
5404   generate_header CStyle LGPLv2plus;
5405
5406   (* This is a public exported header file containing various
5407    * structures.  The structures are carefully written to have
5408    * exactly the same in-memory format as the XDR structures that
5409    * we use on the wire to the daemon.  The reason for creating
5410    * copies of these structures here is just so we don't have to
5411    * export the whole of guestfs_protocol.h (which includes much
5412    * unrelated and XDR-dependent stuff that we don't want to be
5413    * public, or required by clients).
5414    *
5415    * To reiterate, we will pass these structures to and from the
5416    * client with a simple assignment or memcpy, so the format
5417    * must be identical to what rpcgen / the RFC defines.
5418    *)
5419
5420   (* Public structures. *)
5421   List.iter (
5422     fun (typ, cols) ->
5423       pr "struct guestfs_%s {\n" typ;
5424       List.iter (
5425         function
5426         | name, FChar -> pr "  char %s;\n" name
5427         | name, FString -> pr "  char *%s;\n" name
5428         | name, FBuffer ->
5429             pr "  uint32_t %s_len;\n" name;
5430             pr "  char *%s;\n" name
5431         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5432         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5433         | name, FInt32 -> pr "  int32_t %s;\n" name
5434         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5435         | name, FInt64 -> pr "  int64_t %s;\n" name
5436         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5437       ) cols;
5438       pr "};\n";
5439       pr "\n";
5440       pr "struct guestfs_%s_list {\n" typ;
5441       pr "  uint32_t len;\n";
5442       pr "  struct guestfs_%s *val;\n" typ;
5443       pr "};\n";
5444       pr "\n";
5445       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5446       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5447       pr "\n"
5448   ) structs
5449
5450 (* Generate the guestfs-actions.h file. *)
5451 and generate_actions_h () =
5452   generate_header CStyle LGPLv2plus;
5453   List.iter (
5454     fun (shortname, style, _, _, _, _, _) ->
5455       let name = "guestfs_" ^ shortname in
5456       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5457         name style
5458   ) all_functions
5459
5460 (* Generate the guestfs-internal-actions.h file. *)
5461 and generate_internal_actions_h () =
5462   generate_header CStyle LGPLv2plus;
5463   List.iter (
5464     fun (shortname, style, _, _, _, _, _) ->
5465       let name = "guestfs__" ^ shortname in
5466       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5467         name style
5468   ) non_daemon_functions
5469
5470 (* Generate the client-side dispatch stubs. *)
5471 and generate_client_actions () =
5472   generate_header CStyle LGPLv2plus;
5473
5474   pr "\
5475 #include <stdio.h>
5476 #include <stdlib.h>
5477 #include <stdint.h>
5478 #include <string.h>
5479 #include <inttypes.h>
5480
5481 #include \"guestfs.h\"
5482 #include \"guestfs-internal.h\"
5483 #include \"guestfs-internal-actions.h\"
5484 #include \"guestfs_protocol.h\"
5485
5486 #define error guestfs_error
5487 //#define perrorf guestfs_perrorf
5488 #define safe_malloc guestfs_safe_malloc
5489 #define safe_realloc guestfs_safe_realloc
5490 //#define safe_strdup guestfs_safe_strdup
5491 #define safe_memdup guestfs_safe_memdup
5492
5493 /* Check the return message from a call for validity. */
5494 static int
5495 check_reply_header (guestfs_h *g,
5496                     const struct guestfs_message_header *hdr,
5497                     unsigned int proc_nr, unsigned int serial)
5498 {
5499   if (hdr->prog != GUESTFS_PROGRAM) {
5500     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5501     return -1;
5502   }
5503   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5504     error (g, \"wrong protocol version (%%d/%%d)\",
5505            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5506     return -1;
5507   }
5508   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5509     error (g, \"unexpected message direction (%%d/%%d)\",
5510            hdr->direction, GUESTFS_DIRECTION_REPLY);
5511     return -1;
5512   }
5513   if (hdr->proc != proc_nr) {
5514     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5515     return -1;
5516   }
5517   if (hdr->serial != serial) {
5518     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5519     return -1;
5520   }
5521
5522   return 0;
5523 }
5524
5525 /* Check we are in the right state to run a high-level action. */
5526 static int
5527 check_state (guestfs_h *g, const char *caller)
5528 {
5529   if (!guestfs__is_ready (g)) {
5530     if (guestfs__is_config (g) || guestfs__is_launching (g))
5531       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5532         caller);
5533     else
5534       error (g, \"%%s called from the wrong state, %%d != READY\",
5535         caller, guestfs__get_state (g));
5536     return -1;
5537   }
5538   return 0;
5539 }
5540
5541 ";
5542
5543   (* Generate code to generate guestfish call traces. *)
5544   let trace_call shortname style =
5545     pr "  if (guestfs__get_trace (g)) {\n";
5546
5547     let needs_i =
5548       List.exists (function
5549                    | StringList _ | DeviceList _ -> true
5550                    | _ -> false) (snd style) in
5551     if needs_i then (
5552       pr "    int i;\n";
5553       pr "\n"
5554     );
5555
5556     pr "    printf (\"%s\");\n" shortname;
5557     List.iter (
5558       function
5559       | String n                        (* strings *)
5560       | Device n
5561       | Pathname n
5562       | Dev_or_Path n
5563       | FileIn n
5564       | FileOut n ->
5565           (* guestfish doesn't support string escaping, so neither do we *)
5566           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5567       | OptString n ->                  (* string option *)
5568           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5569           pr "    else printf (\" null\");\n"
5570       | StringList n
5571       | DeviceList n ->                 (* string list *)
5572           pr "    putchar (' ');\n";
5573           pr "    putchar ('\"');\n";
5574           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5575           pr "      if (i > 0) putchar (' ');\n";
5576           pr "      fputs (%s[i], stdout);\n" n;
5577           pr "    }\n";
5578           pr "    putchar ('\"');\n";
5579       | Bool n ->                       (* boolean *)
5580           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5581       | Int n ->                        (* int *)
5582           pr "    printf (\" %%d\", %s);\n" n
5583       | Int64 n ->
5584           pr "    printf (\" %%\" PRIi64, %s);\n" n
5585     ) (snd style);
5586     pr "    putchar ('\\n');\n";
5587     pr "  }\n";
5588     pr "\n";
5589   in
5590
5591   (* For non-daemon functions, generate a wrapper around each function. *)
5592   List.iter (
5593     fun (shortname, style, _, _, _, _, _) ->
5594       let name = "guestfs_" ^ shortname in
5595
5596       generate_prototype ~extern:false ~semicolon:false ~newline:true
5597         ~handle:"g" name style;
5598       pr "{\n";
5599       trace_call shortname style;
5600       pr "  return guestfs__%s " shortname;
5601       generate_c_call_args ~handle:"g" style;
5602       pr ";\n";
5603       pr "}\n";
5604       pr "\n"
5605   ) non_daemon_functions;
5606
5607   (* Client-side stubs for each function. *)
5608   List.iter (
5609     fun (shortname, style, _, _, _, _, _) ->
5610       let name = "guestfs_" ^ shortname in
5611
5612       (* Generate the action stub. *)
5613       generate_prototype ~extern:false ~semicolon:false ~newline:true
5614         ~handle:"g" name style;
5615
5616       let error_code =
5617         match fst style with
5618         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5619         | RConstString _ | RConstOptString _ ->
5620             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5621         | RString _ | RStringList _
5622         | RStruct _ | RStructList _
5623         | RHashtable _ | RBufferOut _ ->
5624             "NULL" in
5625
5626       pr "{\n";
5627
5628       (match snd style with
5629        | [] -> ()
5630        | _ -> pr "  struct %s_args args;\n" name
5631       );
5632
5633       pr "  guestfs_message_header hdr;\n";
5634       pr "  guestfs_message_error err;\n";
5635       let has_ret =
5636         match fst style with
5637         | RErr -> false
5638         | RConstString _ | RConstOptString _ ->
5639             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5640         | RInt _ | RInt64 _
5641         | RBool _ | RString _ | RStringList _
5642         | RStruct _ | RStructList _
5643         | RHashtable _ | RBufferOut _ ->
5644             pr "  struct %s_ret ret;\n" name;
5645             true in
5646
5647       pr "  int serial;\n";
5648       pr "  int r;\n";
5649       pr "\n";
5650       trace_call shortname style;
5651       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5652       pr "  guestfs___set_busy (g);\n";
5653       pr "\n";
5654
5655       (* Send the main header and arguments. *)
5656       (match snd style with
5657        | [] ->
5658            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5659              (String.uppercase shortname)
5660        | args ->
5661            List.iter (
5662              function
5663              | Pathname n | Device n | Dev_or_Path n | String n ->
5664                  pr "  args.%s = (char *) %s;\n" n n
5665              | OptString n ->
5666                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5667              | StringList n | DeviceList n ->
5668                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5669                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5670              | Bool n ->
5671                  pr "  args.%s = %s;\n" n n
5672              | Int n ->
5673                  pr "  args.%s = %s;\n" n n
5674              | Int64 n ->
5675                  pr "  args.%s = %s;\n" n n
5676              | FileIn _ | FileOut _ -> ()
5677            ) args;
5678            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5679              (String.uppercase shortname);
5680            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5681              name;
5682       );
5683       pr "  if (serial == -1) {\n";
5684       pr "    guestfs___end_busy (g);\n";
5685       pr "    return %s;\n" error_code;
5686       pr "  }\n";
5687       pr "\n";
5688
5689       (* Send any additional files (FileIn) requested. *)
5690       let need_read_reply_label = ref false in
5691       List.iter (
5692         function
5693         | FileIn n ->
5694             pr "  r = guestfs___send_file (g, %s);\n" n;
5695             pr "  if (r == -1) {\n";
5696             pr "    guestfs___end_busy (g);\n";
5697             pr "    return %s;\n" error_code;
5698             pr "  }\n";
5699             pr "  if (r == -2) /* daemon cancelled */\n";
5700             pr "    goto read_reply;\n";
5701             need_read_reply_label := true;
5702             pr "\n";
5703         | _ -> ()
5704       ) (snd style);
5705
5706       (* Wait for the reply from the remote end. *)
5707       if !need_read_reply_label then pr " read_reply:\n";
5708       pr "  memset (&hdr, 0, sizeof hdr);\n";
5709       pr "  memset (&err, 0, sizeof err);\n";
5710       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5711       pr "\n";
5712       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5713       if not has_ret then
5714         pr "NULL, NULL"
5715       else
5716         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5717       pr ");\n";
5718
5719       pr "  if (r == -1) {\n";
5720       pr "    guestfs___end_busy (g);\n";
5721       pr "    return %s;\n" error_code;
5722       pr "  }\n";
5723       pr "\n";
5724
5725       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5726         (String.uppercase shortname);
5727       pr "    guestfs___end_busy (g);\n";
5728       pr "    return %s;\n" error_code;
5729       pr "  }\n";
5730       pr "\n";
5731
5732       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5733       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5734       pr "    free (err.error_message);\n";
5735       pr "    guestfs___end_busy (g);\n";
5736       pr "    return %s;\n" error_code;
5737       pr "  }\n";
5738       pr "\n";
5739
5740       (* Expecting to receive further files (FileOut)? *)
5741       List.iter (
5742         function
5743         | FileOut n ->
5744             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5745             pr "    guestfs___end_busy (g);\n";
5746             pr "    return %s;\n" error_code;
5747             pr "  }\n";
5748             pr "\n";
5749         | _ -> ()
5750       ) (snd style);
5751
5752       pr "  guestfs___end_busy (g);\n";
5753
5754       (match fst style with
5755        | RErr -> pr "  return 0;\n"
5756        | RInt n | RInt64 n | RBool n ->
5757            pr "  return ret.%s;\n" n
5758        | RConstString _ | RConstOptString _ ->
5759            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5760        | RString n ->
5761            pr "  return ret.%s; /* caller will free */\n" n
5762        | RStringList n | RHashtable n ->
5763            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5764            pr "  ret.%s.%s_val =\n" n n;
5765            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5766            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5767              n n;
5768            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5769            pr "  return ret.%s.%s_val;\n" n n
5770        | RStruct (n, _) ->
5771            pr "  /* caller will free this */\n";
5772            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5773        | RStructList (n, _) ->
5774            pr "  /* caller will free this */\n";
5775            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5776        | RBufferOut n ->
5777            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5778            pr "   * _val might be NULL here.  To make the API saner for\n";
5779            pr "   * callers, we turn this case into a unique pointer (using\n";
5780            pr "   * malloc(1)).\n";
5781            pr "   */\n";
5782            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5783            pr "    *size_r = ret.%s.%s_len;\n" n n;
5784            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5785            pr "  } else {\n";
5786            pr "    free (ret.%s.%s_val);\n" n n;
5787            pr "    char *p = safe_malloc (g, 1);\n";
5788            pr "    *size_r = ret.%s.%s_len;\n" n n;
5789            pr "    return p;\n";
5790            pr "  }\n";
5791       );
5792
5793       pr "}\n\n"
5794   ) daemon_functions;
5795
5796   (* Functions to free structures. *)
5797   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5798   pr " * structure format is identical to the XDR format.  See note in\n";
5799   pr " * generator.ml.\n";
5800   pr " */\n";
5801   pr "\n";
5802
5803   List.iter (
5804     fun (typ, _) ->
5805       pr "void\n";
5806       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5807       pr "{\n";
5808       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5809       pr "  free (x);\n";
5810       pr "}\n";
5811       pr "\n";
5812
5813       pr "void\n";
5814       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5815       pr "{\n";
5816       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5817       pr "  free (x);\n";
5818       pr "}\n";
5819       pr "\n";
5820
5821   ) structs;
5822
5823 (* Generate daemon/actions.h. *)
5824 and generate_daemon_actions_h () =
5825   generate_header CStyle GPLv2plus;
5826
5827   pr "#include \"../src/guestfs_protocol.h\"\n";
5828   pr "\n";
5829
5830   List.iter (
5831     fun (name, style, _, _, _, _, _) ->
5832       generate_prototype
5833         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5834         name style;
5835   ) daemon_functions
5836
5837 (* Generate the linker script which controls the visibility of
5838  * symbols in the public ABI and ensures no other symbols get
5839  * exported accidentally.
5840  *)
5841 and generate_linker_script () =
5842   generate_header HashStyle GPLv2plus;
5843
5844   let globals = [
5845     "guestfs_create";
5846     "guestfs_close";
5847     "guestfs_get_error_handler";
5848     "guestfs_get_out_of_memory_handler";
5849     "guestfs_last_error";
5850     "guestfs_set_error_handler";
5851     "guestfs_set_launch_done_callback";
5852     "guestfs_set_log_message_callback";
5853     "guestfs_set_out_of_memory_handler";
5854     "guestfs_set_subprocess_quit_callback";
5855
5856     (* Unofficial parts of the API: the bindings code use these
5857      * functions, so it is useful to export them.
5858      *)
5859     "guestfs_safe_calloc";
5860     "guestfs_safe_malloc";
5861   ] in
5862   let functions =
5863     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5864       all_functions in
5865   let structs =
5866     List.concat (
5867       List.map (fun (typ, _) ->
5868                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5869         structs
5870     ) in
5871   let globals = List.sort compare (globals @ functions @ structs) in
5872
5873   pr "{\n";
5874   pr "    global:\n";
5875   List.iter (pr "        %s;\n") globals;
5876   pr "\n";
5877
5878   pr "    local:\n";
5879   pr "        *;\n";
5880   pr "};\n"
5881
5882 (* Generate the server-side stubs. *)
5883 and generate_daemon_actions () =
5884   generate_header CStyle GPLv2plus;
5885
5886   pr "#include <config.h>\n";
5887   pr "\n";
5888   pr "#include <stdio.h>\n";
5889   pr "#include <stdlib.h>\n";
5890   pr "#include <string.h>\n";
5891   pr "#include <inttypes.h>\n";
5892   pr "#include <rpc/types.h>\n";
5893   pr "#include <rpc/xdr.h>\n";
5894   pr "\n";
5895   pr "#include \"daemon.h\"\n";
5896   pr "#include \"c-ctype.h\"\n";
5897   pr "#include \"../src/guestfs_protocol.h\"\n";
5898   pr "#include \"actions.h\"\n";
5899   pr "\n";
5900
5901   List.iter (
5902     fun (name, style, _, _, _, _, _) ->
5903       (* Generate server-side stubs. *)
5904       pr "static void %s_stub (XDR *xdr_in)\n" name;
5905       pr "{\n";
5906       let error_code =
5907         match fst style with
5908         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5909         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5910         | RBool _ -> pr "  int r;\n"; "-1"
5911         | RConstString _ | RConstOptString _ ->
5912             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5913         | RString _ -> pr "  char *r;\n"; "NULL"
5914         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5915         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5916         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5917         | RBufferOut _ ->
5918             pr "  size_t size = 1;\n";
5919             pr "  char *r;\n";
5920             "NULL" in
5921
5922       (match snd style with
5923        | [] -> ()
5924        | args ->
5925            pr "  struct guestfs_%s_args args;\n" name;
5926            List.iter (
5927              function
5928              | Device n | Dev_or_Path n
5929              | Pathname n
5930              | String n -> ()
5931              | OptString n -> pr "  char *%s;\n" n
5932              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5933              | Bool n -> pr "  int %s;\n" n
5934              | Int n -> pr "  int %s;\n" n
5935              | Int64 n -> pr "  int64_t %s;\n" n
5936              | FileIn _ | FileOut _ -> ()
5937            ) args
5938       );
5939       pr "\n";
5940
5941       (match snd style with
5942        | [] -> ()
5943        | args ->
5944            pr "  memset (&args, 0, sizeof args);\n";
5945            pr "\n";
5946            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5947            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5948            pr "    return;\n";
5949            pr "  }\n";
5950            let pr_args n =
5951              pr "  char *%s = args.%s;\n" n n
5952            in
5953            let pr_list_handling_code n =
5954              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5955              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5956              pr "  if (%s == NULL) {\n" n;
5957              pr "    reply_with_perror (\"realloc\");\n";
5958              pr "    goto done;\n";
5959              pr "  }\n";
5960              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5961              pr "  args.%s.%s_val = %s;\n" n n n;
5962            in
5963            List.iter (
5964              function
5965              | Pathname n ->
5966                  pr_args n;
5967                  pr "  ABS_PATH (%s, goto done);\n" n;
5968              | Device n ->
5969                  pr_args n;
5970                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5971              | Dev_or_Path n ->
5972                  pr_args n;
5973                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5974              | String n -> pr_args n
5975              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5976              | StringList n ->
5977                  pr_list_handling_code n;
5978              | DeviceList n ->
5979                  pr_list_handling_code n;
5980                  pr "  /* Ensure that each is a device,\n";
5981                  pr "   * and perform device name translation. */\n";
5982                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5983                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5984                  pr "  }\n";
5985              | Bool n -> pr "  %s = args.%s;\n" n n
5986              | Int n -> pr "  %s = args.%s;\n" n n
5987              | Int64 n -> pr "  %s = args.%s;\n" n n
5988              | FileIn _ | FileOut _ -> ()
5989            ) args;
5990            pr "\n"
5991       );
5992
5993
5994       (* this is used at least for do_equal *)
5995       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5996         (* Emit NEED_ROOT just once, even when there are two or
5997            more Pathname args *)
5998         pr "  NEED_ROOT (goto done);\n";
5999       );
6000
6001       (* Don't want to call the impl with any FileIn or FileOut
6002        * parameters, since these go "outside" the RPC protocol.
6003        *)
6004       let args' =
6005         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6006           (snd style) in
6007       pr "  r = do_%s " name;
6008       generate_c_call_args (fst style, args');
6009       pr ";\n";
6010
6011       (match fst style with
6012        | RErr | RInt _ | RInt64 _ | RBool _
6013        | RConstString _ | RConstOptString _
6014        | RString _ | RStringList _ | RHashtable _
6015        | RStruct (_, _) | RStructList (_, _) ->
6016            pr "  if (r == %s)\n" error_code;
6017            pr "    /* do_%s has already called reply_with_error */\n" name;
6018            pr "    goto done;\n";
6019            pr "\n"
6020        | RBufferOut _ ->
6021            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6022            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6023            pr "   */\n";
6024            pr "  if (size == 1 && r == %s)\n" error_code;
6025            pr "    /* do_%s has already called reply_with_error */\n" name;
6026            pr "    goto done;\n";
6027            pr "\n"
6028       );
6029
6030       (* If there are any FileOut parameters, then the impl must
6031        * send its own reply.
6032        *)
6033       let no_reply =
6034         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6035       if no_reply then
6036         pr "  /* do_%s has already sent a reply */\n" name
6037       else (
6038         match fst style with
6039         | RErr -> pr "  reply (NULL, NULL);\n"
6040         | RInt n | RInt64 n | RBool n ->
6041             pr "  struct guestfs_%s_ret ret;\n" name;
6042             pr "  ret.%s = r;\n" n;
6043             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6044               name
6045         | RConstString _ | RConstOptString _ ->
6046             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6047         | RString n ->
6048             pr "  struct guestfs_%s_ret ret;\n" name;
6049             pr "  ret.%s = r;\n" n;
6050             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6051               name;
6052             pr "  free (r);\n"
6053         | RStringList n | RHashtable n ->
6054             pr "  struct guestfs_%s_ret ret;\n" name;
6055             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6056             pr "  ret.%s.%s_val = r;\n" n n;
6057             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6058               name;
6059             pr "  free_strings (r);\n"
6060         | RStruct (n, _) ->
6061             pr "  struct guestfs_%s_ret ret;\n" name;
6062             pr "  ret.%s = *r;\n" n;
6063             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6064               name;
6065             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6066               name
6067         | RStructList (n, _) ->
6068             pr "  struct guestfs_%s_ret ret;\n" name;
6069             pr "  ret.%s = *r;\n" n;
6070             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6071               name;
6072             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6073               name
6074         | RBufferOut n ->
6075             pr "  struct guestfs_%s_ret ret;\n" name;
6076             pr "  ret.%s.%s_val = r;\n" n n;
6077             pr "  ret.%s.%s_len = size;\n" n n;
6078             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6079               name;
6080             pr "  free (r);\n"
6081       );
6082
6083       (* Free the args. *)
6084       (match snd style with
6085        | [] ->
6086            pr "done: ;\n";
6087        | _ ->
6088            pr "done:\n";
6089            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6090              name
6091       );
6092
6093       pr "}\n\n";
6094   ) daemon_functions;
6095
6096   (* Dispatch function. *)
6097   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6098   pr "{\n";
6099   pr "  switch (proc_nr) {\n";
6100
6101   List.iter (
6102     fun (name, style, _, _, _, _, _) ->
6103       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6104       pr "      %s_stub (xdr_in);\n" name;
6105       pr "      break;\n"
6106   ) daemon_functions;
6107
6108   pr "    default:\n";
6109   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";
6110   pr "  }\n";
6111   pr "}\n";
6112   pr "\n";
6113
6114   (* LVM columns and tokenization functions. *)
6115   (* XXX This generates crap code.  We should rethink how we
6116    * do this parsing.
6117    *)
6118   List.iter (
6119     function
6120     | typ, cols ->
6121         pr "static const char *lvm_%s_cols = \"%s\";\n"
6122           typ (String.concat "," (List.map fst cols));
6123         pr "\n";
6124
6125         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6126         pr "{\n";
6127         pr "  char *tok, *p, *next;\n";
6128         pr "  int i, j;\n";
6129         pr "\n";
6130         (*
6131           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6132           pr "\n";
6133         *)
6134         pr "  if (!str) {\n";
6135         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6136         pr "    return -1;\n";
6137         pr "  }\n";
6138         pr "  if (!*str || c_isspace (*str)) {\n";
6139         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6140         pr "    return -1;\n";
6141         pr "  }\n";
6142         pr "  tok = str;\n";
6143         List.iter (
6144           fun (name, coltype) ->
6145             pr "  if (!tok) {\n";
6146             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6147             pr "    return -1;\n";
6148             pr "  }\n";
6149             pr "  p = strchrnul (tok, ',');\n";
6150             pr "  if (*p) next = p+1; else next = NULL;\n";
6151             pr "  *p = '\\0';\n";
6152             (match coltype with
6153              | FString ->
6154                  pr "  r->%s = strdup (tok);\n" name;
6155                  pr "  if (r->%s == NULL) {\n" name;
6156                  pr "    perror (\"strdup\");\n";
6157                  pr "    return -1;\n";
6158                  pr "  }\n"
6159              | FUUID ->
6160                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6161                  pr "    if (tok[j] == '\\0') {\n";
6162                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6163                  pr "      return -1;\n";
6164                  pr "    } else if (tok[j] != '-')\n";
6165                  pr "      r->%s[i++] = tok[j];\n" name;
6166                  pr "  }\n";
6167              | FBytes ->
6168                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6169                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6170                  pr "    return -1;\n";
6171                  pr "  }\n";
6172              | FInt64 ->
6173                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6174                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6175                  pr "    return -1;\n";
6176                  pr "  }\n";
6177              | FOptPercent ->
6178                  pr "  if (tok[0] == '\\0')\n";
6179                  pr "    r->%s = -1;\n" name;
6180                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6181                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6182                  pr "    return -1;\n";
6183                  pr "  }\n";
6184              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6185                  assert false (* can never be an LVM column *)
6186             );
6187             pr "  tok = next;\n";
6188         ) cols;
6189
6190         pr "  if (tok != NULL) {\n";
6191         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6192         pr "    return -1;\n";
6193         pr "  }\n";
6194         pr "  return 0;\n";
6195         pr "}\n";
6196         pr "\n";
6197
6198         pr "guestfs_int_lvm_%s_list *\n" typ;
6199         pr "parse_command_line_%ss (void)\n" typ;
6200         pr "{\n";
6201         pr "  char *out, *err;\n";
6202         pr "  char *p, *pend;\n";
6203         pr "  int r, i;\n";
6204         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6205         pr "  void *newp;\n";
6206         pr "\n";
6207         pr "  ret = malloc (sizeof *ret);\n";
6208         pr "  if (!ret) {\n";
6209         pr "    reply_with_perror (\"malloc\");\n";
6210         pr "    return NULL;\n";
6211         pr "  }\n";
6212         pr "\n";
6213         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6214         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6215         pr "\n";
6216         pr "  r = command (&out, &err,\n";
6217         pr "           \"lvm\", \"%ss\",\n" typ;
6218         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6219         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6220         pr "  if (r == -1) {\n";
6221         pr "    reply_with_error (\"%%s\", err);\n";
6222         pr "    free (out);\n";
6223         pr "    free (err);\n";
6224         pr "    free (ret);\n";
6225         pr "    return NULL;\n";
6226         pr "  }\n";
6227         pr "\n";
6228         pr "  free (err);\n";
6229         pr "\n";
6230         pr "  /* Tokenize each line of the output. */\n";
6231         pr "  p = out;\n";
6232         pr "  i = 0;\n";
6233         pr "  while (p) {\n";
6234         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6235         pr "    if (pend) {\n";
6236         pr "      *pend = '\\0';\n";
6237         pr "      pend++;\n";
6238         pr "    }\n";
6239         pr "\n";
6240         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6241         pr "      p++;\n";
6242         pr "\n";
6243         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6244         pr "      p = pend;\n";
6245         pr "      continue;\n";
6246         pr "    }\n";
6247         pr "\n";
6248         pr "    /* Allocate some space to store this next entry. */\n";
6249         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6250         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6251         pr "    if (newp == NULL) {\n";
6252         pr "      reply_with_perror (\"realloc\");\n";
6253         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6254         pr "      free (ret);\n";
6255         pr "      free (out);\n";
6256         pr "      return NULL;\n";
6257         pr "    }\n";
6258         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6259         pr "\n";
6260         pr "    /* Tokenize the next entry. */\n";
6261         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6262         pr "    if (r == -1) {\n";
6263         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6264         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6265         pr "      free (ret);\n";
6266         pr "      free (out);\n";
6267         pr "      return NULL;\n";
6268         pr "    }\n";
6269         pr "\n";
6270         pr "    ++i;\n";
6271         pr "    p = pend;\n";
6272         pr "  }\n";
6273         pr "\n";
6274         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6275         pr "\n";
6276         pr "  free (out);\n";
6277         pr "  return ret;\n";
6278         pr "}\n"
6279
6280   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6281
6282 (* Generate a list of function names, for debugging in the daemon.. *)
6283 and generate_daemon_names () =
6284   generate_header CStyle GPLv2plus;
6285
6286   pr "#include <config.h>\n";
6287   pr "\n";
6288   pr "#include \"daemon.h\"\n";
6289   pr "\n";
6290
6291   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6292   pr "const char *function_names[] = {\n";
6293   List.iter (
6294     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6295   ) daemon_functions;
6296   pr "};\n";
6297
6298 (* Generate the optional groups for the daemon to implement
6299  * guestfs_available.
6300  *)
6301 and generate_daemon_optgroups_c () =
6302   generate_header CStyle GPLv2plus;
6303
6304   pr "#include <config.h>\n";
6305   pr "\n";
6306   pr "#include \"daemon.h\"\n";
6307   pr "#include \"optgroups.h\"\n";
6308   pr "\n";
6309
6310   pr "struct optgroup optgroups[] = {\n";
6311   List.iter (
6312     fun (group, _) ->
6313       pr "  { \"%s\", optgroup_%s_available },\n" group group
6314   ) optgroups;
6315   pr "  { NULL, NULL }\n";
6316   pr "};\n"
6317
6318 and generate_daemon_optgroups_h () =
6319   generate_header CStyle GPLv2plus;
6320
6321   List.iter (
6322     fun (group, _) ->
6323       pr "extern int optgroup_%s_available (void);\n" group
6324   ) optgroups
6325
6326 (* Generate the tests. *)
6327 and generate_tests () =
6328   generate_header CStyle GPLv2plus;
6329
6330   pr "\
6331 #include <stdio.h>
6332 #include <stdlib.h>
6333 #include <string.h>
6334 #include <unistd.h>
6335 #include <sys/types.h>
6336 #include <fcntl.h>
6337
6338 #include \"guestfs.h\"
6339 #include \"guestfs-internal.h\"
6340
6341 static guestfs_h *g;
6342 static int suppress_error = 0;
6343
6344 static void print_error (guestfs_h *g, void *data, const char *msg)
6345 {
6346   if (!suppress_error)
6347     fprintf (stderr, \"%%s\\n\", msg);
6348 }
6349
6350 /* FIXME: nearly identical code appears in fish.c */
6351 static void print_strings (char *const *argv)
6352 {
6353   int argc;
6354
6355   for (argc = 0; argv[argc] != NULL; ++argc)
6356     printf (\"\\t%%s\\n\", argv[argc]);
6357 }
6358
6359 /*
6360 static void print_table (char const *const *argv)
6361 {
6362   int i;
6363
6364   for (i = 0; argv[i] != NULL; i += 2)
6365     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6366 }
6367 */
6368
6369 ";
6370
6371   (* Generate a list of commands which are not tested anywhere. *)
6372   pr "static void no_test_warnings (void)\n";
6373   pr "{\n";
6374
6375   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6376   List.iter (
6377     fun (_, _, _, _, tests, _, _) ->
6378       let tests = filter_map (
6379         function
6380         | (_, (Always|If _|Unless _), test) -> Some test
6381         | (_, Disabled, _) -> None
6382       ) tests in
6383       let seq = List.concat (List.map seq_of_test tests) in
6384       let cmds_tested = List.map List.hd seq in
6385       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6386   ) all_functions;
6387
6388   List.iter (
6389     fun (name, _, _, _, _, _, _) ->
6390       if not (Hashtbl.mem hash name) then
6391         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6392   ) all_functions;
6393
6394   pr "}\n";
6395   pr "\n";
6396
6397   (* Generate the actual tests.  Note that we generate the tests
6398    * in reverse order, deliberately, so that (in general) the
6399    * newest tests run first.  This makes it quicker and easier to
6400    * debug them.
6401    *)
6402   let test_names =
6403     List.map (
6404       fun (name, _, _, flags, tests, _, _) ->
6405         mapi (generate_one_test name flags) tests
6406     ) (List.rev all_functions) in
6407   let test_names = List.concat test_names in
6408   let nr_tests = List.length test_names in
6409
6410   pr "\
6411 int main (int argc, char *argv[])
6412 {
6413   char c = 0;
6414   unsigned long int n_failed = 0;
6415   const char *filename;
6416   int fd;
6417   int nr_tests, test_num = 0;
6418
6419   setbuf (stdout, NULL);
6420
6421   no_test_warnings ();
6422
6423   g = guestfs_create ();
6424   if (g == NULL) {
6425     printf (\"guestfs_create FAILED\\n\");
6426     exit (EXIT_FAILURE);
6427   }
6428
6429   guestfs_set_error_handler (g, print_error, NULL);
6430
6431   guestfs_set_path (g, \"../appliance\");
6432
6433   filename = \"test1.img\";
6434   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6435   if (fd == -1) {
6436     perror (filename);
6437     exit (EXIT_FAILURE);
6438   }
6439   if (lseek (fd, %d, SEEK_SET) == -1) {
6440     perror (\"lseek\");
6441     close (fd);
6442     unlink (filename);
6443     exit (EXIT_FAILURE);
6444   }
6445   if (write (fd, &c, 1) == -1) {
6446     perror (\"write\");
6447     close (fd);
6448     unlink (filename);
6449     exit (EXIT_FAILURE);
6450   }
6451   if (close (fd) == -1) {
6452     perror (filename);
6453     unlink (filename);
6454     exit (EXIT_FAILURE);
6455   }
6456   if (guestfs_add_drive (g, filename) == -1) {
6457     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6458     exit (EXIT_FAILURE);
6459   }
6460
6461   filename = \"test2.img\";
6462   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6463   if (fd == -1) {
6464     perror (filename);
6465     exit (EXIT_FAILURE);
6466   }
6467   if (lseek (fd, %d, SEEK_SET) == -1) {
6468     perror (\"lseek\");
6469     close (fd);
6470     unlink (filename);
6471     exit (EXIT_FAILURE);
6472   }
6473   if (write (fd, &c, 1) == -1) {
6474     perror (\"write\");
6475     close (fd);
6476     unlink (filename);
6477     exit (EXIT_FAILURE);
6478   }
6479   if (close (fd) == -1) {
6480     perror (filename);
6481     unlink (filename);
6482     exit (EXIT_FAILURE);
6483   }
6484   if (guestfs_add_drive (g, filename) == -1) {
6485     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6486     exit (EXIT_FAILURE);
6487   }
6488
6489   filename = \"test3.img\";
6490   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6491   if (fd == -1) {
6492     perror (filename);
6493     exit (EXIT_FAILURE);
6494   }
6495   if (lseek (fd, %d, SEEK_SET) == -1) {
6496     perror (\"lseek\");
6497     close (fd);
6498     unlink (filename);
6499     exit (EXIT_FAILURE);
6500   }
6501   if (write (fd, &c, 1) == -1) {
6502     perror (\"write\");
6503     close (fd);
6504     unlink (filename);
6505     exit (EXIT_FAILURE);
6506   }
6507   if (close (fd) == -1) {
6508     perror (filename);
6509     unlink (filename);
6510     exit (EXIT_FAILURE);
6511   }
6512   if (guestfs_add_drive (g, filename) == -1) {
6513     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6514     exit (EXIT_FAILURE);
6515   }
6516
6517   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6518     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6519     exit (EXIT_FAILURE);
6520   }
6521
6522   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6523   alarm (600);
6524
6525   if (guestfs_launch (g) == -1) {
6526     printf (\"guestfs_launch FAILED\\n\");
6527     exit (EXIT_FAILURE);
6528   }
6529
6530   /* Cancel previous alarm. */
6531   alarm (0);
6532
6533   nr_tests = %d;
6534
6535 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6536
6537   iteri (
6538     fun i test_name ->
6539       pr "  test_num++;\n";
6540       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6541       pr "  if (%s () == -1) {\n" test_name;
6542       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6543       pr "    n_failed++;\n";
6544       pr "  }\n";
6545   ) test_names;
6546   pr "\n";
6547
6548   pr "  guestfs_close (g);\n";
6549   pr "  unlink (\"test1.img\");\n";
6550   pr "  unlink (\"test2.img\");\n";
6551   pr "  unlink (\"test3.img\");\n";
6552   pr "\n";
6553
6554   pr "  if (n_failed > 0) {\n";
6555   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6556   pr "    exit (EXIT_FAILURE);\n";
6557   pr "  }\n";
6558   pr "\n";
6559
6560   pr "  exit (EXIT_SUCCESS);\n";
6561   pr "}\n"
6562
6563 and generate_one_test name flags i (init, prereq, test) =
6564   let test_name = sprintf "test_%s_%d" name i in
6565
6566   pr "\
6567 static int %s_skip (void)
6568 {
6569   const char *str;
6570
6571   str = getenv (\"TEST_ONLY\");
6572   if (str)
6573     return strstr (str, \"%s\") == NULL;
6574   str = getenv (\"SKIP_%s\");
6575   if (str && STREQ (str, \"1\")) return 1;
6576   str = getenv (\"SKIP_TEST_%s\");
6577   if (str && STREQ (str, \"1\")) return 1;
6578   return 0;
6579 }
6580
6581 " test_name name (String.uppercase test_name) (String.uppercase name);
6582
6583   (match prereq with
6584    | Disabled | Always -> ()
6585    | If code | Unless code ->
6586        pr "static int %s_prereq (void)\n" test_name;
6587        pr "{\n";
6588        pr "  %s\n" code;
6589        pr "}\n";
6590        pr "\n";
6591   );
6592
6593   pr "\
6594 static int %s (void)
6595 {
6596   if (%s_skip ()) {
6597     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6598     return 0;
6599   }
6600
6601 " test_name test_name test_name;
6602
6603   (* Optional functions should only be tested if the relevant
6604    * support is available in the daemon.
6605    *)
6606   List.iter (
6607     function
6608     | Optional group ->
6609         pr "  {\n";
6610         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6611         pr "    int r;\n";
6612         pr "    suppress_error = 1;\n";
6613         pr "    r = guestfs_available (g, (char **) groups);\n";
6614         pr "    suppress_error = 0;\n";
6615         pr "    if (r == -1) {\n";
6616         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6617         pr "      return 0;\n";
6618         pr "    }\n";
6619         pr "  }\n";
6620     | _ -> ()
6621   ) flags;
6622
6623   (match prereq with
6624    | Disabled ->
6625        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6626    | If _ ->
6627        pr "  if (! %s_prereq ()) {\n" test_name;
6628        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6629        pr "    return 0;\n";
6630        pr "  }\n";
6631        pr "\n";
6632        generate_one_test_body name i test_name init test;
6633    | Unless _ ->
6634        pr "  if (%s_prereq ()) {\n" test_name;
6635        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6636        pr "    return 0;\n";
6637        pr "  }\n";
6638        pr "\n";
6639        generate_one_test_body name i test_name init test;
6640    | Always ->
6641        generate_one_test_body name i test_name init test
6642   );
6643
6644   pr "  return 0;\n";
6645   pr "}\n";
6646   pr "\n";
6647   test_name
6648
6649 and generate_one_test_body name i test_name init test =
6650   (match init with
6651    | InitNone (* XXX at some point, InitNone and InitEmpty became
6652                * folded together as the same thing.  Really we should
6653                * make InitNone do nothing at all, but the tests may
6654                * need to be checked to make sure this is OK.
6655                *)
6656    | InitEmpty ->
6657        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6658        List.iter (generate_test_command_call test_name)
6659          [["blockdev_setrw"; "/dev/sda"];
6660           ["umount_all"];
6661           ["lvm_remove_all"]]
6662    | InitPartition ->
6663        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6664        List.iter (generate_test_command_call test_name)
6665          [["blockdev_setrw"; "/dev/sda"];
6666           ["umount_all"];
6667           ["lvm_remove_all"];
6668           ["part_disk"; "/dev/sda"; "mbr"]]
6669    | InitBasicFS ->
6670        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6671        List.iter (generate_test_command_call test_name)
6672          [["blockdev_setrw"; "/dev/sda"];
6673           ["umount_all"];
6674           ["lvm_remove_all"];
6675           ["part_disk"; "/dev/sda"; "mbr"];
6676           ["mkfs"; "ext2"; "/dev/sda1"];
6677           ["mount_options"; ""; "/dev/sda1"; "/"]]
6678    | InitBasicFSonLVM ->
6679        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6680          test_name;
6681        List.iter (generate_test_command_call test_name)
6682          [["blockdev_setrw"; "/dev/sda"];
6683           ["umount_all"];
6684           ["lvm_remove_all"];
6685           ["part_disk"; "/dev/sda"; "mbr"];
6686           ["pvcreate"; "/dev/sda1"];
6687           ["vgcreate"; "VG"; "/dev/sda1"];
6688           ["lvcreate"; "LV"; "VG"; "8"];
6689           ["mkfs"; "ext2"; "/dev/VG/LV"];
6690           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6691    | InitISOFS ->
6692        pr "  /* InitISOFS for %s */\n" test_name;
6693        List.iter (generate_test_command_call test_name)
6694          [["blockdev_setrw"; "/dev/sda"];
6695           ["umount_all"];
6696           ["lvm_remove_all"];
6697           ["mount_ro"; "/dev/sdd"; "/"]]
6698   );
6699
6700   let get_seq_last = function
6701     | [] ->
6702         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6703           test_name
6704     | seq ->
6705         let seq = List.rev seq in
6706         List.rev (List.tl seq), List.hd seq
6707   in
6708
6709   match test with
6710   | TestRun seq ->
6711       pr "  /* TestRun for %s (%d) */\n" name i;
6712       List.iter (generate_test_command_call test_name) seq
6713   | TestOutput (seq, expected) ->
6714       pr "  /* TestOutput for %s (%d) */\n" name i;
6715       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6716       let seq, last = get_seq_last seq in
6717       let test () =
6718         pr "    if (STRNEQ (r, expected)) {\n";
6719         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6720         pr "      return -1;\n";
6721         pr "    }\n"
6722       in
6723       List.iter (generate_test_command_call test_name) seq;
6724       generate_test_command_call ~test test_name last
6725   | TestOutputList (seq, expected) ->
6726       pr "  /* TestOutputList for %s (%d) */\n" name i;
6727       let seq, last = get_seq_last seq in
6728       let test () =
6729         iteri (
6730           fun i str ->
6731             pr "    if (!r[%d]) {\n" i;
6732             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6733             pr "      print_strings (r);\n";
6734             pr "      return -1;\n";
6735             pr "    }\n";
6736             pr "    {\n";
6737             pr "      const char *expected = \"%s\";\n" (c_quote str);
6738             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6739             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6740             pr "        return -1;\n";
6741             pr "      }\n";
6742             pr "    }\n"
6743         ) expected;
6744         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6745         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6746           test_name;
6747         pr "      print_strings (r);\n";
6748         pr "      return -1;\n";
6749         pr "    }\n"
6750       in
6751       List.iter (generate_test_command_call test_name) seq;
6752       generate_test_command_call ~test test_name last
6753   | TestOutputListOfDevices (seq, expected) ->
6754       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6755       let seq, last = get_seq_last seq in
6756       let test () =
6757         iteri (
6758           fun i str ->
6759             pr "    if (!r[%d]) {\n" i;
6760             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6761             pr "      print_strings (r);\n";
6762             pr "      return -1;\n";
6763             pr "    }\n";
6764             pr "    {\n";
6765             pr "      const char *expected = \"%s\";\n" (c_quote str);
6766             pr "      r[%d][5] = 's';\n" i;
6767             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6768             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6769             pr "        return -1;\n";
6770             pr "      }\n";
6771             pr "    }\n"
6772         ) expected;
6773         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6774         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6775           test_name;
6776         pr "      print_strings (r);\n";
6777         pr "      return -1;\n";
6778         pr "    }\n"
6779       in
6780       List.iter (generate_test_command_call test_name) seq;
6781       generate_test_command_call ~test test_name last
6782   | TestOutputInt (seq, expected) ->
6783       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6784       let seq, last = get_seq_last seq in
6785       let test () =
6786         pr "    if (r != %d) {\n" expected;
6787         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6788           test_name expected;
6789         pr "               (int) r);\n";
6790         pr "      return -1;\n";
6791         pr "    }\n"
6792       in
6793       List.iter (generate_test_command_call test_name) seq;
6794       generate_test_command_call ~test test_name last
6795   | TestOutputIntOp (seq, op, expected) ->
6796       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6797       let seq, last = get_seq_last seq in
6798       let test () =
6799         pr "    if (! (r %s %d)) {\n" op expected;
6800         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6801           test_name op expected;
6802         pr "               (int) 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   | TestOutputTrue seq ->
6809       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6810       let seq, last = get_seq_last seq in
6811       let test () =
6812         pr "    if (!r) {\n";
6813         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6814           test_name;
6815         pr "      return -1;\n";
6816         pr "    }\n"
6817       in
6818       List.iter (generate_test_command_call test_name) seq;
6819       generate_test_command_call ~test test_name last
6820   | TestOutputFalse seq ->
6821       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6822       let seq, last = get_seq_last seq in
6823       let test () =
6824         pr "    if (r) {\n";
6825         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6826           test_name;
6827         pr "      return -1;\n";
6828         pr "    }\n"
6829       in
6830       List.iter (generate_test_command_call test_name) seq;
6831       generate_test_command_call ~test test_name last
6832   | TestOutputLength (seq, expected) ->
6833       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6834       let seq, last = get_seq_last seq in
6835       let test () =
6836         pr "    int j;\n";
6837         pr "    for (j = 0; j < %d; ++j)\n" expected;
6838         pr "      if (r[j] == NULL) {\n";
6839         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6840           test_name;
6841         pr "        print_strings (r);\n";
6842         pr "        return -1;\n";
6843         pr "      }\n";
6844         pr "    if (r[j] != NULL) {\n";
6845         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6846           test_name;
6847         pr "      print_strings (r);\n";
6848         pr "      return -1;\n";
6849         pr "    }\n"
6850       in
6851       List.iter (generate_test_command_call test_name) seq;
6852       generate_test_command_call ~test test_name last
6853   | TestOutputBuffer (seq, expected) ->
6854       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6855       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6856       let seq, last = get_seq_last seq in
6857       let len = String.length expected in
6858       let test () =
6859         pr "    if (size != %d) {\n" len;
6860         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6861         pr "      return -1;\n";
6862         pr "    }\n";
6863         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6864         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6865         pr "      return -1;\n";
6866         pr "    }\n"
6867       in
6868       List.iter (generate_test_command_call test_name) seq;
6869       generate_test_command_call ~test test_name last
6870   | TestOutputStruct (seq, checks) ->
6871       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6872       let seq, last = get_seq_last seq in
6873       let test () =
6874         List.iter (
6875           function
6876           | CompareWithInt (field, expected) ->
6877               pr "    if (r->%s != %d) {\n" field expected;
6878               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6879                 test_name field expected;
6880               pr "               (int) r->%s);\n" field;
6881               pr "      return -1;\n";
6882               pr "    }\n"
6883           | CompareWithIntOp (field, op, expected) ->
6884               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6885               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6886                 test_name field op expected;
6887               pr "               (int) r->%s);\n" field;
6888               pr "      return -1;\n";
6889               pr "    }\n"
6890           | CompareWithString (field, expected) ->
6891               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6892               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6893                 test_name field expected;
6894               pr "               r->%s);\n" field;
6895               pr "      return -1;\n";
6896               pr "    }\n"
6897           | CompareFieldsIntEq (field1, field2) ->
6898               pr "    if (r->%s != r->%s) {\n" field1 field2;
6899               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6900                 test_name field1 field2;
6901               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6902               pr "      return -1;\n";
6903               pr "    }\n"
6904           | CompareFieldsStrEq (field1, field2) ->
6905               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6906               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6907                 test_name field1 field2;
6908               pr "               r->%s, r->%s);\n" field1 field2;
6909               pr "      return -1;\n";
6910               pr "    }\n"
6911         ) checks
6912       in
6913       List.iter (generate_test_command_call test_name) seq;
6914       generate_test_command_call ~test test_name last
6915   | TestLastFail seq ->
6916       pr "  /* TestLastFail for %s (%d) */\n" name i;
6917       let seq, last = get_seq_last seq in
6918       List.iter (generate_test_command_call test_name) seq;
6919       generate_test_command_call test_name ~expect_error:true last
6920
6921 (* Generate the code to run a command, leaving the result in 'r'.
6922  * If you expect to get an error then you should set expect_error:true.
6923  *)
6924 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6925   match cmd with
6926   | [] -> assert false
6927   | name :: args ->
6928       (* Look up the command to find out what args/ret it has. *)
6929       let style =
6930         try
6931           let _, style, _, _, _, _, _ =
6932             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6933           style
6934         with Not_found ->
6935           failwithf "%s: in test, command %s was not found" test_name name in
6936
6937       if List.length (snd style) <> List.length args then
6938         failwithf "%s: in test, wrong number of args given to %s"
6939           test_name name;
6940
6941       pr "  {\n";
6942
6943       List.iter (
6944         function
6945         | OptString n, "NULL" -> ()
6946         | Pathname n, arg
6947         | Device n, arg
6948         | Dev_or_Path n, arg
6949         | String n, arg
6950         | OptString n, arg ->
6951             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6952         | Int _, _
6953         | Int64 _, _
6954         | Bool _, _
6955         | FileIn _, _ | FileOut _, _ -> ()
6956         | StringList n, "" | DeviceList n, "" ->
6957             pr "    const char *const %s[1] = { NULL };\n" n
6958         | StringList n, arg | DeviceList n, arg ->
6959             let strs = string_split " " arg in
6960             iteri (
6961               fun i str ->
6962                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6963             ) strs;
6964             pr "    const char *const %s[] = {\n" n;
6965             iteri (
6966               fun i _ -> pr "      %s_%d,\n" n i
6967             ) strs;
6968             pr "      NULL\n";
6969             pr "    };\n";
6970       ) (List.combine (snd style) args);
6971
6972       let error_code =
6973         match fst style with
6974         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6975         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6976         | RConstString _ | RConstOptString _ ->
6977             pr "    const char *r;\n"; "NULL"
6978         | RString _ -> pr "    char *r;\n"; "NULL"
6979         | RStringList _ | RHashtable _ ->
6980             pr "    char **r;\n";
6981             pr "    int i;\n";
6982             "NULL"
6983         | RStruct (_, typ) ->
6984             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6985         | RStructList (_, typ) ->
6986             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6987         | RBufferOut _ ->
6988             pr "    char *r;\n";
6989             pr "    size_t size;\n";
6990             "NULL" in
6991
6992       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6993       pr "    r = guestfs_%s (g" name;
6994
6995       (* Generate the parameters. *)
6996       List.iter (
6997         function
6998         | OptString _, "NULL" -> pr ", NULL"
6999         | Pathname n, _
7000         | Device n, _ | Dev_or_Path n, _
7001         | String n, _
7002         | OptString n, _ ->
7003             pr ", %s" n
7004         | FileIn _, arg | FileOut _, arg ->
7005             pr ", \"%s\"" (c_quote arg)
7006         | StringList n, _ | DeviceList n, _ ->
7007             pr ", (char **) %s" n
7008         | Int _, arg ->
7009             let i =
7010               try int_of_string arg
7011               with Failure "int_of_string" ->
7012                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7013             pr ", %d" i
7014         | Int64 _, arg ->
7015             let i =
7016               try Int64.of_string arg
7017               with Failure "int_of_string" ->
7018                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7019             pr ", %Ld" i
7020         | Bool _, arg ->
7021             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7022       ) (List.combine (snd style) args);
7023
7024       (match fst style with
7025        | RBufferOut _ -> pr ", &size"
7026        | _ -> ()
7027       );
7028
7029       pr ");\n";
7030
7031       if not expect_error then
7032         pr "    if (r == %s)\n" error_code
7033       else
7034         pr "    if (r != %s)\n" error_code;
7035       pr "      return -1;\n";
7036
7037       (* Insert the test code. *)
7038       (match test with
7039        | None -> ()
7040        | Some f -> f ()
7041       );
7042
7043       (match fst style with
7044        | RErr | RInt _ | RInt64 _ | RBool _
7045        | RConstString _ | RConstOptString _ -> ()
7046        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7047        | RStringList _ | RHashtable _ ->
7048            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7049            pr "      free (r[i]);\n";
7050            pr "    free (r);\n"
7051        | RStruct (_, typ) ->
7052            pr "    guestfs_free_%s (r);\n" typ
7053        | RStructList (_, typ) ->
7054            pr "    guestfs_free_%s_list (r);\n" typ
7055       );
7056
7057       pr "  }\n"
7058
7059 and c_quote str =
7060   let str = replace_str str "\r" "\\r" in
7061   let str = replace_str str "\n" "\\n" in
7062   let str = replace_str str "\t" "\\t" in
7063   let str = replace_str str "\000" "\\0" in
7064   str
7065
7066 (* Generate a lot of different functions for guestfish. *)
7067 and generate_fish_cmds () =
7068   generate_header CStyle GPLv2plus;
7069
7070   let all_functions =
7071     List.filter (
7072       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7073     ) all_functions in
7074   let all_functions_sorted =
7075     List.filter (
7076       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7077     ) all_functions_sorted in
7078
7079   pr "#include <config.h>\n";
7080   pr "\n";
7081   pr "#include <stdio.h>\n";
7082   pr "#include <stdlib.h>\n";
7083   pr "#include <string.h>\n";
7084   pr "#include <inttypes.h>\n";
7085   pr "\n";
7086   pr "#include <guestfs.h>\n";
7087   pr "#include \"c-ctype.h\"\n";
7088   pr "#include \"full-write.h\"\n";
7089   pr "#include \"xstrtol.h\"\n";
7090   pr "#include \"fish.h\"\n";
7091   pr "\n";
7092
7093   (* list_commands function, which implements guestfish -h *)
7094   pr "void list_commands (void)\n";
7095   pr "{\n";
7096   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7097   pr "  list_builtin_commands ();\n";
7098   List.iter (
7099     fun (name, _, _, flags, _, shortdesc, _) ->
7100       let name = replace_char name '_' '-' in
7101       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7102         name shortdesc
7103   ) all_functions_sorted;
7104   pr "  printf (\"    %%s\\n\",";
7105   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7106   pr "}\n";
7107   pr "\n";
7108
7109   (* display_command function, which implements guestfish -h cmd *)
7110   pr "void display_command (const char *cmd)\n";
7111   pr "{\n";
7112   List.iter (
7113     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7114       let name2 = replace_char name '_' '-' in
7115       let alias =
7116         try find_map (function FishAlias n -> Some n | _ -> None) flags
7117         with Not_found -> name in
7118       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7119       let synopsis =
7120         match snd style with
7121         | [] -> name2
7122         | args ->
7123             sprintf "%s %s"
7124               name2 (String.concat " " (List.map name_of_argt args)) in
7125
7126       let warnings =
7127         if List.mem ProtocolLimitWarning flags then
7128           ("\n\n" ^ protocol_limit_warning)
7129         else "" in
7130
7131       (* For DangerWillRobinson commands, we should probably have
7132        * guestfish prompt before allowing you to use them (especially
7133        * in interactive mode). XXX
7134        *)
7135       let warnings =
7136         warnings ^
7137           if List.mem DangerWillRobinson flags then
7138             ("\n\n" ^ danger_will_robinson)
7139           else "" in
7140
7141       let warnings =
7142         warnings ^
7143           match deprecation_notice flags with
7144           | None -> ""
7145           | Some txt -> "\n\n" ^ txt in
7146
7147       let describe_alias =
7148         if name <> alias then
7149           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7150         else "" in
7151
7152       pr "  if (";
7153       pr "STRCASEEQ (cmd, \"%s\")" name;
7154       if name <> name2 then
7155         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7156       if name <> alias then
7157         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7158       pr ")\n";
7159       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7160         name2 shortdesc
7161         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7162          "=head1 DESCRIPTION\n\n" ^
7163          longdesc ^ warnings ^ describe_alias);
7164       pr "  else\n"
7165   ) all_functions;
7166   pr "    display_builtin_command (cmd);\n";
7167   pr "}\n";
7168   pr "\n";
7169
7170   let emit_print_list_function typ =
7171     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7172       typ typ typ;
7173     pr "{\n";
7174     pr "  unsigned int i;\n";
7175     pr "\n";
7176     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7177     pr "    printf (\"[%%d] = {\\n\", i);\n";
7178     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7179     pr "    printf (\"}\\n\");\n";
7180     pr "  }\n";
7181     pr "}\n";
7182     pr "\n";
7183   in
7184
7185   (* print_* functions *)
7186   List.iter (
7187     fun (typ, cols) ->
7188       let needs_i =
7189         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7190
7191       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7192       pr "{\n";
7193       if needs_i then (
7194         pr "  unsigned int i;\n";
7195         pr "\n"
7196       );
7197       List.iter (
7198         function
7199         | name, FString ->
7200             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7201         | name, FUUID ->
7202             pr "  printf (\"%%s%s: \", indent);\n" name;
7203             pr "  for (i = 0; i < 32; ++i)\n";
7204             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7205             pr "  printf (\"\\n\");\n"
7206         | name, FBuffer ->
7207             pr "  printf (\"%%s%s: \", indent);\n" name;
7208             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7209             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7210             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7211             pr "    else\n";
7212             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7213             pr "  printf (\"\\n\");\n"
7214         | name, (FUInt64|FBytes) ->
7215             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7216               name typ name
7217         | name, FInt64 ->
7218             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7219               name typ name
7220         | name, FUInt32 ->
7221             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7222               name typ name
7223         | name, FInt32 ->
7224             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7225               name typ name
7226         | name, FChar ->
7227             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7228               name typ name
7229         | name, FOptPercent ->
7230             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7231               typ name name typ name;
7232             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7233       ) cols;
7234       pr "}\n";
7235       pr "\n";
7236   ) structs;
7237
7238   (* Emit a print_TYPE_list function definition only if that function is used. *)
7239   List.iter (
7240     function
7241     | typ, (RStructListOnly | RStructAndList) ->
7242         (* generate the function for typ *)
7243         emit_print_list_function typ
7244     | typ, _ -> () (* empty *)
7245   ) (rstructs_used_by all_functions);
7246
7247   (* Emit a print_TYPE function definition only if that function is used. *)
7248   List.iter (
7249     function
7250     | typ, (RStructOnly | RStructAndList) ->
7251         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7252         pr "{\n";
7253         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7254         pr "}\n";
7255         pr "\n";
7256     | typ, _ -> () (* empty *)
7257   ) (rstructs_used_by all_functions);
7258
7259   (* run_<action> actions *)
7260   List.iter (
7261     fun (name, style, _, flags, _, _, _) ->
7262       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7263       pr "{\n";
7264       (match fst style with
7265        | RErr
7266        | RInt _
7267        | RBool _ -> pr "  int r;\n"
7268        | RInt64 _ -> pr "  int64_t r;\n"
7269        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7270        | RString _ -> pr "  char *r;\n"
7271        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7272        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7273        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7274        | RBufferOut _ ->
7275            pr "  char *r;\n";
7276            pr "  size_t size;\n";
7277       );
7278       List.iter (
7279         function
7280         | Device n
7281         | String n
7282         | OptString n
7283         | FileIn n
7284         | FileOut n -> pr "  const char *%s;\n" n
7285         | Pathname n
7286         | Dev_or_Path n -> pr "  char *%s;\n" n
7287         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7288         | Bool n -> pr "  int %s;\n" n
7289         | Int n -> pr "  int %s;\n" n
7290         | Int64 n -> pr "  int64_t %s;\n" n
7291       ) (snd style);
7292
7293       (* Check and convert parameters. *)
7294       let argc_expected = List.length (snd style) in
7295       pr "  if (argc != %d) {\n" argc_expected;
7296       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7297         argc_expected;
7298       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7299       pr "    return -1;\n";
7300       pr "  }\n";
7301
7302       let parse_integer fn fntyp rtyp range name i =
7303         pr "  {\n";
7304         pr "    strtol_error xerr;\n";
7305         pr "    %s r;\n" fntyp;
7306         pr "\n";
7307         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7308         pr "    if (xerr != LONGINT_OK) {\n";
7309         pr "      fprintf (stderr,\n";
7310         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7311         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7312         pr "      return -1;\n";
7313         pr "    }\n";
7314         (match range with
7315          | None -> ()
7316          | Some (min, max, comment) ->
7317              pr "    /* %s */\n" comment;
7318              pr "    if (r < %s || r > %s) {\n" min max;
7319              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7320                name;
7321              pr "      return -1;\n";
7322              pr "    }\n";
7323              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7324         );
7325         pr "    %s = r;\n" name;
7326         pr "  }\n";
7327       in
7328
7329       iteri (
7330         fun i ->
7331           function
7332           | Device name
7333           | String name ->
7334               pr "  %s = argv[%d];\n" name i
7335           | Pathname name
7336           | Dev_or_Path name ->
7337               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7338               pr "  if (%s == NULL) return -1;\n" name
7339           | OptString name ->
7340               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7341                 name i i
7342           | FileIn name ->
7343               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7344                 name i i
7345           | FileOut name ->
7346               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7347                 name i i
7348           | StringList name | DeviceList name ->
7349               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7350               pr "  if (%s == NULL) return -1;\n" name;
7351           | Bool name ->
7352               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7353           | Int name ->
7354               let range =
7355                 let min = "(-(2LL<<30))"
7356                 and max = "((2LL<<30)-1)"
7357                 and comment =
7358                   "The Int type in the generator is a signed 31 bit int." in
7359                 Some (min, max, comment) in
7360               parse_integer "xstrtoll" "long long" "int" range name i
7361           | Int64 name ->
7362               parse_integer "xstrtoll" "long long" "int64_t" None name i
7363       ) (snd style);
7364
7365       (* Call C API function. *)
7366       let fn =
7367         try find_map (function FishAction n -> Some n | _ -> None) flags
7368         with Not_found -> sprintf "guestfs_%s" name in
7369       pr "  r = %s " fn;
7370       generate_c_call_args ~handle:"g" style;
7371       pr ";\n";
7372
7373       List.iter (
7374         function
7375         | Device name | String name
7376         | OptString name | FileIn name | FileOut name | Bool name
7377         | Int name | Int64 name -> ()
7378         | Pathname name | Dev_or_Path name ->
7379             pr "  free (%s);\n" name
7380         | StringList name | DeviceList name ->
7381             pr "  free_strings (%s);\n" name
7382       ) (snd style);
7383
7384       (* Check return value for errors and display command results. *)
7385       (match fst style with
7386        | RErr -> pr "  return r;\n"
7387        | RInt _ ->
7388            pr "  if (r == -1) return -1;\n";
7389            pr "  printf (\"%%d\\n\", r);\n";
7390            pr "  return 0;\n"
7391        | RInt64 _ ->
7392            pr "  if (r == -1) return -1;\n";
7393            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7394            pr "  return 0;\n"
7395        | RBool _ ->
7396            pr "  if (r == -1) return -1;\n";
7397            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7398            pr "  return 0;\n"
7399        | RConstString _ ->
7400            pr "  if (r == NULL) return -1;\n";
7401            pr "  printf (\"%%s\\n\", r);\n";
7402            pr "  return 0;\n"
7403        | RConstOptString _ ->
7404            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7405            pr "  return 0;\n"
7406        | RString _ ->
7407            pr "  if (r == NULL) return -1;\n";
7408            pr "  printf (\"%%s\\n\", r);\n";
7409            pr "  free (r);\n";
7410            pr "  return 0;\n"
7411        | RStringList _ ->
7412            pr "  if (r == NULL) return -1;\n";
7413            pr "  print_strings (r);\n";
7414            pr "  free_strings (r);\n";
7415            pr "  return 0;\n"
7416        | RStruct (_, typ) ->
7417            pr "  if (r == NULL) return -1;\n";
7418            pr "  print_%s (r);\n" typ;
7419            pr "  guestfs_free_%s (r);\n" typ;
7420            pr "  return 0;\n"
7421        | RStructList (_, typ) ->
7422            pr "  if (r == NULL) return -1;\n";
7423            pr "  print_%s_list (r);\n" typ;
7424            pr "  guestfs_free_%s_list (r);\n" typ;
7425            pr "  return 0;\n"
7426        | RHashtable _ ->
7427            pr "  if (r == NULL) return -1;\n";
7428            pr "  print_table (r);\n";
7429            pr "  free_strings (r);\n";
7430            pr "  return 0;\n"
7431        | RBufferOut _ ->
7432            pr "  if (r == NULL) return -1;\n";
7433            pr "  if (full_write (1, r, size) != size) {\n";
7434            pr "    perror (\"write\");\n";
7435            pr "    free (r);\n";
7436            pr "    return -1;\n";
7437            pr "  }\n";
7438            pr "  free (r);\n";
7439            pr "  return 0;\n"
7440       );
7441       pr "}\n";
7442       pr "\n"
7443   ) all_functions;
7444
7445   (* run_action function *)
7446   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7447   pr "{\n";
7448   List.iter (
7449     fun (name, _, _, flags, _, _, _) ->
7450       let name2 = replace_char name '_' '-' in
7451       let alias =
7452         try find_map (function FishAlias n -> Some n | _ -> None) flags
7453         with Not_found -> name in
7454       pr "  if (";
7455       pr "STRCASEEQ (cmd, \"%s\")" name;
7456       if name <> name2 then
7457         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7458       if name <> alias then
7459         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7460       pr ")\n";
7461       pr "    return run_%s (cmd, argc, argv);\n" name;
7462       pr "  else\n";
7463   ) all_functions;
7464   pr "    {\n";
7465   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7466   pr "      if (command_num == 1)\n";
7467   pr "        extended_help_message ();\n";
7468   pr "      return -1;\n";
7469   pr "    }\n";
7470   pr "  return 0;\n";
7471   pr "}\n";
7472   pr "\n"
7473
7474 (* Readline completion for guestfish. *)
7475 and generate_fish_completion () =
7476   generate_header CStyle GPLv2plus;
7477
7478   let all_functions =
7479     List.filter (
7480       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7481     ) all_functions in
7482
7483   pr "\
7484 #include <config.h>
7485
7486 #include <stdio.h>
7487 #include <stdlib.h>
7488 #include <string.h>
7489
7490 #ifdef HAVE_LIBREADLINE
7491 #include <readline/readline.h>
7492 #endif
7493
7494 #include \"fish.h\"
7495
7496 #ifdef HAVE_LIBREADLINE
7497
7498 static const char *const commands[] = {
7499   BUILTIN_COMMANDS_FOR_COMPLETION,
7500 ";
7501
7502   (* Get the commands, including the aliases.  They don't need to be
7503    * sorted - the generator() function just does a dumb linear search.
7504    *)
7505   let commands =
7506     List.map (
7507       fun (name, _, _, flags, _, _, _) ->
7508         let name2 = replace_char name '_' '-' in
7509         let alias =
7510           try find_map (function FishAlias n -> Some n | _ -> None) flags
7511           with Not_found -> name in
7512
7513         if name <> alias then [name2; alias] else [name2]
7514     ) all_functions in
7515   let commands = List.flatten commands in
7516
7517   List.iter (pr "  \"%s\",\n") commands;
7518
7519   pr "  NULL
7520 };
7521
7522 static char *
7523 generator (const char *text, int state)
7524 {
7525   static int index, len;
7526   const char *name;
7527
7528   if (!state) {
7529     index = 0;
7530     len = strlen (text);
7531   }
7532
7533   rl_attempted_completion_over = 1;
7534
7535   while ((name = commands[index]) != NULL) {
7536     index++;
7537     if (STRCASEEQLEN (name, text, len))
7538       return strdup (name);
7539   }
7540
7541   return NULL;
7542 }
7543
7544 #endif /* HAVE_LIBREADLINE */
7545
7546 #ifdef HAVE_RL_COMPLETION_MATCHES
7547 #define RL_COMPLETION_MATCHES rl_completion_matches
7548 #else
7549 #ifdef HAVE_COMPLETION_MATCHES
7550 #define RL_COMPLETION_MATCHES completion_matches
7551 #endif
7552 #endif /* else just fail if we don't have either symbol */
7553
7554 char **
7555 do_completion (const char *text, int start, int end)
7556 {
7557   char **matches = NULL;
7558
7559 #ifdef HAVE_LIBREADLINE
7560   rl_completion_append_character = ' ';
7561
7562   if (start == 0)
7563     matches = RL_COMPLETION_MATCHES (text, generator);
7564   else if (complete_dest_paths)
7565     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7566 #endif
7567
7568   return matches;
7569 }
7570 ";
7571
7572 (* Generate the POD documentation for guestfish. *)
7573 and generate_fish_actions_pod () =
7574   let all_functions_sorted =
7575     List.filter (
7576       fun (_, _, _, flags, _, _, _) ->
7577         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7578     ) all_functions_sorted in
7579
7580   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7581
7582   List.iter (
7583     fun (name, style, _, flags, _, _, longdesc) ->
7584       let longdesc =
7585         Str.global_substitute rex (
7586           fun s ->
7587             let sub =
7588               try Str.matched_group 1 s
7589               with Not_found ->
7590                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7591             "C<" ^ replace_char sub '_' '-' ^ ">"
7592         ) longdesc in
7593       let name = replace_char name '_' '-' in
7594       let alias =
7595         try find_map (function FishAlias n -> Some n | _ -> None) flags
7596         with Not_found -> name in
7597
7598       pr "=head2 %s" name;
7599       if name <> alias then
7600         pr " | %s" alias;
7601       pr "\n";
7602       pr "\n";
7603       pr " %s" name;
7604       List.iter (
7605         function
7606         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7607         | OptString n -> pr " %s" n
7608         | StringList n | DeviceList n -> pr " '%s ...'" n
7609         | Bool _ -> pr " true|false"
7610         | Int n -> pr " %s" n
7611         | Int64 n -> pr " %s" n
7612         | FileIn n | FileOut n -> pr " (%s|-)" n
7613       ) (snd style);
7614       pr "\n";
7615       pr "\n";
7616       pr "%s\n\n" longdesc;
7617
7618       if List.exists (function FileIn _ | FileOut _ -> true
7619                       | _ -> false) (snd style) then
7620         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7621
7622       if List.mem ProtocolLimitWarning flags then
7623         pr "%s\n\n" protocol_limit_warning;
7624
7625       if List.mem DangerWillRobinson flags then
7626         pr "%s\n\n" danger_will_robinson;
7627
7628       match deprecation_notice flags with
7629       | None -> ()
7630       | Some txt -> pr "%s\n\n" txt
7631   ) all_functions_sorted
7632
7633 (* Generate a C function prototype. *)
7634 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7635     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7636     ?(prefix = "")
7637     ?handle name style =
7638   if extern then pr "extern ";
7639   if static then pr "static ";
7640   (match fst style with
7641    | RErr -> pr "int "
7642    | RInt _ -> pr "int "
7643    | RInt64 _ -> pr "int64_t "
7644    | RBool _ -> pr "int "
7645    | RConstString _ | RConstOptString _ -> pr "const char *"
7646    | RString _ | RBufferOut _ -> pr "char *"
7647    | RStringList _ | RHashtable _ -> pr "char **"
7648    | RStruct (_, typ) ->
7649        if not in_daemon then pr "struct guestfs_%s *" typ
7650        else pr "guestfs_int_%s *" typ
7651    | RStructList (_, typ) ->
7652        if not in_daemon then pr "struct guestfs_%s_list *" typ
7653        else pr "guestfs_int_%s_list *" typ
7654   );
7655   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7656   pr "%s%s (" prefix name;
7657   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7658     pr "void"
7659   else (
7660     let comma = ref false in
7661     (match handle with
7662      | None -> ()
7663      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7664     );
7665     let next () =
7666       if !comma then (
7667         if single_line then pr ", " else pr ",\n\t\t"
7668       );
7669       comma := true
7670     in
7671     List.iter (
7672       function
7673       | Pathname n
7674       | Device n | Dev_or_Path n
7675       | String n
7676       | OptString n ->
7677           next ();
7678           pr "const char *%s" n
7679       | StringList n | DeviceList n ->
7680           next ();
7681           pr "char *const *%s" n
7682       | Bool n -> next (); pr "int %s" n
7683       | Int n -> next (); pr "int %s" n
7684       | Int64 n -> next (); pr "int64_t %s" n
7685       | FileIn n
7686       | FileOut n ->
7687           if not in_daemon then (next (); pr "const char *%s" n)
7688     ) (snd style);
7689     if is_RBufferOut then (next (); pr "size_t *size_r");
7690   );
7691   pr ")";
7692   if semicolon then pr ";";
7693   if newline then pr "\n"
7694
7695 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7696 and generate_c_call_args ?handle ?(decl = false) style =
7697   pr "(";
7698   let comma = ref false in
7699   let next () =
7700     if !comma then pr ", ";
7701     comma := true
7702   in
7703   (match handle with
7704    | None -> ()
7705    | Some handle -> pr "%s" handle; comma := true
7706   );
7707   List.iter (
7708     fun arg ->
7709       next ();
7710       pr "%s" (name_of_argt arg)
7711   ) (snd style);
7712   (* For RBufferOut calls, add implicit &size parameter. *)
7713   if not decl then (
7714     match fst style with
7715     | RBufferOut _ ->
7716         next ();
7717         pr "&size"
7718     | _ -> ()
7719   );
7720   pr ")"
7721
7722 (* Generate the OCaml bindings interface. *)
7723 and generate_ocaml_mli () =
7724   generate_header OCamlStyle LGPLv2plus;
7725
7726   pr "\
7727 (** For API documentation you should refer to the C API
7728     in the guestfs(3) manual page.  The OCaml API uses almost
7729     exactly the same calls. *)
7730
7731 type t
7732 (** A [guestfs_h] handle. *)
7733
7734 exception Error of string
7735 (** This exception is raised when there is an error. *)
7736
7737 exception Handle_closed of string
7738 (** This exception is raised if you use a {!Guestfs.t} handle
7739     after calling {!close} on it.  The string is the name of
7740     the function. *)
7741
7742 val create : unit -> t
7743 (** Create a {!Guestfs.t} handle. *)
7744
7745 val close : t -> unit
7746 (** Close the {!Guestfs.t} handle and free up all resources used
7747     by it immediately.
7748
7749     Handles are closed by the garbage collector when they become
7750     unreferenced, but callers can call this in order to provide
7751     predictable cleanup. *)
7752
7753 ";
7754   generate_ocaml_structure_decls ();
7755
7756   (* The actions. *)
7757   List.iter (
7758     fun (name, style, _, _, _, shortdesc, _) ->
7759       generate_ocaml_prototype name style;
7760       pr "(** %s *)\n" shortdesc;
7761       pr "\n"
7762   ) all_functions_sorted
7763
7764 (* Generate the OCaml bindings implementation. *)
7765 and generate_ocaml_ml () =
7766   generate_header OCamlStyle LGPLv2plus;
7767
7768   pr "\
7769 type t
7770
7771 exception Error of string
7772 exception Handle_closed of string
7773
7774 external create : unit -> t = \"ocaml_guestfs_create\"
7775 external close : t -> unit = \"ocaml_guestfs_close\"
7776
7777 (* Give the exceptions names, so they can be raised from the C code. *)
7778 let () =
7779   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7780   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7781
7782 ";
7783
7784   generate_ocaml_structure_decls ();
7785
7786   (* The actions. *)
7787   List.iter (
7788     fun (name, style, _, _, _, shortdesc, _) ->
7789       generate_ocaml_prototype ~is_external:true name style;
7790   ) all_functions_sorted
7791
7792 (* Generate the OCaml bindings C implementation. *)
7793 and generate_ocaml_c () =
7794   generate_header CStyle LGPLv2plus;
7795
7796   pr "\
7797 #include <stdio.h>
7798 #include <stdlib.h>
7799 #include <string.h>
7800
7801 #include <caml/config.h>
7802 #include <caml/alloc.h>
7803 #include <caml/callback.h>
7804 #include <caml/fail.h>
7805 #include <caml/memory.h>
7806 #include <caml/mlvalues.h>
7807 #include <caml/signals.h>
7808
7809 #include <guestfs.h>
7810
7811 #include \"guestfs_c.h\"
7812
7813 /* Copy a hashtable of string pairs into an assoc-list.  We return
7814  * the list in reverse order, but hashtables aren't supposed to be
7815  * ordered anyway.
7816  */
7817 static CAMLprim value
7818 copy_table (char * const * argv)
7819 {
7820   CAMLparam0 ();
7821   CAMLlocal5 (rv, pairv, kv, vv, cons);
7822   int i;
7823
7824   rv = Val_int (0);
7825   for (i = 0; argv[i] != NULL; i += 2) {
7826     kv = caml_copy_string (argv[i]);
7827     vv = caml_copy_string (argv[i+1]);
7828     pairv = caml_alloc (2, 0);
7829     Store_field (pairv, 0, kv);
7830     Store_field (pairv, 1, vv);
7831     cons = caml_alloc (2, 0);
7832     Store_field (cons, 1, rv);
7833     rv = cons;
7834     Store_field (cons, 0, pairv);
7835   }
7836
7837   CAMLreturn (rv);
7838 }
7839
7840 ";
7841
7842   (* Struct copy functions. *)
7843
7844   let emit_ocaml_copy_list_function typ =
7845     pr "static CAMLprim value\n";
7846     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7847     pr "{\n";
7848     pr "  CAMLparam0 ();\n";
7849     pr "  CAMLlocal2 (rv, v);\n";
7850     pr "  unsigned int i;\n";
7851     pr "\n";
7852     pr "  if (%ss->len == 0)\n" typ;
7853     pr "    CAMLreturn (Atom (0));\n";
7854     pr "  else {\n";
7855     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7856     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7857     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7858     pr "      caml_modify (&Field (rv, i), v);\n";
7859     pr "    }\n";
7860     pr "    CAMLreturn (rv);\n";
7861     pr "  }\n";
7862     pr "}\n";
7863     pr "\n";
7864   in
7865
7866   List.iter (
7867     fun (typ, cols) ->
7868       let has_optpercent_col =
7869         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7870
7871       pr "static CAMLprim value\n";
7872       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7873       pr "{\n";
7874       pr "  CAMLparam0 ();\n";
7875       if has_optpercent_col then
7876         pr "  CAMLlocal3 (rv, v, v2);\n"
7877       else
7878         pr "  CAMLlocal2 (rv, v);\n";
7879       pr "\n";
7880       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7881       iteri (
7882         fun i col ->
7883           (match col with
7884            | name, FString ->
7885                pr "  v = caml_copy_string (%s->%s);\n" typ name
7886            | name, FBuffer ->
7887                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7888                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7889                  typ name typ name
7890            | name, FUUID ->
7891                pr "  v = caml_alloc_string (32);\n";
7892                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7893            | name, (FBytes|FInt64|FUInt64) ->
7894                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7895            | name, (FInt32|FUInt32) ->
7896                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7897            | name, FOptPercent ->
7898                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7899                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7900                pr "    v = caml_alloc (1, 0);\n";
7901                pr "    Store_field (v, 0, v2);\n";
7902                pr "  } else /* None */\n";
7903                pr "    v = Val_int (0);\n";
7904            | name, FChar ->
7905                pr "  v = Val_int (%s->%s);\n" typ name
7906           );
7907           pr "  Store_field (rv, %d, v);\n" i
7908       ) cols;
7909       pr "  CAMLreturn (rv);\n";
7910       pr "}\n";
7911       pr "\n";
7912   ) structs;
7913
7914   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7915   List.iter (
7916     function
7917     | typ, (RStructListOnly | RStructAndList) ->
7918         (* generate the function for typ *)
7919         emit_ocaml_copy_list_function typ
7920     | typ, _ -> () (* empty *)
7921   ) (rstructs_used_by all_functions);
7922
7923   (* The wrappers. *)
7924   List.iter (
7925     fun (name, style, _, _, _, _, _) ->
7926       pr "/* Automatically generated wrapper for function\n";
7927       pr " * ";
7928       generate_ocaml_prototype name style;
7929       pr " */\n";
7930       pr "\n";
7931
7932       let params =
7933         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7934
7935       let needs_extra_vs =
7936         match fst style with RConstOptString _ -> true | _ -> false in
7937
7938       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7939       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7940       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7941       pr "\n";
7942
7943       pr "CAMLprim value\n";
7944       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7945       List.iter (pr ", value %s") (List.tl params);
7946       pr ")\n";
7947       pr "{\n";
7948
7949       (match params with
7950        | [p1; p2; p3; p4; p5] ->
7951            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7952        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7953            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7954            pr "  CAMLxparam%d (%s);\n"
7955              (List.length rest) (String.concat ", " rest)
7956        | ps ->
7957            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7958       );
7959       if not needs_extra_vs then
7960         pr "  CAMLlocal1 (rv);\n"
7961       else
7962         pr "  CAMLlocal3 (rv, v, v2);\n";
7963       pr "\n";
7964
7965       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7966       pr "  if (g == NULL)\n";
7967       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7968       pr "\n";
7969
7970       List.iter (
7971         function
7972         | Pathname n
7973         | Device n | Dev_or_Path n
7974         | String n
7975         | FileIn n
7976         | FileOut n ->
7977             pr "  const char *%s = String_val (%sv);\n" n n
7978         | OptString n ->
7979             pr "  const char *%s =\n" n;
7980             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7981               n n
7982         | StringList n | DeviceList n ->
7983             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7984         | Bool n ->
7985             pr "  int %s = Bool_val (%sv);\n" n n
7986         | Int n ->
7987             pr "  int %s = Int_val (%sv);\n" n n
7988         | Int64 n ->
7989             pr "  int64_t %s = Int64_val (%sv);\n" n n
7990       ) (snd style);
7991       let error_code =
7992         match fst style with
7993         | RErr -> pr "  int r;\n"; "-1"
7994         | RInt _ -> pr "  int r;\n"; "-1"
7995         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7996         | RBool _ -> pr "  int r;\n"; "-1"
7997         | RConstString _ | RConstOptString _ ->
7998             pr "  const char *r;\n"; "NULL"
7999         | RString _ -> pr "  char *r;\n"; "NULL"
8000         | RStringList _ ->
8001             pr "  int i;\n";
8002             pr "  char **r;\n";
8003             "NULL"
8004         | RStruct (_, typ) ->
8005             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8006         | RStructList (_, typ) ->
8007             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8008         | RHashtable _ ->
8009             pr "  int i;\n";
8010             pr "  char **r;\n";
8011             "NULL"
8012         | RBufferOut _ ->
8013             pr "  char *r;\n";
8014             pr "  size_t size;\n";
8015             "NULL" in
8016       pr "\n";
8017
8018       pr "  caml_enter_blocking_section ();\n";
8019       pr "  r = guestfs_%s " name;
8020       generate_c_call_args ~handle:"g" style;
8021       pr ";\n";
8022       pr "  caml_leave_blocking_section ();\n";
8023
8024       List.iter (
8025         function
8026         | StringList n | DeviceList n ->
8027             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8028         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8029         | Bool _ | Int _ | Int64 _
8030         | FileIn _ | FileOut _ -> ()
8031       ) (snd style);
8032
8033       pr "  if (r == %s)\n" error_code;
8034       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8035       pr "\n";
8036
8037       (match fst style with
8038        | RErr -> pr "  rv = Val_unit;\n"
8039        | RInt _ -> pr "  rv = Val_int (r);\n"
8040        | RInt64 _ ->
8041            pr "  rv = caml_copy_int64 (r);\n"
8042        | RBool _ -> pr "  rv = Val_bool (r);\n"
8043        | RConstString _ ->
8044            pr "  rv = caml_copy_string (r);\n"
8045        | RConstOptString _ ->
8046            pr "  if (r) { /* Some string */\n";
8047            pr "    v = caml_alloc (1, 0);\n";
8048            pr "    v2 = caml_copy_string (r);\n";
8049            pr "    Store_field (v, 0, v2);\n";
8050            pr "  } else /* None */\n";
8051            pr "    v = Val_int (0);\n";
8052        | RString _ ->
8053            pr "  rv = caml_copy_string (r);\n";
8054            pr "  free (r);\n"
8055        | RStringList _ ->
8056            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8057            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8058            pr "  free (r);\n"
8059        | RStruct (_, typ) ->
8060            pr "  rv = copy_%s (r);\n" typ;
8061            pr "  guestfs_free_%s (r);\n" typ;
8062        | RStructList (_, typ) ->
8063            pr "  rv = copy_%s_list (r);\n" typ;
8064            pr "  guestfs_free_%s_list (r);\n" typ;
8065        | RHashtable _ ->
8066            pr "  rv = copy_table (r);\n";
8067            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8068            pr "  free (r);\n";
8069        | RBufferOut _ ->
8070            pr "  rv = caml_alloc_string (size);\n";
8071            pr "  memcpy (String_val (rv), r, size);\n";
8072       );
8073
8074       pr "  CAMLreturn (rv);\n";
8075       pr "}\n";
8076       pr "\n";
8077
8078       if List.length params > 5 then (
8079         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8080         pr "CAMLprim value ";
8081         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8082         pr "CAMLprim value\n";
8083         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8084         pr "{\n";
8085         pr "  return ocaml_guestfs_%s (argv[0]" name;
8086         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8087         pr ");\n";
8088         pr "}\n";
8089         pr "\n"
8090       )
8091   ) all_functions_sorted
8092
8093 and generate_ocaml_structure_decls () =
8094   List.iter (
8095     fun (typ, cols) ->
8096       pr "type %s = {\n" typ;
8097       List.iter (
8098         function
8099         | name, FString -> pr "  %s : string;\n" name
8100         | name, FBuffer -> pr "  %s : string;\n" name
8101         | name, FUUID -> pr "  %s : string;\n" name
8102         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8103         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8104         | name, FChar -> pr "  %s : char;\n" name
8105         | name, FOptPercent -> pr "  %s : float option;\n" name
8106       ) cols;
8107       pr "}\n";
8108       pr "\n"
8109   ) structs
8110
8111 and generate_ocaml_prototype ?(is_external = false) name style =
8112   if is_external then pr "external " else pr "val ";
8113   pr "%s : t -> " name;
8114   List.iter (
8115     function
8116     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8117     | OptString _ -> pr "string option -> "
8118     | StringList _ | DeviceList _ -> pr "string array -> "
8119     | Bool _ -> pr "bool -> "
8120     | Int _ -> pr "int -> "
8121     | Int64 _ -> pr "int64 -> "
8122   ) (snd style);
8123   (match fst style with
8124    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8125    | RInt _ -> pr "int"
8126    | RInt64 _ -> pr "int64"
8127    | RBool _ -> pr "bool"
8128    | RConstString _ -> pr "string"
8129    | RConstOptString _ -> pr "string option"
8130    | RString _ | RBufferOut _ -> pr "string"
8131    | RStringList _ -> pr "string array"
8132    | RStruct (_, typ) -> pr "%s" typ
8133    | RStructList (_, typ) -> pr "%s array" typ
8134    | RHashtable _ -> pr "(string * string) list"
8135   );
8136   if is_external then (
8137     pr " = ";
8138     if List.length (snd style) + 1 > 5 then
8139       pr "\"ocaml_guestfs_%s_byte\" " name;
8140     pr "\"ocaml_guestfs_%s\"" name
8141   );
8142   pr "\n"
8143
8144 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8145 and generate_perl_xs () =
8146   generate_header CStyle LGPLv2plus;
8147
8148   pr "\
8149 #include \"EXTERN.h\"
8150 #include \"perl.h\"
8151 #include \"XSUB.h\"
8152
8153 #include <guestfs.h>
8154
8155 #ifndef PRId64
8156 #define PRId64 \"lld\"
8157 #endif
8158
8159 static SV *
8160 my_newSVll(long long val) {
8161 #ifdef USE_64_BIT_ALL
8162   return newSViv(val);
8163 #else
8164   char buf[100];
8165   int len;
8166   len = snprintf(buf, 100, \"%%\" PRId64, val);
8167   return newSVpv(buf, len);
8168 #endif
8169 }
8170
8171 #ifndef PRIu64
8172 #define PRIu64 \"llu\"
8173 #endif
8174
8175 static SV *
8176 my_newSVull(unsigned long long val) {
8177 #ifdef USE_64_BIT_ALL
8178   return newSVuv(val);
8179 #else
8180   char buf[100];
8181   int len;
8182   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8183   return newSVpv(buf, len);
8184 #endif
8185 }
8186
8187 /* http://www.perlmonks.org/?node_id=680842 */
8188 static char **
8189 XS_unpack_charPtrPtr (SV *arg) {
8190   char **ret;
8191   AV *av;
8192   I32 i;
8193
8194   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8195     croak (\"array reference expected\");
8196
8197   av = (AV *)SvRV (arg);
8198   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8199   if (!ret)
8200     croak (\"malloc failed\");
8201
8202   for (i = 0; i <= av_len (av); i++) {
8203     SV **elem = av_fetch (av, i, 0);
8204
8205     if (!elem || !*elem)
8206       croak (\"missing element in list\");
8207
8208     ret[i] = SvPV_nolen (*elem);
8209   }
8210
8211   ret[i] = NULL;
8212
8213   return ret;
8214 }
8215
8216 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8217
8218 PROTOTYPES: ENABLE
8219
8220 guestfs_h *
8221 _create ()
8222    CODE:
8223       RETVAL = guestfs_create ();
8224       if (!RETVAL)
8225         croak (\"could not create guestfs handle\");
8226       guestfs_set_error_handler (RETVAL, NULL, NULL);
8227  OUTPUT:
8228       RETVAL
8229
8230 void
8231 DESTROY (g)
8232       guestfs_h *g;
8233  PPCODE:
8234       guestfs_close (g);
8235
8236 ";
8237
8238   List.iter (
8239     fun (name, style, _, _, _, _, _) ->
8240       (match fst style with
8241        | RErr -> pr "void\n"
8242        | RInt _ -> pr "SV *\n"
8243        | RInt64 _ -> pr "SV *\n"
8244        | RBool _ -> pr "SV *\n"
8245        | RConstString _ -> pr "SV *\n"
8246        | RConstOptString _ -> pr "SV *\n"
8247        | RString _ -> pr "SV *\n"
8248        | RBufferOut _ -> pr "SV *\n"
8249        | RStringList _
8250        | RStruct _ | RStructList _
8251        | RHashtable _ ->
8252            pr "void\n" (* all lists returned implictly on the stack *)
8253       );
8254       (* Call and arguments. *)
8255       pr "%s " name;
8256       generate_c_call_args ~handle:"g" ~decl:true style;
8257       pr "\n";
8258       pr "      guestfs_h *g;\n";
8259       iteri (
8260         fun i ->
8261           function
8262           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8263               pr "      char *%s;\n" n
8264           | OptString n ->
8265               (* http://www.perlmonks.org/?node_id=554277
8266                * Note that the implicit handle argument means we have
8267                * to add 1 to the ST(x) operator.
8268                *)
8269               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8270           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8271           | Bool n -> pr "      int %s;\n" n
8272           | Int n -> pr "      int %s;\n" n
8273           | Int64 n -> pr "      int64_t %s;\n" n
8274       ) (snd style);
8275
8276       let do_cleanups () =
8277         List.iter (
8278           function
8279           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8280           | Bool _ | Int _ | Int64 _
8281           | FileIn _ | FileOut _ -> ()
8282           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8283         ) (snd style)
8284       in
8285
8286       (* Code. *)
8287       (match fst style with
8288        | RErr ->
8289            pr "PREINIT:\n";
8290            pr "      int r;\n";
8291            pr " PPCODE:\n";
8292            pr "      r = guestfs_%s " name;
8293            generate_c_call_args ~handle:"g" style;
8294            pr ";\n";
8295            do_cleanups ();
8296            pr "      if (r == -1)\n";
8297            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8298        | RInt n
8299        | RBool n ->
8300            pr "PREINIT:\n";
8301            pr "      int %s;\n" n;
8302            pr "   CODE:\n";
8303            pr "      %s = guestfs_%s " n name;
8304            generate_c_call_args ~handle:"g" style;
8305            pr ";\n";
8306            do_cleanups ();
8307            pr "      if (%s == -1)\n" n;
8308            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8309            pr "      RETVAL = newSViv (%s);\n" n;
8310            pr " OUTPUT:\n";
8311            pr "      RETVAL\n"
8312        | RInt64 n ->
8313            pr "PREINIT:\n";
8314            pr "      int64_t %s;\n" n;
8315            pr "   CODE:\n";
8316            pr "      %s = guestfs_%s " n name;
8317            generate_c_call_args ~handle:"g" style;
8318            pr ";\n";
8319            do_cleanups ();
8320            pr "      if (%s == -1)\n" n;
8321            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8322            pr "      RETVAL = my_newSVll (%s);\n" n;
8323            pr " OUTPUT:\n";
8324            pr "      RETVAL\n"
8325        | RConstString n ->
8326            pr "PREINIT:\n";
8327            pr "      const char *%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 == NULL)\n" n;
8334            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8335            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8336            pr " OUTPUT:\n";
8337            pr "      RETVAL\n"
8338        | RConstOptString n ->
8339            pr "PREINIT:\n";
8340            pr "      const char *%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 == NULL)\n" n;
8347            pr "        RETVAL = &PL_sv_undef;\n";
8348            pr "      else\n";
8349            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8350            pr " OUTPUT:\n";
8351            pr "      RETVAL\n"
8352        | RString n ->
8353            pr "PREINIT:\n";
8354            pr "      char *%s;\n" n;
8355            pr "   CODE:\n";
8356            pr "      %s = guestfs_%s " n name;
8357            generate_c_call_args ~handle:"g" style;
8358            pr ";\n";
8359            do_cleanups ();
8360            pr "      if (%s == NULL)\n" n;
8361            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8362            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8363            pr "      free (%s);\n" n;
8364            pr " OUTPUT:\n";
8365            pr "      RETVAL\n"
8366        | RStringList n | RHashtable n ->
8367            pr "PREINIT:\n";
8368            pr "      char **%s;\n" n;
8369            pr "      int i, n;\n";
8370            pr " PPCODE:\n";
8371            pr "      %s = guestfs_%s " n name;
8372            generate_c_call_args ~handle:"g" style;
8373            pr ";\n";
8374            do_cleanups ();
8375            pr "      if (%s == NULL)\n" n;
8376            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8377            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8378            pr "      EXTEND (SP, n);\n";
8379            pr "      for (i = 0; i < n; ++i) {\n";
8380            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8381            pr "        free (%s[i]);\n" n;
8382            pr "      }\n";
8383            pr "      free (%s);\n" n;
8384        | RStruct (n, typ) ->
8385            let cols = cols_of_struct typ in
8386            generate_perl_struct_code typ cols name style n do_cleanups
8387        | RStructList (n, typ) ->
8388            let cols = cols_of_struct typ in
8389            generate_perl_struct_list_code typ cols name style n do_cleanups
8390        | RBufferOut n ->
8391            pr "PREINIT:\n";
8392            pr "      char *%s;\n" n;
8393            pr "      size_t size;\n";
8394            pr "   CODE:\n";
8395            pr "      %s = guestfs_%s " n name;
8396            generate_c_call_args ~handle:"g" style;
8397            pr ";\n";
8398            do_cleanups ();
8399            pr "      if (%s == NULL)\n" n;
8400            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8401            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8402            pr "      free (%s);\n" n;
8403            pr " OUTPUT:\n";
8404            pr "      RETVAL\n"
8405       );
8406
8407       pr "\n"
8408   ) all_functions
8409
8410 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8411   pr "PREINIT:\n";
8412   pr "      struct guestfs_%s_list *%s;\n" typ n;
8413   pr "      int i;\n";
8414   pr "      HV *hv;\n";
8415   pr " PPCODE:\n";
8416   pr "      %s = guestfs_%s " n name;
8417   generate_c_call_args ~handle:"g" style;
8418   pr ";\n";
8419   do_cleanups ();
8420   pr "      if (%s == NULL)\n" n;
8421   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8422   pr "      EXTEND (SP, %s->len);\n" n;
8423   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8424   pr "        hv = newHV ();\n";
8425   List.iter (
8426     function
8427     | name, FString ->
8428         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8429           name (String.length name) n name
8430     | name, FUUID ->
8431         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8432           name (String.length name) n name
8433     | name, FBuffer ->
8434         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8435           name (String.length name) n name n name
8436     | name, (FBytes|FUInt64) ->
8437         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8438           name (String.length name) n name
8439     | name, FInt64 ->
8440         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8441           name (String.length name) n name
8442     | name, (FInt32|FUInt32) ->
8443         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8444           name (String.length name) n name
8445     | name, FChar ->
8446         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8447           name (String.length name) n name
8448     | name, FOptPercent ->
8449         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8450           name (String.length name) n name
8451   ) cols;
8452   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8453   pr "      }\n";
8454   pr "      guestfs_free_%s_list (%s);\n" typ n
8455
8456 and generate_perl_struct_code typ cols name style n do_cleanups =
8457   pr "PREINIT:\n";
8458   pr "      struct guestfs_%s *%s;\n" typ n;
8459   pr " PPCODE:\n";
8460   pr "      %s = guestfs_%s " n name;
8461   generate_c_call_args ~handle:"g" style;
8462   pr ";\n";
8463   do_cleanups ();
8464   pr "      if (%s == NULL)\n" n;
8465   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8466   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8467   List.iter (
8468     fun ((name, _) as col) ->
8469       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8470
8471       match col with
8472       | name, FString ->
8473           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8474             n name
8475       | name, FBuffer ->
8476           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8477             n name n name
8478       | name, FUUID ->
8479           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8480             n name
8481       | name, (FBytes|FUInt64) ->
8482           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8483             n name
8484       | name, FInt64 ->
8485           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8486             n name
8487       | name, (FInt32|FUInt32) ->
8488           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8489             n name
8490       | name, FChar ->
8491           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8492             n name
8493       | name, FOptPercent ->
8494           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8495             n name
8496   ) cols;
8497   pr "      free (%s);\n" n
8498
8499 (* Generate Sys/Guestfs.pm. *)
8500 and generate_perl_pm () =
8501   generate_header HashStyle LGPLv2plus;
8502
8503   pr "\
8504 =pod
8505
8506 =head1 NAME
8507
8508 Sys::Guestfs - Perl bindings for libguestfs
8509
8510 =head1 SYNOPSIS
8511
8512  use Sys::Guestfs;
8513
8514  my $h = Sys::Guestfs->new ();
8515  $h->add_drive ('guest.img');
8516  $h->launch ();
8517  $h->mount ('/dev/sda1', '/');
8518  $h->touch ('/hello');
8519  $h->sync ();
8520
8521 =head1 DESCRIPTION
8522
8523 The C<Sys::Guestfs> module provides a Perl XS binding to the
8524 libguestfs API for examining and modifying virtual machine
8525 disk images.
8526
8527 Amongst the things this is good for: making batch configuration
8528 changes to guests, getting disk used/free statistics (see also:
8529 virt-df), migrating between virtualization systems (see also:
8530 virt-p2v), performing partial backups, performing partial guest
8531 clones, cloning guests and changing registry/UUID/hostname info, and
8532 much else besides.
8533
8534 Libguestfs uses Linux kernel and qemu code, and can access any type of
8535 guest filesystem that Linux and qemu can, including but not limited
8536 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8537 schemes, qcow, qcow2, vmdk.
8538
8539 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8540 LVs, what filesystem is in each LV, etc.).  It can also run commands
8541 in the context of the guest.  Also you can access filesystems over
8542 FUSE.
8543
8544 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8545 functions for using libguestfs from Perl, including integration
8546 with libvirt.
8547
8548 =head1 ERRORS
8549
8550 All errors turn into calls to C<croak> (see L<Carp(3)>).
8551
8552 =head1 METHODS
8553
8554 =over 4
8555
8556 =cut
8557
8558 package Sys::Guestfs;
8559
8560 use strict;
8561 use warnings;
8562
8563 require XSLoader;
8564 XSLoader::load ('Sys::Guestfs');
8565
8566 =item $h = Sys::Guestfs->new ();
8567
8568 Create a new guestfs handle.
8569
8570 =cut
8571
8572 sub new {
8573   my $proto = shift;
8574   my $class = ref ($proto) || $proto;
8575
8576   my $self = Sys::Guestfs::_create ();
8577   bless $self, $class;
8578   return $self;
8579 }
8580
8581 ";
8582
8583   (* Actions.  We only need to print documentation for these as
8584    * they are pulled in from the XS code automatically.
8585    *)
8586   List.iter (
8587     fun (name, style, _, flags, _, _, longdesc) ->
8588       if not (List.mem NotInDocs flags) then (
8589         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8590         pr "=item ";
8591         generate_perl_prototype name style;
8592         pr "\n\n";
8593         pr "%s\n\n" longdesc;
8594         if List.mem ProtocolLimitWarning flags then
8595           pr "%s\n\n" protocol_limit_warning;
8596         if List.mem DangerWillRobinson flags then
8597           pr "%s\n\n" danger_will_robinson;
8598         match deprecation_notice flags with
8599         | None -> ()
8600         | Some txt -> pr "%s\n\n" txt
8601       )
8602   ) all_functions_sorted;
8603
8604   (* End of file. *)
8605   pr "\
8606 =cut
8607
8608 1;
8609
8610 =back
8611
8612 =head1 COPYRIGHT
8613
8614 Copyright (C) %s Red Hat Inc.
8615
8616 =head1 LICENSE
8617
8618 Please see the file COPYING.LIB for the full license.
8619
8620 =head1 SEE ALSO
8621
8622 L<guestfs(3)>,
8623 L<guestfish(1)>,
8624 L<http://libguestfs.org>,
8625 L<Sys::Guestfs::Lib(3)>.
8626
8627 =cut
8628 " copyright_years
8629
8630 and generate_perl_prototype name style =
8631   (match fst style with
8632    | RErr -> ()
8633    | RBool n
8634    | RInt n
8635    | RInt64 n
8636    | RConstString n
8637    | RConstOptString n
8638    | RString n
8639    | RBufferOut n -> pr "$%s = " n
8640    | RStruct (n,_)
8641    | RHashtable n -> pr "%%%s = " n
8642    | RStringList n
8643    | RStructList (n,_) -> pr "@%s = " n
8644   );
8645   pr "$h->%s (" name;
8646   let comma = ref false in
8647   List.iter (
8648     fun arg ->
8649       if !comma then pr ", ";
8650       comma := true;
8651       match arg with
8652       | Pathname n | Device n | Dev_or_Path n | String n
8653       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8654           pr "$%s" n
8655       | StringList n | DeviceList n ->
8656           pr "\\@%s" n
8657   ) (snd style);
8658   pr ");"
8659
8660 (* Generate Python C module. *)
8661 and generate_python_c () =
8662   generate_header CStyle LGPLv2plus;
8663
8664   pr "\
8665 #include <Python.h>
8666
8667 #include <stdio.h>
8668 #include <stdlib.h>
8669 #include <assert.h>
8670
8671 #include \"guestfs.h\"
8672
8673 typedef struct {
8674   PyObject_HEAD
8675   guestfs_h *g;
8676 } Pyguestfs_Object;
8677
8678 static guestfs_h *
8679 get_handle (PyObject *obj)
8680 {
8681   assert (obj);
8682   assert (obj != Py_None);
8683   return ((Pyguestfs_Object *) obj)->g;
8684 }
8685
8686 static PyObject *
8687 put_handle (guestfs_h *g)
8688 {
8689   assert (g);
8690   return
8691     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8692 }
8693
8694 /* This list should be freed (but not the strings) after use. */
8695 static char **
8696 get_string_list (PyObject *obj)
8697 {
8698   int i, len;
8699   char **r;
8700
8701   assert (obj);
8702
8703   if (!PyList_Check (obj)) {
8704     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8705     return NULL;
8706   }
8707
8708   len = PyList_Size (obj);
8709   r = malloc (sizeof (char *) * (len+1));
8710   if (r == NULL) {
8711     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8712     return NULL;
8713   }
8714
8715   for (i = 0; i < len; ++i)
8716     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8717   r[len] = NULL;
8718
8719   return r;
8720 }
8721
8722 static PyObject *
8723 put_string_list (char * const * const argv)
8724 {
8725   PyObject *list;
8726   int argc, i;
8727
8728   for (argc = 0; argv[argc] != NULL; ++argc)
8729     ;
8730
8731   list = PyList_New (argc);
8732   for (i = 0; i < argc; ++i)
8733     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8734
8735   return list;
8736 }
8737
8738 static PyObject *
8739 put_table (char * const * const argv)
8740 {
8741   PyObject *list, *item;
8742   int argc, i;
8743
8744   for (argc = 0; argv[argc] != NULL; ++argc)
8745     ;
8746
8747   list = PyList_New (argc >> 1);
8748   for (i = 0; i < argc; i += 2) {
8749     item = PyTuple_New (2);
8750     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8751     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8752     PyList_SetItem (list, i >> 1, item);
8753   }
8754
8755   return list;
8756 }
8757
8758 static void
8759 free_strings (char **argv)
8760 {
8761   int argc;
8762
8763   for (argc = 0; argv[argc] != NULL; ++argc)
8764     free (argv[argc]);
8765   free (argv);
8766 }
8767
8768 static PyObject *
8769 py_guestfs_create (PyObject *self, PyObject *args)
8770 {
8771   guestfs_h *g;
8772
8773   g = guestfs_create ();
8774   if (g == NULL) {
8775     PyErr_SetString (PyExc_RuntimeError,
8776                      \"guestfs.create: failed to allocate handle\");
8777     return NULL;
8778   }
8779   guestfs_set_error_handler (g, NULL, NULL);
8780   return put_handle (g);
8781 }
8782
8783 static PyObject *
8784 py_guestfs_close (PyObject *self, PyObject *args)
8785 {
8786   PyObject *py_g;
8787   guestfs_h *g;
8788
8789   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8790     return NULL;
8791   g = get_handle (py_g);
8792
8793   guestfs_close (g);
8794
8795   Py_INCREF (Py_None);
8796   return Py_None;
8797 }
8798
8799 ";
8800
8801   let emit_put_list_function typ =
8802     pr "static PyObject *\n";
8803     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8804     pr "{\n";
8805     pr "  PyObject *list;\n";
8806     pr "  int i;\n";
8807     pr "\n";
8808     pr "  list = PyList_New (%ss->len);\n" typ;
8809     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8810     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8811     pr "  return list;\n";
8812     pr "};\n";
8813     pr "\n"
8814   in
8815
8816   (* Structures, turned into Python dictionaries. *)
8817   List.iter (
8818     fun (typ, cols) ->
8819       pr "static PyObject *\n";
8820       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8821       pr "{\n";
8822       pr "  PyObject *dict;\n";
8823       pr "\n";
8824       pr "  dict = PyDict_New ();\n";
8825       List.iter (
8826         function
8827         | name, FString ->
8828             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8829             pr "                        PyString_FromString (%s->%s));\n"
8830               typ name
8831         | name, FBuffer ->
8832             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8833             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8834               typ name typ name
8835         | name, FUUID ->
8836             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8837             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8838               typ name
8839         | name, (FBytes|FUInt64) ->
8840             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8841             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8842               typ name
8843         | name, FInt64 ->
8844             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8845             pr "                        PyLong_FromLongLong (%s->%s));\n"
8846               typ name
8847         | name, FUInt32 ->
8848             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8849             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8850               typ name
8851         | name, FInt32 ->
8852             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8853             pr "                        PyLong_FromLong (%s->%s));\n"
8854               typ name
8855         | name, FOptPercent ->
8856             pr "  if (%s->%s >= 0)\n" typ name;
8857             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8858             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8859               typ name;
8860             pr "  else {\n";
8861             pr "    Py_INCREF (Py_None);\n";
8862             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8863             pr "  }\n"
8864         | name, FChar ->
8865             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8866             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8867       ) cols;
8868       pr "  return dict;\n";
8869       pr "};\n";
8870       pr "\n";
8871
8872   ) structs;
8873
8874   (* Emit a put_TYPE_list function definition only if that function is used. *)
8875   List.iter (
8876     function
8877     | typ, (RStructListOnly | RStructAndList) ->
8878         (* generate the function for typ *)
8879         emit_put_list_function typ
8880     | typ, _ -> () (* empty *)
8881   ) (rstructs_used_by all_functions);
8882
8883   (* Python wrapper functions. *)
8884   List.iter (
8885     fun (name, style, _, _, _, _, _) ->
8886       pr "static PyObject *\n";
8887       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8888       pr "{\n";
8889
8890       pr "  PyObject *py_g;\n";
8891       pr "  guestfs_h *g;\n";
8892       pr "  PyObject *py_r;\n";
8893
8894       let error_code =
8895         match fst style with
8896         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8897         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8898         | RConstString _ | RConstOptString _ ->
8899             pr "  const char *r;\n"; "NULL"
8900         | RString _ -> pr "  char *r;\n"; "NULL"
8901         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8902         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8903         | RStructList (_, typ) ->
8904             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8905         | RBufferOut _ ->
8906             pr "  char *r;\n";
8907             pr "  size_t size;\n";
8908             "NULL" in
8909
8910       List.iter (
8911         function
8912         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8913             pr "  const char *%s;\n" n
8914         | OptString n -> pr "  const char *%s;\n" n
8915         | StringList n | DeviceList n ->
8916             pr "  PyObject *py_%s;\n" n;
8917             pr "  char **%s;\n" n
8918         | Bool n -> pr "  int %s;\n" n
8919         | Int n -> pr "  int %s;\n" n
8920         | Int64 n -> pr "  long long %s;\n" n
8921       ) (snd style);
8922
8923       pr "\n";
8924
8925       (* Convert the parameters. *)
8926       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8927       List.iter (
8928         function
8929         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8930         | OptString _ -> pr "z"
8931         | StringList _ | DeviceList _ -> pr "O"
8932         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8933         | Int _ -> pr "i"
8934         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8935                              * emulate C's int/long/long long in Python?
8936                              *)
8937       ) (snd style);
8938       pr ":guestfs_%s\",\n" name;
8939       pr "                         &py_g";
8940       List.iter (
8941         function
8942         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8943         | OptString n -> pr ", &%s" n
8944         | StringList n | DeviceList n -> pr ", &py_%s" n
8945         | Bool n -> pr ", &%s" n
8946         | Int n -> pr ", &%s" n
8947         | Int64 n -> pr ", &%s" n
8948       ) (snd style);
8949
8950       pr "))\n";
8951       pr "    return NULL;\n";
8952
8953       pr "  g = get_handle (py_g);\n";
8954       List.iter (
8955         function
8956         | Pathname _ | Device _ | Dev_or_Path _ | String _
8957         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8958         | StringList n | DeviceList n ->
8959             pr "  %s = get_string_list (py_%s);\n" n n;
8960             pr "  if (!%s) return NULL;\n" n
8961       ) (snd style);
8962
8963       pr "\n";
8964
8965       pr "  r = guestfs_%s " name;
8966       generate_c_call_args ~handle:"g" style;
8967       pr ";\n";
8968
8969       List.iter (
8970         function
8971         | Pathname _ | Device _ | Dev_or_Path _ | String _
8972         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8973         | StringList n | DeviceList n ->
8974             pr "  free (%s);\n" n
8975       ) (snd style);
8976
8977       pr "  if (r == %s) {\n" error_code;
8978       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8979       pr "    return NULL;\n";
8980       pr "  }\n";
8981       pr "\n";
8982
8983       (match fst style with
8984        | RErr ->
8985            pr "  Py_INCREF (Py_None);\n";
8986            pr "  py_r = Py_None;\n"
8987        | RInt _
8988        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8989        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8990        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8991        | RConstOptString _ ->
8992            pr "  if (r)\n";
8993            pr "    py_r = PyString_FromString (r);\n";
8994            pr "  else {\n";
8995            pr "    Py_INCREF (Py_None);\n";
8996            pr "    py_r = Py_None;\n";
8997            pr "  }\n"
8998        | RString _ ->
8999            pr "  py_r = PyString_FromString (r);\n";
9000            pr "  free (r);\n"
9001        | RStringList _ ->
9002            pr "  py_r = put_string_list (r);\n";
9003            pr "  free_strings (r);\n"
9004        | RStruct (_, typ) ->
9005            pr "  py_r = put_%s (r);\n" typ;
9006            pr "  guestfs_free_%s (r);\n" typ
9007        | RStructList (_, typ) ->
9008            pr "  py_r = put_%s_list (r);\n" typ;
9009            pr "  guestfs_free_%s_list (r);\n" typ
9010        | RHashtable n ->
9011            pr "  py_r = put_table (r);\n";
9012            pr "  free_strings (r);\n"
9013        | RBufferOut _ ->
9014            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9015            pr "  free (r);\n"
9016       );
9017
9018       pr "  return py_r;\n";
9019       pr "}\n";
9020       pr "\n"
9021   ) all_functions;
9022
9023   (* Table of functions. *)
9024   pr "static PyMethodDef methods[] = {\n";
9025   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9026   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9027   List.iter (
9028     fun (name, _, _, _, _, _, _) ->
9029       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9030         name name
9031   ) all_functions;
9032   pr "  { NULL, NULL, 0, NULL }\n";
9033   pr "};\n";
9034   pr "\n";
9035
9036   (* Init function. *)
9037   pr "\
9038 void
9039 initlibguestfsmod (void)
9040 {
9041   static int initialized = 0;
9042
9043   if (initialized) return;
9044   Py_InitModule ((char *) \"libguestfsmod\", methods);
9045   initialized = 1;
9046 }
9047 "
9048
9049 (* Generate Python module. *)
9050 and generate_python_py () =
9051   generate_header HashStyle LGPLv2plus;
9052
9053   pr "\
9054 u\"\"\"Python bindings for libguestfs
9055
9056 import guestfs
9057 g = guestfs.GuestFS ()
9058 g.add_drive (\"guest.img\")
9059 g.launch ()
9060 parts = g.list_partitions ()
9061
9062 The guestfs module provides a Python binding to the libguestfs API
9063 for examining and modifying virtual machine disk images.
9064
9065 Amongst the things this is good for: making batch configuration
9066 changes to guests, getting disk used/free statistics (see also:
9067 virt-df), migrating between virtualization systems (see also:
9068 virt-p2v), performing partial backups, performing partial guest
9069 clones, cloning guests and changing registry/UUID/hostname info, and
9070 much else besides.
9071
9072 Libguestfs uses Linux kernel and qemu code, and can access any type of
9073 guest filesystem that Linux and qemu can, including but not limited
9074 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9075 schemes, qcow, qcow2, vmdk.
9076
9077 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9078 LVs, what filesystem is in each LV, etc.).  It can also run commands
9079 in the context of the guest.  Also you can access filesystems over
9080 FUSE.
9081
9082 Errors which happen while using the API are turned into Python
9083 RuntimeError exceptions.
9084
9085 To create a guestfs handle you usually have to perform the following
9086 sequence of calls:
9087
9088 # Create the handle, call add_drive at least once, and possibly
9089 # several times if the guest has multiple block devices:
9090 g = guestfs.GuestFS ()
9091 g.add_drive (\"guest.img\")
9092
9093 # Launch the qemu subprocess and wait for it to become ready:
9094 g.launch ()
9095
9096 # Now you can issue commands, for example:
9097 logvols = g.lvs ()
9098
9099 \"\"\"
9100
9101 import libguestfsmod
9102
9103 class GuestFS:
9104     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9105
9106     def __init__ (self):
9107         \"\"\"Create a new libguestfs handle.\"\"\"
9108         self._o = libguestfsmod.create ()
9109
9110     def __del__ (self):
9111         libguestfsmod.close (self._o)
9112
9113 ";
9114
9115   List.iter (
9116     fun (name, style, _, flags, _, _, longdesc) ->
9117       pr "    def %s " name;
9118       generate_py_call_args ~handle:"self" (snd style);
9119       pr ":\n";
9120
9121       if not (List.mem NotInDocs flags) then (
9122         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9123         let doc =
9124           match fst style with
9125           | RErr | RInt _ | RInt64 _ | RBool _
9126           | RConstOptString _ | RConstString _
9127           | RString _ | RBufferOut _ -> doc
9128           | RStringList _ ->
9129               doc ^ "\n\nThis function returns a list of strings."
9130           | RStruct (_, typ) ->
9131               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9132           | RStructList (_, typ) ->
9133               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9134           | RHashtable _ ->
9135               doc ^ "\n\nThis function returns a dictionary." in
9136         let doc =
9137           if List.mem ProtocolLimitWarning flags then
9138             doc ^ "\n\n" ^ protocol_limit_warning
9139           else doc in
9140         let doc =
9141           if List.mem DangerWillRobinson flags then
9142             doc ^ "\n\n" ^ danger_will_robinson
9143           else doc in
9144         let doc =
9145           match deprecation_notice flags with
9146           | None -> doc
9147           | Some txt -> doc ^ "\n\n" ^ txt in
9148         let doc = pod2text ~width:60 name doc in
9149         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9150         let doc = String.concat "\n        " doc in
9151         pr "        u\"\"\"%s\"\"\"\n" doc;
9152       );
9153       pr "        return libguestfsmod.%s " name;
9154       generate_py_call_args ~handle:"self._o" (snd style);
9155       pr "\n";
9156       pr "\n";
9157   ) all_functions
9158
9159 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9160 and generate_py_call_args ~handle args =
9161   pr "(%s" handle;
9162   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9163   pr ")"
9164
9165 (* Useful if you need the longdesc POD text as plain text.  Returns a
9166  * list of lines.
9167  *
9168  * Because this is very slow (the slowest part of autogeneration),
9169  * we memoize the results.
9170  *)
9171 and pod2text ~width name longdesc =
9172   let key = width, name, longdesc in
9173   try Hashtbl.find pod2text_memo key
9174   with Not_found ->
9175     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9176     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9177     close_out chan;
9178     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9179     let chan = open_process_in cmd in
9180     let lines = ref [] in
9181     let rec loop i =
9182       let line = input_line chan in
9183       if i = 1 then             (* discard the first line of output *)
9184         loop (i+1)
9185       else (
9186         let line = triml line in
9187         lines := line :: !lines;
9188         loop (i+1)
9189       ) in
9190     let lines = try loop 1 with End_of_file -> List.rev !lines in
9191     unlink filename;
9192     (match close_process_in chan with
9193      | WEXITED 0 -> ()
9194      | WEXITED i ->
9195          failwithf "pod2text: process exited with non-zero status (%d)" i
9196      | WSIGNALED i | WSTOPPED i ->
9197          failwithf "pod2text: process signalled or stopped by signal %d" i
9198     );
9199     Hashtbl.add pod2text_memo key lines;
9200     pod2text_memo_updated ();
9201     lines
9202
9203 (* Generate ruby bindings. *)
9204 and generate_ruby_c () =
9205   generate_header CStyle LGPLv2plus;
9206
9207   pr "\
9208 #include <stdio.h>
9209 #include <stdlib.h>
9210
9211 #include <ruby.h>
9212
9213 #include \"guestfs.h\"
9214
9215 #include \"extconf.h\"
9216
9217 /* For Ruby < 1.9 */
9218 #ifndef RARRAY_LEN
9219 #define RARRAY_LEN(r) (RARRAY((r))->len)
9220 #endif
9221
9222 static VALUE m_guestfs;                 /* guestfs module */
9223 static VALUE c_guestfs;                 /* guestfs_h handle */
9224 static VALUE e_Error;                   /* used for all errors */
9225
9226 static void ruby_guestfs_free (void *p)
9227 {
9228   if (!p) return;
9229   guestfs_close ((guestfs_h *) p);
9230 }
9231
9232 static VALUE ruby_guestfs_create (VALUE m)
9233 {
9234   guestfs_h *g;
9235
9236   g = guestfs_create ();
9237   if (!g)
9238     rb_raise (e_Error, \"failed to create guestfs handle\");
9239
9240   /* Don't print error messages to stderr by default. */
9241   guestfs_set_error_handler (g, NULL, NULL);
9242
9243   /* Wrap it, and make sure the close function is called when the
9244    * handle goes away.
9245    */
9246   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9247 }
9248
9249 static VALUE ruby_guestfs_close (VALUE gv)
9250 {
9251   guestfs_h *g;
9252   Data_Get_Struct (gv, guestfs_h, g);
9253
9254   ruby_guestfs_free (g);
9255   DATA_PTR (gv) = NULL;
9256
9257   return Qnil;
9258 }
9259
9260 ";
9261
9262   List.iter (
9263     fun (name, style, _, _, _, _, _) ->
9264       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9265       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9266       pr ")\n";
9267       pr "{\n";
9268       pr "  guestfs_h *g;\n";
9269       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9270       pr "  if (!g)\n";
9271       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9272         name;
9273       pr "\n";
9274
9275       List.iter (
9276         function
9277         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9278             pr "  Check_Type (%sv, T_STRING);\n" n;
9279             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9280             pr "  if (!%s)\n" n;
9281             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9282             pr "              \"%s\", \"%s\");\n" n name
9283         | OptString n ->
9284             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9285         | StringList n | DeviceList n ->
9286             pr "  char **%s;\n" n;
9287             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9288             pr "  {\n";
9289             pr "    int i, len;\n";
9290             pr "    len = RARRAY_LEN (%sv);\n" n;
9291             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9292               n;
9293             pr "    for (i = 0; i < len; ++i) {\n";
9294             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9295             pr "      %s[i] = StringValueCStr (v);\n" n;
9296             pr "    }\n";
9297             pr "    %s[len] = NULL;\n" n;
9298             pr "  }\n";
9299         | Bool n ->
9300             pr "  int %s = RTEST (%sv);\n" n n
9301         | Int n ->
9302             pr "  int %s = NUM2INT (%sv);\n" n n
9303         | Int64 n ->
9304             pr "  long long %s = NUM2LL (%sv);\n" n n
9305       ) (snd style);
9306       pr "\n";
9307
9308       let error_code =
9309         match fst style with
9310         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9311         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9312         | RConstString _ | RConstOptString _ ->
9313             pr "  const char *r;\n"; "NULL"
9314         | RString _ -> pr "  char *r;\n"; "NULL"
9315         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9316         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9317         | RStructList (_, typ) ->
9318             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9319         | RBufferOut _ ->
9320             pr "  char *r;\n";
9321             pr "  size_t size;\n";
9322             "NULL" in
9323       pr "\n";
9324
9325       pr "  r = guestfs_%s " name;
9326       generate_c_call_args ~handle:"g" style;
9327       pr ";\n";
9328
9329       List.iter (
9330         function
9331         | Pathname _ | Device _ | Dev_or_Path _ | String _
9332         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9333         | StringList n | DeviceList n ->
9334             pr "  free (%s);\n" n
9335       ) (snd style);
9336
9337       pr "  if (r == %s)\n" error_code;
9338       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9339       pr "\n";
9340
9341       (match fst style with
9342        | RErr ->
9343            pr "  return Qnil;\n"
9344        | RInt _ | RBool _ ->
9345            pr "  return INT2NUM (r);\n"
9346        | RInt64 _ ->
9347            pr "  return ULL2NUM (r);\n"
9348        | RConstString _ ->
9349            pr "  return rb_str_new2 (r);\n";
9350        | RConstOptString _ ->
9351            pr "  if (r)\n";
9352            pr "    return rb_str_new2 (r);\n";
9353            pr "  else\n";
9354            pr "    return Qnil;\n";
9355        | RString _ ->
9356            pr "  VALUE rv = rb_str_new2 (r);\n";
9357            pr "  free (r);\n";
9358            pr "  return rv;\n";
9359        | RStringList _ ->
9360            pr "  int i, len = 0;\n";
9361            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9362            pr "  VALUE rv = rb_ary_new2 (len);\n";
9363            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9364            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9365            pr "    free (r[i]);\n";
9366            pr "  }\n";
9367            pr "  free (r);\n";
9368            pr "  return rv;\n"
9369        | RStruct (_, typ) ->
9370            let cols = cols_of_struct typ in
9371            generate_ruby_struct_code typ cols
9372        | RStructList (_, typ) ->
9373            let cols = cols_of_struct typ in
9374            generate_ruby_struct_list_code typ cols
9375        | RHashtable _ ->
9376            pr "  VALUE rv = rb_hash_new ();\n";
9377            pr "  int i;\n";
9378            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9379            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9380            pr "    free (r[i]);\n";
9381            pr "    free (r[i+1]);\n";
9382            pr "  }\n";
9383            pr "  free (r);\n";
9384            pr "  return rv;\n"
9385        | RBufferOut _ ->
9386            pr "  VALUE rv = rb_str_new (r, size);\n";
9387            pr "  free (r);\n";
9388            pr "  return rv;\n";
9389       );
9390
9391       pr "}\n";
9392       pr "\n"
9393   ) all_functions;
9394
9395   pr "\
9396 /* Initialize the module. */
9397 void Init__guestfs ()
9398 {
9399   m_guestfs = rb_define_module (\"Guestfs\");
9400   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9401   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9402
9403   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9404   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9405
9406 ";
9407   (* Define the rest of the methods. *)
9408   List.iter (
9409     fun (name, style, _, _, _, _, _) ->
9410       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9411       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9412   ) all_functions;
9413
9414   pr "}\n"
9415
9416 (* Ruby code to return a struct. *)
9417 and generate_ruby_struct_code typ cols =
9418   pr "  VALUE rv = rb_hash_new ();\n";
9419   List.iter (
9420     function
9421     | name, FString ->
9422         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9423     | name, FBuffer ->
9424         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9425     | name, FUUID ->
9426         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9427     | name, (FBytes|FUInt64) ->
9428         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9429     | name, FInt64 ->
9430         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9431     | name, FUInt32 ->
9432         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9433     | name, FInt32 ->
9434         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9435     | name, FOptPercent ->
9436         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9437     | name, FChar -> (* XXX wrong? *)
9438         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9439   ) cols;
9440   pr "  guestfs_free_%s (r);\n" typ;
9441   pr "  return rv;\n"
9442
9443 (* Ruby code to return a struct list. *)
9444 and generate_ruby_struct_list_code typ cols =
9445   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9446   pr "  int i;\n";
9447   pr "  for (i = 0; i < r->len; ++i) {\n";
9448   pr "    VALUE hv = rb_hash_new ();\n";
9449   List.iter (
9450     function
9451     | name, FString ->
9452         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9453     | name, FBuffer ->
9454         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
9455     | name, FUUID ->
9456         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9457     | name, (FBytes|FUInt64) ->
9458         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9459     | name, FInt64 ->
9460         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9461     | name, FUInt32 ->
9462         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9463     | name, FInt32 ->
9464         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9465     | name, FOptPercent ->
9466         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9467     | name, FChar -> (* XXX wrong? *)
9468         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9469   ) cols;
9470   pr "    rb_ary_push (rv, hv);\n";
9471   pr "  }\n";
9472   pr "  guestfs_free_%s_list (r);\n" typ;
9473   pr "  return rv;\n"
9474
9475 (* Generate Java bindings GuestFS.java file. *)
9476 and generate_java_java () =
9477   generate_header CStyle LGPLv2plus;
9478
9479   pr "\
9480 package com.redhat.et.libguestfs;
9481
9482 import java.util.HashMap;
9483 import com.redhat.et.libguestfs.LibGuestFSException;
9484 import com.redhat.et.libguestfs.PV;
9485 import com.redhat.et.libguestfs.VG;
9486 import com.redhat.et.libguestfs.LV;
9487 import com.redhat.et.libguestfs.Stat;
9488 import com.redhat.et.libguestfs.StatVFS;
9489 import com.redhat.et.libguestfs.IntBool;
9490 import com.redhat.et.libguestfs.Dirent;
9491
9492 /**
9493  * The GuestFS object is a libguestfs handle.
9494  *
9495  * @author rjones
9496  */
9497 public class GuestFS {
9498   // Load the native code.
9499   static {
9500     System.loadLibrary (\"guestfs_jni\");
9501   }
9502
9503   /**
9504    * The native guestfs_h pointer.
9505    */
9506   long g;
9507
9508   /**
9509    * Create a libguestfs handle.
9510    *
9511    * @throws LibGuestFSException
9512    */
9513   public GuestFS () throws LibGuestFSException
9514   {
9515     g = _create ();
9516   }
9517   private native long _create () throws LibGuestFSException;
9518
9519   /**
9520    * Close a libguestfs handle.
9521    *
9522    * You can also leave handles to be collected by the garbage
9523    * collector, but this method ensures that the resources used
9524    * by the handle are freed up immediately.  If you call any
9525    * other methods after closing the handle, you will get an
9526    * exception.
9527    *
9528    * @throws LibGuestFSException
9529    */
9530   public void close () throws LibGuestFSException
9531   {
9532     if (g != 0)
9533       _close (g);
9534     g = 0;
9535   }
9536   private native void _close (long g) throws LibGuestFSException;
9537
9538   public void finalize () throws LibGuestFSException
9539   {
9540     close ();
9541   }
9542
9543 ";
9544
9545   List.iter (
9546     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9547       if not (List.mem NotInDocs flags); then (
9548         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9549         let doc =
9550           if List.mem ProtocolLimitWarning flags then
9551             doc ^ "\n\n" ^ protocol_limit_warning
9552           else doc in
9553         let doc =
9554           if List.mem DangerWillRobinson flags then
9555             doc ^ "\n\n" ^ danger_will_robinson
9556           else doc in
9557         let doc =
9558           match deprecation_notice flags with
9559           | None -> doc
9560           | Some txt -> doc ^ "\n\n" ^ txt in
9561         let doc = pod2text ~width:60 name doc in
9562         let doc = List.map (            (* RHBZ#501883 *)
9563           function
9564           | "" -> "<p>"
9565           | nonempty -> nonempty
9566         ) doc in
9567         let doc = String.concat "\n   * " doc in
9568
9569         pr "  /**\n";
9570         pr "   * %s\n" shortdesc;
9571         pr "   * <p>\n";
9572         pr "   * %s\n" doc;
9573         pr "   * @throws LibGuestFSException\n";
9574         pr "   */\n";
9575         pr "  ";
9576       );
9577       generate_java_prototype ~public:true ~semicolon:false name style;
9578       pr "\n";
9579       pr "  {\n";
9580       pr "    if (g == 0)\n";
9581       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9582         name;
9583       pr "    ";
9584       if fst style <> RErr then pr "return ";
9585       pr "_%s " name;
9586       generate_java_call_args ~handle:"g" (snd style);
9587       pr ";\n";
9588       pr "  }\n";
9589       pr "  ";
9590       generate_java_prototype ~privat:true ~native:true name style;
9591       pr "\n";
9592       pr "\n";
9593   ) all_functions;
9594
9595   pr "}\n"
9596
9597 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9598 and generate_java_call_args ~handle args =
9599   pr "(%s" handle;
9600   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9601   pr ")"
9602
9603 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9604     ?(semicolon=true) name style =
9605   if privat then pr "private ";
9606   if public then pr "public ";
9607   if native then pr "native ";
9608
9609   (* return type *)
9610   (match fst style with
9611    | RErr -> pr "void ";
9612    | RInt _ -> pr "int ";
9613    | RInt64 _ -> pr "long ";
9614    | RBool _ -> pr "boolean ";
9615    | RConstString _ | RConstOptString _ | RString _
9616    | RBufferOut _ -> pr "String ";
9617    | RStringList _ -> pr "String[] ";
9618    | RStruct (_, typ) ->
9619        let name = java_name_of_struct typ in
9620        pr "%s " name;
9621    | RStructList (_, typ) ->
9622        let name = java_name_of_struct typ in
9623        pr "%s[] " name;
9624    | RHashtable _ -> pr "HashMap<String,String> ";
9625   );
9626
9627   if native then pr "_%s " name else pr "%s " name;
9628   pr "(";
9629   let needs_comma = ref false in
9630   if native then (
9631     pr "long g";
9632     needs_comma := true
9633   );
9634
9635   (* args *)
9636   List.iter (
9637     fun arg ->
9638       if !needs_comma then pr ", ";
9639       needs_comma := true;
9640
9641       match arg with
9642       | Pathname n
9643       | Device n | Dev_or_Path n
9644       | String n
9645       | OptString n
9646       | FileIn n
9647       | FileOut n ->
9648           pr "String %s" n
9649       | StringList n | DeviceList n ->
9650           pr "String[] %s" n
9651       | Bool n ->
9652           pr "boolean %s" n
9653       | Int n ->
9654           pr "int %s" n
9655       | Int64 n ->
9656           pr "long %s" n
9657   ) (snd style);
9658
9659   pr ")\n";
9660   pr "    throws LibGuestFSException";
9661   if semicolon then pr ";"
9662
9663 and generate_java_struct jtyp cols () =
9664   generate_header CStyle LGPLv2plus;
9665
9666   pr "\
9667 package com.redhat.et.libguestfs;
9668
9669 /**
9670  * Libguestfs %s structure.
9671  *
9672  * @author rjones
9673  * @see GuestFS
9674  */
9675 public class %s {
9676 " jtyp jtyp;
9677
9678   List.iter (
9679     function
9680     | name, FString
9681     | name, FUUID
9682     | name, FBuffer -> pr "  public String %s;\n" name
9683     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9684     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9685     | name, FChar -> pr "  public char %s;\n" name
9686     | name, FOptPercent ->
9687         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9688         pr "  public float %s;\n" name
9689   ) cols;
9690
9691   pr "}\n"
9692
9693 and generate_java_c () =
9694   generate_header CStyle LGPLv2plus;
9695
9696   pr "\
9697 #include <stdio.h>
9698 #include <stdlib.h>
9699 #include <string.h>
9700
9701 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9702 #include \"guestfs.h\"
9703
9704 /* Note that this function returns.  The exception is not thrown
9705  * until after the wrapper function returns.
9706  */
9707 static void
9708 throw_exception (JNIEnv *env, const char *msg)
9709 {
9710   jclass cl;
9711   cl = (*env)->FindClass (env,
9712                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9713   (*env)->ThrowNew (env, cl, msg);
9714 }
9715
9716 JNIEXPORT jlong JNICALL
9717 Java_com_redhat_et_libguestfs_GuestFS__1create
9718   (JNIEnv *env, jobject obj)
9719 {
9720   guestfs_h *g;
9721
9722   g = guestfs_create ();
9723   if (g == NULL) {
9724     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9725     return 0;
9726   }
9727   guestfs_set_error_handler (g, NULL, NULL);
9728   return (jlong) (long) g;
9729 }
9730
9731 JNIEXPORT void JNICALL
9732 Java_com_redhat_et_libguestfs_GuestFS__1close
9733   (JNIEnv *env, jobject obj, jlong jg)
9734 {
9735   guestfs_h *g = (guestfs_h *) (long) jg;
9736   guestfs_close (g);
9737 }
9738
9739 ";
9740
9741   List.iter (
9742     fun (name, style, _, _, _, _, _) ->
9743       pr "JNIEXPORT ";
9744       (match fst style with
9745        | RErr -> pr "void ";
9746        | RInt _ -> pr "jint ";
9747        | RInt64 _ -> pr "jlong ";
9748        | RBool _ -> pr "jboolean ";
9749        | RConstString _ | RConstOptString _ | RString _
9750        | RBufferOut _ -> pr "jstring ";
9751        | RStruct _ | RHashtable _ ->
9752            pr "jobject ";
9753        | RStringList _ | RStructList _ ->
9754            pr "jobjectArray ";
9755       );
9756       pr "JNICALL\n";
9757       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9758       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9759       pr "\n";
9760       pr "  (JNIEnv *env, jobject obj, jlong jg";
9761       List.iter (
9762         function
9763         | Pathname n
9764         | Device n | Dev_or_Path n
9765         | String n
9766         | OptString n
9767         | FileIn n
9768         | FileOut n ->
9769             pr ", jstring j%s" n
9770         | StringList n | DeviceList n ->
9771             pr ", jobjectArray j%s" n
9772         | Bool n ->
9773             pr ", jboolean j%s" n
9774         | Int n ->
9775             pr ", jint j%s" n
9776         | Int64 n ->
9777             pr ", jlong j%s" n
9778       ) (snd style);
9779       pr ")\n";
9780       pr "{\n";
9781       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9782       let error_code, no_ret =
9783         match fst style with
9784         | RErr -> pr "  int r;\n"; "-1", ""
9785         | RBool _
9786         | RInt _ -> pr "  int r;\n"; "-1", "0"
9787         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9788         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9789         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9790         | RString _ ->
9791             pr "  jstring jr;\n";
9792             pr "  char *r;\n"; "NULL", "NULL"
9793         | RStringList _ ->
9794             pr "  jobjectArray jr;\n";
9795             pr "  int r_len;\n";
9796             pr "  jclass cl;\n";
9797             pr "  jstring jstr;\n";
9798             pr "  char **r;\n"; "NULL", "NULL"
9799         | RStruct (_, typ) ->
9800             pr "  jobject jr;\n";
9801             pr "  jclass cl;\n";
9802             pr "  jfieldID fl;\n";
9803             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9804         | RStructList (_, typ) ->
9805             pr "  jobjectArray jr;\n";
9806             pr "  jclass cl;\n";
9807             pr "  jfieldID fl;\n";
9808             pr "  jobject jfl;\n";
9809             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9810         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9811         | RBufferOut _ ->
9812             pr "  jstring jr;\n";
9813             pr "  char *r;\n";
9814             pr "  size_t size;\n";
9815             "NULL", "NULL" in
9816       List.iter (
9817         function
9818         | Pathname n
9819         | Device n | Dev_or_Path n
9820         | String n
9821         | OptString n
9822         | FileIn n
9823         | FileOut n ->
9824             pr "  const char *%s;\n" n
9825         | StringList n | DeviceList n ->
9826             pr "  int %s_len;\n" n;
9827             pr "  const char **%s;\n" n
9828         | Bool n
9829         | Int n ->
9830             pr "  int %s;\n" n
9831         | Int64 n ->
9832             pr "  int64_t %s;\n" n
9833       ) (snd style);
9834
9835       let needs_i =
9836         (match fst style with
9837          | RStringList _ | RStructList _ -> true
9838          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9839          | RConstOptString _
9840          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9841           List.exists (function
9842                        | StringList _ -> true
9843                        | DeviceList _ -> true
9844                        | _ -> false) (snd style) in
9845       if needs_i then
9846         pr "  int i;\n";
9847
9848       pr "\n";
9849
9850       (* Get the parameters. *)
9851       List.iter (
9852         function
9853         | Pathname n
9854         | Device n | Dev_or_Path n
9855         | String n
9856         | FileIn n
9857         | FileOut n ->
9858             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9859         | OptString n ->
9860             (* This is completely undocumented, but Java null becomes
9861              * a NULL parameter.
9862              *)
9863             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9864         | StringList n | DeviceList n ->
9865             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9866             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9867             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9868             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9869               n;
9870             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9871             pr "  }\n";
9872             pr "  %s[%s_len] = NULL;\n" n n;
9873         | Bool n
9874         | Int n
9875         | Int64 n ->
9876             pr "  %s = j%s;\n" n n
9877       ) (snd style);
9878
9879       (* Make the call. *)
9880       pr "  r = guestfs_%s " name;
9881       generate_c_call_args ~handle:"g" style;
9882       pr ";\n";
9883
9884       (* Release the parameters. *)
9885       List.iter (
9886         function
9887         | Pathname n
9888         | Device n | Dev_or_Path n
9889         | String n
9890         | FileIn n
9891         | FileOut n ->
9892             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9893         | OptString n ->
9894             pr "  if (j%s)\n" n;
9895             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9896         | StringList n | DeviceList n ->
9897             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9898             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9899               n;
9900             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9901             pr "  }\n";
9902             pr "  free (%s);\n" n
9903         | Bool n
9904         | Int n
9905         | Int64 n -> ()
9906       ) (snd style);
9907
9908       (* Check for errors. *)
9909       pr "  if (r == %s) {\n" error_code;
9910       pr "    throw_exception (env, guestfs_last_error (g));\n";
9911       pr "    return %s;\n" no_ret;
9912       pr "  }\n";
9913
9914       (* Return value. *)
9915       (match fst style with
9916        | RErr -> ()
9917        | RInt _ -> pr "  return (jint) r;\n"
9918        | RBool _ -> pr "  return (jboolean) r;\n"
9919        | RInt64 _ -> pr "  return (jlong) r;\n"
9920        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9921        | RConstOptString _ ->
9922            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9923        | RString _ ->
9924            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9925            pr "  free (r);\n";
9926            pr "  return jr;\n"
9927        | RStringList _ ->
9928            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9929            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9930            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9931            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9932            pr "  for (i = 0; i < r_len; ++i) {\n";
9933            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9934            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9935            pr "    free (r[i]);\n";
9936            pr "  }\n";
9937            pr "  free (r);\n";
9938            pr "  return jr;\n"
9939        | RStruct (_, typ) ->
9940            let jtyp = java_name_of_struct typ in
9941            let cols = cols_of_struct typ in
9942            generate_java_struct_return typ jtyp cols
9943        | RStructList (_, typ) ->
9944            let jtyp = java_name_of_struct typ in
9945            let cols = cols_of_struct typ in
9946            generate_java_struct_list_return typ jtyp cols
9947        | RHashtable _ ->
9948            (* XXX *)
9949            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9950            pr "  return NULL;\n"
9951        | RBufferOut _ ->
9952            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9953            pr "  free (r);\n";
9954            pr "  return jr;\n"
9955       );
9956
9957       pr "}\n";
9958       pr "\n"
9959   ) all_functions
9960
9961 and generate_java_struct_return typ jtyp cols =
9962   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9963   pr "  jr = (*env)->AllocObject (env, cl);\n";
9964   List.iter (
9965     function
9966     | name, FString ->
9967         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9968         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9969     | name, FUUID ->
9970         pr "  {\n";
9971         pr "    char s[33];\n";
9972         pr "    memcpy (s, r->%s, 32);\n" name;
9973         pr "    s[32] = 0;\n";
9974         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9975         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9976         pr "  }\n";
9977     | name, FBuffer ->
9978         pr "  {\n";
9979         pr "    int len = r->%s_len;\n" name;
9980         pr "    char s[len+1];\n";
9981         pr "    memcpy (s, r->%s, len);\n" name;
9982         pr "    s[len] = 0;\n";
9983         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9984         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9985         pr "  }\n";
9986     | name, (FBytes|FUInt64|FInt64) ->
9987         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9988         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9989     | name, (FUInt32|FInt32) ->
9990         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9991         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9992     | name, FOptPercent ->
9993         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9994         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9995     | name, FChar ->
9996         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9997         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9998   ) cols;
9999   pr "  free (r);\n";
10000   pr "  return jr;\n"
10001
10002 and generate_java_struct_list_return typ jtyp cols =
10003   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10004   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10005   pr "  for (i = 0; i < r->len; ++i) {\n";
10006   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10007   List.iter (
10008     function
10009     | name, FString ->
10010         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10011         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10012     | name, FUUID ->
10013         pr "    {\n";
10014         pr "      char s[33];\n";
10015         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10016         pr "      s[32] = 0;\n";
10017         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10018         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10019         pr "    }\n";
10020     | name, FBuffer ->
10021         pr "    {\n";
10022         pr "      int len = r->val[i].%s_len;\n" name;
10023         pr "      char s[len+1];\n";
10024         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10025         pr "      s[len] = 0;\n";
10026         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10027         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10028         pr "    }\n";
10029     | name, (FBytes|FUInt64|FInt64) ->
10030         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10031         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10032     | name, (FUInt32|FInt32) ->
10033         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10034         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10035     | name, FOptPercent ->
10036         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10037         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10038     | name, FChar ->
10039         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10040         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10041   ) cols;
10042   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10043   pr "  }\n";
10044   pr "  guestfs_free_%s_list (r);\n" typ;
10045   pr "  return jr;\n"
10046
10047 and generate_java_makefile_inc () =
10048   generate_header HashStyle GPLv2plus;
10049
10050   pr "java_built_sources = \\\n";
10051   List.iter (
10052     fun (typ, jtyp) ->
10053         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10054   ) java_structs;
10055   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10056
10057 and generate_haskell_hs () =
10058   generate_header HaskellStyle LGPLv2plus;
10059
10060   (* XXX We only know how to generate partial FFI for Haskell
10061    * at the moment.  Please help out!
10062    *)
10063   let can_generate style =
10064     match style with
10065     | RErr, _
10066     | RInt _, _
10067     | RInt64 _, _ -> true
10068     | RBool _, _
10069     | RConstString _, _
10070     | RConstOptString _, _
10071     | RString _, _
10072     | RStringList _, _
10073     | RStruct _, _
10074     | RStructList _, _
10075     | RHashtable _, _
10076     | RBufferOut _, _ -> false in
10077
10078   pr "\
10079 {-# INCLUDE <guestfs.h> #-}
10080 {-# LANGUAGE ForeignFunctionInterface #-}
10081
10082 module Guestfs (
10083   create";
10084
10085   (* List out the names of the actions we want to export. *)
10086   List.iter (
10087     fun (name, style, _, _, _, _, _) ->
10088       if can_generate style then pr ",\n  %s" name
10089   ) all_functions;
10090
10091   pr "
10092   ) where
10093
10094 -- Unfortunately some symbols duplicate ones already present
10095 -- in Prelude.  We don't know which, so we hard-code a list
10096 -- here.
10097 import Prelude hiding (truncate)
10098
10099 import Foreign
10100 import Foreign.C
10101 import Foreign.C.Types
10102 import IO
10103 import Control.Exception
10104 import Data.Typeable
10105
10106 data GuestfsS = GuestfsS            -- represents the opaque C struct
10107 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10108 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10109
10110 -- XXX define properly later XXX
10111 data PV = PV
10112 data VG = VG
10113 data LV = LV
10114 data IntBool = IntBool
10115 data Stat = Stat
10116 data StatVFS = StatVFS
10117 data Hashtable = Hashtable
10118
10119 foreign import ccall unsafe \"guestfs_create\" c_create
10120   :: IO GuestfsP
10121 foreign import ccall unsafe \"&guestfs_close\" c_close
10122   :: FunPtr (GuestfsP -> IO ())
10123 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10124   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10125
10126 create :: IO GuestfsH
10127 create = do
10128   p <- c_create
10129   c_set_error_handler p nullPtr nullPtr
10130   h <- newForeignPtr c_close p
10131   return h
10132
10133 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10134   :: GuestfsP -> IO CString
10135
10136 -- last_error :: GuestfsH -> IO (Maybe String)
10137 -- last_error h = do
10138 --   str <- withForeignPtr h (\\p -> c_last_error p)
10139 --   maybePeek peekCString str
10140
10141 last_error :: GuestfsH -> IO (String)
10142 last_error h = do
10143   str <- withForeignPtr h (\\p -> c_last_error p)
10144   if (str == nullPtr)
10145     then return \"no error\"
10146     else peekCString str
10147
10148 ";
10149
10150   (* Generate wrappers for each foreign function. *)
10151   List.iter (
10152     fun (name, style, _, _, _, _, _) ->
10153       if can_generate style then (
10154         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10155         pr "  :: ";
10156         generate_haskell_prototype ~handle:"GuestfsP" style;
10157         pr "\n";
10158         pr "\n";
10159         pr "%s :: " name;
10160         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10161         pr "\n";
10162         pr "%s %s = do\n" name
10163           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10164         pr "  r <- ";
10165         (* Convert pointer arguments using with* functions. *)
10166         List.iter (
10167           function
10168           | FileIn n
10169           | FileOut n
10170           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10171           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10172           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10173           | Bool _ | Int _ | Int64 _ -> ()
10174         ) (snd style);
10175         (* Convert integer arguments. *)
10176         let args =
10177           List.map (
10178             function
10179             | Bool n -> sprintf "(fromBool %s)" n
10180             | Int n -> sprintf "(fromIntegral %s)" n
10181             | Int64 n -> sprintf "(fromIntegral %s)" n
10182             | FileIn n | FileOut n
10183             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10184           ) (snd style) in
10185         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10186           (String.concat " " ("p" :: args));
10187         (match fst style with
10188          | RErr | RInt _ | RInt64 _ | RBool _ ->
10189              pr "  if (r == -1)\n";
10190              pr "    then do\n";
10191              pr "      err <- last_error h\n";
10192              pr "      fail err\n";
10193          | RConstString _ | RConstOptString _ | RString _
10194          | RStringList _ | RStruct _
10195          | RStructList _ | RHashtable _ | RBufferOut _ ->
10196              pr "  if (r == nullPtr)\n";
10197              pr "    then do\n";
10198              pr "      err <- last_error h\n";
10199              pr "      fail err\n";
10200         );
10201         (match fst style with
10202          | RErr ->
10203              pr "    else return ()\n"
10204          | RInt _ ->
10205              pr "    else return (fromIntegral r)\n"
10206          | RInt64 _ ->
10207              pr "    else return (fromIntegral r)\n"
10208          | RBool _ ->
10209              pr "    else return (toBool r)\n"
10210          | RConstString _
10211          | RConstOptString _
10212          | RString _
10213          | RStringList _
10214          | RStruct _
10215          | RStructList _
10216          | RHashtable _
10217          | RBufferOut _ ->
10218              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10219         );
10220         pr "\n";
10221       )
10222   ) all_functions
10223
10224 and generate_haskell_prototype ~handle ?(hs = false) style =
10225   pr "%s -> " handle;
10226   let string = if hs then "String" else "CString" in
10227   let int = if hs then "Int" else "CInt" in
10228   let bool = if hs then "Bool" else "CInt" in
10229   let int64 = if hs then "Integer" else "Int64" in
10230   List.iter (
10231     fun arg ->
10232       (match arg with
10233        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10234        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10235        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10236        | Bool _ -> pr "%s" bool
10237        | Int _ -> pr "%s" int
10238        | Int64 _ -> pr "%s" int
10239        | FileIn _ -> pr "%s" string
10240        | FileOut _ -> pr "%s" string
10241       );
10242       pr " -> ";
10243   ) (snd style);
10244   pr "IO (";
10245   (match fst style with
10246    | RErr -> if not hs then pr "CInt"
10247    | RInt _ -> pr "%s" int
10248    | RInt64 _ -> pr "%s" int64
10249    | RBool _ -> pr "%s" bool
10250    | RConstString _ -> pr "%s" string
10251    | RConstOptString _ -> pr "Maybe %s" string
10252    | RString _ -> pr "%s" string
10253    | RStringList _ -> pr "[%s]" string
10254    | RStruct (_, typ) ->
10255        let name = java_name_of_struct typ in
10256        pr "%s" name
10257    | RStructList (_, typ) ->
10258        let name = java_name_of_struct typ in
10259        pr "[%s]" name
10260    | RHashtable _ -> pr "Hashtable"
10261    | RBufferOut _ -> pr "%s" string
10262   );
10263   pr ")"
10264
10265 and generate_csharp () =
10266   generate_header CPlusPlusStyle LGPLv2plus;
10267
10268   (* XXX Make this configurable by the C# assembly users. *)
10269   let library = "libguestfs.so.0" in
10270
10271   pr "\
10272 // These C# bindings are highly experimental at present.
10273 //
10274 // Firstly they only work on Linux (ie. Mono).  In order to get them
10275 // to work on Windows (ie. .Net) you would need to port the library
10276 // itself to Windows first.
10277 //
10278 // The second issue is that some calls are known to be incorrect and
10279 // can cause Mono to segfault.  Particularly: calls which pass or
10280 // return string[], or return any structure value.  This is because
10281 // we haven't worked out the correct way to do this from C#.
10282 //
10283 // The third issue is that when compiling you get a lot of warnings.
10284 // We are not sure whether the warnings are important or not.
10285 //
10286 // Fourthly we do not routinely build or test these bindings as part
10287 // of the make && make check cycle, which means that regressions might
10288 // go unnoticed.
10289 //
10290 // Suggestions and patches are welcome.
10291
10292 // To compile:
10293 //
10294 // gmcs Libguestfs.cs
10295 // mono Libguestfs.exe
10296 //
10297 // (You'll probably want to add a Test class / static main function
10298 // otherwise this won't do anything useful).
10299
10300 using System;
10301 using System.IO;
10302 using System.Runtime.InteropServices;
10303 using System.Runtime.Serialization;
10304 using System.Collections;
10305
10306 namespace Guestfs
10307 {
10308   class Error : System.ApplicationException
10309   {
10310     public Error (string message) : base (message) {}
10311     protected Error (SerializationInfo info, StreamingContext context) {}
10312   }
10313
10314   class Guestfs
10315   {
10316     IntPtr _handle;
10317
10318     [DllImport (\"%s\")]
10319     static extern IntPtr guestfs_create ();
10320
10321     public Guestfs ()
10322     {
10323       _handle = guestfs_create ();
10324       if (_handle == IntPtr.Zero)
10325         throw new Error (\"could not create guestfs handle\");
10326     }
10327
10328     [DllImport (\"%s\")]
10329     static extern void guestfs_close (IntPtr h);
10330
10331     ~Guestfs ()
10332     {
10333       guestfs_close (_handle);
10334     }
10335
10336     [DllImport (\"%s\")]
10337     static extern string guestfs_last_error (IntPtr h);
10338
10339 " library library library;
10340
10341   (* Generate C# structure bindings.  We prefix struct names with
10342    * underscore because C# cannot have conflicting struct names and
10343    * method names (eg. "class stat" and "stat").
10344    *)
10345   List.iter (
10346     fun (typ, cols) ->
10347       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10348       pr "    public class _%s {\n" typ;
10349       List.iter (
10350         function
10351         | name, FChar -> pr "      char %s;\n" name
10352         | name, FString -> pr "      string %s;\n" name
10353         | name, FBuffer ->
10354             pr "      uint %s_len;\n" name;
10355             pr "      string %s;\n" name
10356         | name, FUUID ->
10357             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10358             pr "      string %s;\n" name
10359         | name, FUInt32 -> pr "      uint %s;\n" name
10360         | name, FInt32 -> pr "      int %s;\n" name
10361         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10362         | name, FInt64 -> pr "      long %s;\n" name
10363         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10364       ) cols;
10365       pr "    }\n";
10366       pr "\n"
10367   ) structs;
10368
10369   (* Generate C# function bindings. *)
10370   List.iter (
10371     fun (name, style, _, _, _, shortdesc, _) ->
10372       let rec csharp_return_type () =
10373         match fst style with
10374         | RErr -> "void"
10375         | RBool n -> "bool"
10376         | RInt n -> "int"
10377         | RInt64 n -> "long"
10378         | RConstString n
10379         | RConstOptString n
10380         | RString n
10381         | RBufferOut n -> "string"
10382         | RStruct (_,n) -> "_" ^ n
10383         | RHashtable n -> "Hashtable"
10384         | RStringList n -> "string[]"
10385         | RStructList (_,n) -> sprintf "_%s[]" n
10386
10387       and c_return_type () =
10388         match fst style with
10389         | RErr
10390         | RBool _
10391         | RInt _ -> "int"
10392         | RInt64 _ -> "long"
10393         | RConstString _
10394         | RConstOptString _
10395         | RString _
10396         | RBufferOut _ -> "string"
10397         | RStruct (_,n) -> "_" ^ n
10398         | RHashtable _
10399         | RStringList _ -> "string[]"
10400         | RStructList (_,n) -> sprintf "_%s[]" n
10401
10402       and c_error_comparison () =
10403         match fst style with
10404         | RErr
10405         | RBool _
10406         | RInt _
10407         | RInt64 _ -> "== -1"
10408         | RConstString _
10409         | RConstOptString _
10410         | RString _
10411         | RBufferOut _
10412         | RStruct (_,_)
10413         | RHashtable _
10414         | RStringList _
10415         | RStructList (_,_) -> "== null"
10416
10417       and generate_extern_prototype () =
10418         pr "    static extern %s guestfs_%s (IntPtr h"
10419           (c_return_type ()) name;
10420         List.iter (
10421           function
10422           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10423           | FileIn n | FileOut n ->
10424               pr ", [In] string %s" n
10425           | StringList n | DeviceList n ->
10426               pr ", [In] string[] %s" n
10427           | Bool n ->
10428               pr ", bool %s" n
10429           | Int n ->
10430               pr ", int %s" n
10431           | Int64 n ->
10432               pr ", long %s" n
10433         ) (snd style);
10434         pr ");\n"
10435
10436       and generate_public_prototype () =
10437         pr "    public %s %s (" (csharp_return_type ()) name;
10438         let comma = ref false in
10439         let next () =
10440           if !comma then pr ", ";
10441           comma := true
10442         in
10443         List.iter (
10444           function
10445           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10446           | FileIn n | FileOut n ->
10447               next (); pr "string %s" n
10448           | StringList n | DeviceList n ->
10449               next (); pr "string[] %s" n
10450           | Bool n ->
10451               next (); pr "bool %s" n
10452           | Int n ->
10453               next (); pr "int %s" n
10454           | Int64 n ->
10455               next (); pr "long %s" n
10456         ) (snd style);
10457         pr ")\n"
10458
10459       and generate_call () =
10460         pr "guestfs_%s (_handle" name;
10461         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10462         pr ");\n";
10463       in
10464
10465       pr "    [DllImport (\"%s\")]\n" library;
10466       generate_extern_prototype ();
10467       pr "\n";
10468       pr "    /// <summary>\n";
10469       pr "    /// %s\n" shortdesc;
10470       pr "    /// </summary>\n";
10471       generate_public_prototype ();
10472       pr "    {\n";
10473       pr "      %s r;\n" (c_return_type ());
10474       pr "      r = ";
10475       generate_call ();
10476       pr "      if (r %s)\n" (c_error_comparison ());
10477       pr "        throw new Error (guestfs_last_error (_handle));\n";
10478       (match fst style with
10479        | RErr -> ()
10480        | RBool _ ->
10481            pr "      return r != 0 ? true : false;\n"
10482        | RHashtable _ ->
10483            pr "      Hashtable rr = new Hashtable ();\n";
10484            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10485            pr "        rr.Add (r[i], r[i+1]);\n";
10486            pr "      return rr;\n"
10487        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10488        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10489        | RStructList _ ->
10490            pr "      return r;\n"
10491       );
10492       pr "    }\n";
10493       pr "\n";
10494   ) all_functions_sorted;
10495
10496   pr "  }
10497 }
10498 "
10499
10500 and generate_bindtests () =
10501   generate_header CStyle LGPLv2plus;
10502
10503   pr "\
10504 #include <stdio.h>
10505 #include <stdlib.h>
10506 #include <inttypes.h>
10507 #include <string.h>
10508
10509 #include \"guestfs.h\"
10510 #include \"guestfs-internal.h\"
10511 #include \"guestfs-internal-actions.h\"
10512 #include \"guestfs_protocol.h\"
10513
10514 #define error guestfs_error
10515 #define safe_calloc guestfs_safe_calloc
10516 #define safe_malloc guestfs_safe_malloc
10517
10518 static void
10519 print_strings (char *const *argv)
10520 {
10521   int argc;
10522
10523   printf (\"[\");
10524   for (argc = 0; argv[argc] != NULL; ++argc) {
10525     if (argc > 0) printf (\", \");
10526     printf (\"\\\"%%s\\\"\", argv[argc]);
10527   }
10528   printf (\"]\\n\");
10529 }
10530
10531 /* The test0 function prints its parameters to stdout. */
10532 ";
10533
10534   let test0, tests =
10535     match test_functions with
10536     | [] -> assert false
10537     | test0 :: tests -> test0, tests in
10538
10539   let () =
10540     let (name, style, _, _, _, _, _) = test0 in
10541     generate_prototype ~extern:false ~semicolon:false ~newline:true
10542       ~handle:"g" ~prefix:"guestfs__" name style;
10543     pr "{\n";
10544     List.iter (
10545       function
10546       | Pathname n
10547       | Device n | Dev_or_Path n
10548       | String n
10549       | FileIn n
10550       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10551       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10552       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10553       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10554       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10555       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10556     ) (snd style);
10557     pr "  /* Java changes stdout line buffering so we need this: */\n";
10558     pr "  fflush (stdout);\n";
10559     pr "  return 0;\n";
10560     pr "}\n";
10561     pr "\n" in
10562
10563   List.iter (
10564     fun (name, style, _, _, _, _, _) ->
10565       if String.sub name (String.length name - 3) 3 <> "err" then (
10566         pr "/* Test normal return. */\n";
10567         generate_prototype ~extern:false ~semicolon:false ~newline:true
10568           ~handle:"g" ~prefix:"guestfs__" name style;
10569         pr "{\n";
10570         (match fst style with
10571          | RErr ->
10572              pr "  return 0;\n"
10573          | RInt _ ->
10574              pr "  int r;\n";
10575              pr "  sscanf (val, \"%%d\", &r);\n";
10576              pr "  return r;\n"
10577          | RInt64 _ ->
10578              pr "  int64_t r;\n";
10579              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10580              pr "  return r;\n"
10581          | RBool _ ->
10582              pr "  return STREQ (val, \"true\");\n"
10583          | RConstString _
10584          | RConstOptString _ ->
10585              (* Can't return the input string here.  Return a static
10586               * string so we ensure we get a segfault if the caller
10587               * tries to free it.
10588               *)
10589              pr "  return \"static string\";\n"
10590          | RString _ ->
10591              pr "  return strdup (val);\n"
10592          | RStringList _ ->
10593              pr "  char **strs;\n";
10594              pr "  int n, i;\n";
10595              pr "  sscanf (val, \"%%d\", &n);\n";
10596              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10597              pr "  for (i = 0; i < n; ++i) {\n";
10598              pr "    strs[i] = safe_malloc (g, 16);\n";
10599              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10600              pr "  }\n";
10601              pr "  strs[n] = NULL;\n";
10602              pr "  return strs;\n"
10603          | RStruct (_, typ) ->
10604              pr "  struct guestfs_%s *r;\n" typ;
10605              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10606              pr "  return r;\n"
10607          | RStructList (_, typ) ->
10608              pr "  struct guestfs_%s_list *r;\n" typ;
10609              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10610              pr "  sscanf (val, \"%%d\", &r->len);\n";
10611              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10612              pr "  return r;\n"
10613          | RHashtable _ ->
10614              pr "  char **strs;\n";
10615              pr "  int n, i;\n";
10616              pr "  sscanf (val, \"%%d\", &n);\n";
10617              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10618              pr "  for (i = 0; i < n; ++i) {\n";
10619              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10620              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10621              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10622              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10623              pr "  }\n";
10624              pr "  strs[n*2] = NULL;\n";
10625              pr "  return strs;\n"
10626          | RBufferOut _ ->
10627              pr "  return strdup (val);\n"
10628         );
10629         pr "}\n";
10630         pr "\n"
10631       ) else (
10632         pr "/* Test error return. */\n";
10633         generate_prototype ~extern:false ~semicolon:false ~newline:true
10634           ~handle:"g" ~prefix:"guestfs__" name style;
10635         pr "{\n";
10636         pr "  error (g, \"error\");\n";
10637         (match fst style with
10638          | RErr | RInt _ | RInt64 _ | RBool _ ->
10639              pr "  return -1;\n"
10640          | RConstString _ | RConstOptString _
10641          | RString _ | RStringList _ | RStruct _
10642          | RStructList _
10643          | RHashtable _
10644          | RBufferOut _ ->
10645              pr "  return NULL;\n"
10646         );
10647         pr "}\n";
10648         pr "\n"
10649       )
10650   ) tests
10651
10652 and generate_ocaml_bindtests () =
10653   generate_header OCamlStyle GPLv2plus;
10654
10655   pr "\
10656 let () =
10657   let g = Guestfs.create () in
10658 ";
10659
10660   let mkargs args =
10661     String.concat " " (
10662       List.map (
10663         function
10664         | CallString s -> "\"" ^ s ^ "\""
10665         | CallOptString None -> "None"
10666         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10667         | CallStringList xs ->
10668             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10669         | CallInt i when i >= 0 -> string_of_int i
10670         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10671         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10672         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10673         | CallBool b -> string_of_bool b
10674       ) args
10675     )
10676   in
10677
10678   generate_lang_bindtests (
10679     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10680   );
10681
10682   pr "print_endline \"EOF\"\n"
10683
10684 and generate_perl_bindtests () =
10685   pr "#!/usr/bin/perl -w\n";
10686   generate_header HashStyle GPLv2plus;
10687
10688   pr "\
10689 use strict;
10690
10691 use Sys::Guestfs;
10692
10693 my $g = Sys::Guestfs->new ();
10694 ";
10695
10696   let mkargs args =
10697     String.concat ", " (
10698       List.map (
10699         function
10700         | CallString s -> "\"" ^ s ^ "\""
10701         | CallOptString None -> "undef"
10702         | CallOptString (Some s) -> sprintf "\"%s\"" s
10703         | CallStringList xs ->
10704             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10705         | CallInt i -> string_of_int i
10706         | CallInt64 i -> Int64.to_string i
10707         | CallBool b -> if b then "1" else "0"
10708       ) args
10709     )
10710   in
10711
10712   generate_lang_bindtests (
10713     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10714   );
10715
10716   pr "print \"EOF\\n\"\n"
10717
10718 and generate_python_bindtests () =
10719   generate_header HashStyle GPLv2plus;
10720
10721   pr "\
10722 import guestfs
10723
10724 g = guestfs.GuestFS ()
10725 ";
10726
10727   let mkargs args =
10728     String.concat ", " (
10729       List.map (
10730         function
10731         | CallString s -> "\"" ^ s ^ "\""
10732         | CallOptString None -> "None"
10733         | CallOptString (Some s) -> sprintf "\"%s\"" s
10734         | CallStringList xs ->
10735             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10736         | CallInt i -> string_of_int i
10737         | CallInt64 i -> Int64.to_string i
10738         | CallBool b -> if b then "1" else "0"
10739       ) args
10740     )
10741   in
10742
10743   generate_lang_bindtests (
10744     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10745   );
10746
10747   pr "print \"EOF\"\n"
10748
10749 and generate_ruby_bindtests () =
10750   generate_header HashStyle GPLv2plus;
10751
10752   pr "\
10753 require 'guestfs'
10754
10755 g = Guestfs::create()
10756 ";
10757
10758   let mkargs args =
10759     String.concat ", " (
10760       List.map (
10761         function
10762         | CallString s -> "\"" ^ s ^ "\""
10763         | CallOptString None -> "nil"
10764         | CallOptString (Some s) -> sprintf "\"%s\"" s
10765         | CallStringList xs ->
10766             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10767         | CallInt i -> string_of_int i
10768         | CallInt64 i -> Int64.to_string i
10769         | CallBool b -> string_of_bool b
10770       ) args
10771     )
10772   in
10773
10774   generate_lang_bindtests (
10775     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10776   );
10777
10778   pr "print \"EOF\\n\"\n"
10779
10780 and generate_java_bindtests () =
10781   generate_header CStyle GPLv2plus;
10782
10783   pr "\
10784 import com.redhat.et.libguestfs.*;
10785
10786 public class Bindtests {
10787     public static void main (String[] argv)
10788     {
10789         try {
10790             GuestFS g = new GuestFS ();
10791 ";
10792
10793   let mkargs args =
10794     String.concat ", " (
10795       List.map (
10796         function
10797         | CallString s -> "\"" ^ s ^ "\""
10798         | CallOptString None -> "null"
10799         | CallOptString (Some s) -> sprintf "\"%s\"" s
10800         | CallStringList xs ->
10801             "new String[]{" ^
10802               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10803         | CallInt i -> string_of_int i
10804         | CallInt64 i -> Int64.to_string i
10805         | CallBool b -> string_of_bool b
10806       ) args
10807     )
10808   in
10809
10810   generate_lang_bindtests (
10811     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10812   );
10813
10814   pr "
10815             System.out.println (\"EOF\");
10816         }
10817         catch (Exception exn) {
10818             System.err.println (exn);
10819             System.exit (1);
10820         }
10821     }
10822 }
10823 "
10824
10825 and generate_haskell_bindtests () =
10826   generate_header HaskellStyle GPLv2plus;
10827
10828   pr "\
10829 module Bindtests where
10830 import qualified Guestfs
10831
10832 main = do
10833   g <- Guestfs.create
10834 ";
10835
10836   let mkargs args =
10837     String.concat " " (
10838       List.map (
10839         function
10840         | CallString s -> "\"" ^ s ^ "\""
10841         | CallOptString None -> "Nothing"
10842         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10843         | CallStringList xs ->
10844             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10845         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10846         | CallInt i -> string_of_int i
10847         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10848         | CallInt64 i -> Int64.to_string i
10849         | CallBool true -> "True"
10850         | CallBool false -> "False"
10851       ) args
10852     )
10853   in
10854
10855   generate_lang_bindtests (
10856     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10857   );
10858
10859   pr "  putStrLn \"EOF\"\n"
10860
10861 (* Language-independent bindings tests - we do it this way to
10862  * ensure there is parity in testing bindings across all languages.
10863  *)
10864 and generate_lang_bindtests call =
10865   call "test0" [CallString "abc"; CallOptString (Some "def");
10866                 CallStringList []; CallBool false;
10867                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10868   call "test0" [CallString "abc"; CallOptString None;
10869                 CallStringList []; CallBool false;
10870                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10871   call "test0" [CallString ""; CallOptString (Some "def");
10872                 CallStringList []; CallBool false;
10873                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10874   call "test0" [CallString ""; CallOptString (Some "");
10875                 CallStringList []; CallBool false;
10876                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10877   call "test0" [CallString "abc"; CallOptString (Some "def");
10878                 CallStringList ["1"]; CallBool false;
10879                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10880   call "test0" [CallString "abc"; CallOptString (Some "def");
10881                 CallStringList ["1"; "2"]; CallBool false;
10882                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10883   call "test0" [CallString "abc"; CallOptString (Some "def");
10884                 CallStringList ["1"]; CallBool true;
10885                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10886   call "test0" [CallString "abc"; CallOptString (Some "def");
10887                 CallStringList ["1"]; CallBool false;
10888                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10889   call "test0" [CallString "abc"; CallOptString (Some "def");
10890                 CallStringList ["1"]; CallBool false;
10891                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10892   call "test0" [CallString "abc"; CallOptString (Some "def");
10893                 CallStringList ["1"]; CallBool false;
10894                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10895   call "test0" [CallString "abc"; CallOptString (Some "def");
10896                 CallStringList ["1"]; CallBool false;
10897                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10898   call "test0" [CallString "abc"; CallOptString (Some "def");
10899                 CallStringList ["1"]; CallBool false;
10900                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10901   call "test0" [CallString "abc"; CallOptString (Some "def");
10902                 CallStringList ["1"]; CallBool false;
10903                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10904
10905 (* XXX Add here tests of the return and error functions. *)
10906
10907 (* Code to generator bindings for virt-inspector.  Currently only
10908  * implemented for OCaml code (for virt-p2v 2.0).
10909  *)
10910 let rng_input = "inspector/virt-inspector.rng"
10911
10912 (* Read the input file and parse it into internal structures.  This is
10913  * by no means a complete RELAX NG parser, but is just enough to be
10914  * able to parse the specific input file.
10915  *)
10916 type rng =
10917   | Element of string * rng list        (* <element name=name/> *)
10918   | Attribute of string * rng list        (* <attribute name=name/> *)
10919   | Interleave of rng list                (* <interleave/> *)
10920   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10921   | OneOrMore of rng                        (* <oneOrMore/> *)
10922   | Optional of rng                        (* <optional/> *)
10923   | Choice of string list                (* <choice><value/>*</choice> *)
10924   | Value of string                        (* <value>str</value> *)
10925   | Text                                (* <text/> *)
10926
10927 let rec string_of_rng = function
10928   | Element (name, xs) ->
10929       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10930   | Attribute (name, xs) ->
10931       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10932   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10933   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10934   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10935   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10936   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10937   | Value value -> "Value \"" ^ value ^ "\""
10938   | Text -> "Text"
10939
10940 and string_of_rng_list xs =
10941   String.concat ", " (List.map string_of_rng xs)
10942
10943 let rec parse_rng ?defines context = function
10944   | [] -> []
10945   | Xml.Element ("element", ["name", name], children) :: rest ->
10946       Element (name, parse_rng ?defines context children)
10947       :: parse_rng ?defines context rest
10948   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10949       Attribute (name, parse_rng ?defines context children)
10950       :: parse_rng ?defines context rest
10951   | Xml.Element ("interleave", [], children) :: rest ->
10952       Interleave (parse_rng ?defines context children)
10953       :: parse_rng ?defines context rest
10954   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10955       let rng = parse_rng ?defines context [child] in
10956       (match rng with
10957        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10958        | _ ->
10959            failwithf "%s: <zeroOrMore> contains more than one child element"
10960              context
10961       )
10962   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10963       let rng = parse_rng ?defines context [child] in
10964       (match rng with
10965        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10966        | _ ->
10967            failwithf "%s: <oneOrMore> contains more than one child element"
10968              context
10969       )
10970   | Xml.Element ("optional", [], [child]) :: rest ->
10971       let rng = parse_rng ?defines context [child] in
10972       (match rng with
10973        | [child] -> Optional child :: parse_rng ?defines context rest
10974        | _ ->
10975            failwithf "%s: <optional> contains more than one child element"
10976              context
10977       )
10978   | Xml.Element ("choice", [], children) :: rest ->
10979       let values = List.map (
10980         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10981         | _ ->
10982             failwithf "%s: can't handle anything except <value> in <choice>"
10983               context
10984       ) children in
10985       Choice values
10986       :: parse_rng ?defines context rest
10987   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10988       Value value :: parse_rng ?defines context rest
10989   | Xml.Element ("text", [], []) :: rest ->
10990       Text :: parse_rng ?defines context rest
10991   | Xml.Element ("ref", ["name", name], []) :: rest ->
10992       (* Look up the reference.  Because of limitations in this parser,
10993        * we can't handle arbitrarily nested <ref> yet.  You can only
10994        * use <ref> from inside <start>.
10995        *)
10996       (match defines with
10997        | None ->
10998            failwithf "%s: contains <ref>, but no refs are defined yet" context
10999        | Some map ->
11000            let rng = StringMap.find name map in
11001            rng @ parse_rng ?defines context rest
11002       )
11003   | x :: _ ->
11004       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11005
11006 let grammar =
11007   let xml = Xml.parse_file rng_input in
11008   match xml with
11009   | Xml.Element ("grammar", _,
11010                  Xml.Element ("start", _, gram) :: defines) ->
11011       (* The <define/> elements are referenced in the <start> section,
11012        * so build a map of those first.
11013        *)
11014       let defines = List.fold_left (
11015         fun map ->
11016           function Xml.Element ("define", ["name", name], defn) ->
11017             StringMap.add name defn map
11018           | _ ->
11019               failwithf "%s: expected <define name=name/>" rng_input
11020       ) StringMap.empty defines in
11021       let defines = StringMap.mapi parse_rng defines in
11022
11023       (* Parse the <start> clause, passing the defines. *)
11024       parse_rng ~defines "<start>" gram
11025   | _ ->
11026       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11027         rng_input
11028
11029 let name_of_field = function
11030   | Element (name, _) | Attribute (name, _)
11031   | ZeroOrMore (Element (name, _))
11032   | OneOrMore (Element (name, _))
11033   | Optional (Element (name, _)) -> name
11034   | Optional (Attribute (name, _)) -> name
11035   | Text -> (* an unnamed field in an element *)
11036       "data"
11037   | rng ->
11038       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11039
11040 (* At the moment this function only generates OCaml types.  However we
11041  * should parameterize it later so it can generate types/structs in a
11042  * variety of languages.
11043  *)
11044 let generate_types xs =
11045   (* A simple type is one that can be printed out directly, eg.
11046    * "string option".  A complex type is one which has a name and has
11047    * to be defined via another toplevel definition, eg. a struct.
11048    *
11049    * generate_type generates code for either simple or complex types.
11050    * In the simple case, it returns the string ("string option").  In
11051    * the complex case, it returns the name ("mountpoint").  In the
11052    * complex case it has to print out the definition before returning,
11053    * so it should only be called when we are at the beginning of a
11054    * new line (BOL context).
11055    *)
11056   let rec generate_type = function
11057     | Text ->                                (* string *)
11058         "string", true
11059     | Choice values ->                        (* [`val1|`val2|...] *)
11060         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11061     | ZeroOrMore rng ->                        (* <rng> list *)
11062         let t, is_simple = generate_type rng in
11063         t ^ " list (* 0 or more *)", is_simple
11064     | OneOrMore rng ->                        (* <rng> list *)
11065         let t, is_simple = generate_type rng in
11066         t ^ " list (* 1 or more *)", is_simple
11067                                         (* virt-inspector hack: bool *)
11068     | Optional (Attribute (name, [Value "1"])) ->
11069         "bool", true
11070     | Optional rng ->                        (* <rng> list *)
11071         let t, is_simple = generate_type rng in
11072         t ^ " option", is_simple
11073                                         (* type name = { fields ... } *)
11074     | Element (name, fields) when is_attrs_interleave fields ->
11075         generate_type_struct name (get_attrs_interleave fields)
11076     | Element (name, [field])                (* type name = field *)
11077     | Attribute (name, [field]) ->
11078         let t, is_simple = generate_type field in
11079         if is_simple then (t, true)
11080         else (
11081           pr "type %s = %s\n" name t;
11082           name, false
11083         )
11084     | Element (name, fields) ->              (* type name = { fields ... } *)
11085         generate_type_struct name fields
11086     | rng ->
11087         failwithf "generate_type failed at: %s" (string_of_rng rng)
11088
11089   and is_attrs_interleave = function
11090     | [Interleave _] -> true
11091     | Attribute _ :: fields -> is_attrs_interleave fields
11092     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11093     | _ -> false
11094
11095   and get_attrs_interleave = function
11096     | [Interleave fields] -> fields
11097     | ((Attribute _) as field) :: fields
11098     | ((Optional (Attribute _)) as field) :: fields ->
11099         field :: get_attrs_interleave fields
11100     | _ -> assert false
11101
11102   and generate_types xs =
11103     List.iter (fun x -> ignore (generate_type x)) xs
11104
11105   and generate_type_struct name fields =
11106     (* Calculate the types of the fields first.  We have to do this
11107      * before printing anything so we are still in BOL context.
11108      *)
11109     let types = List.map fst (List.map generate_type fields) in
11110
11111     (* Special case of a struct containing just a string and another
11112      * field.  Turn it into an assoc list.
11113      *)
11114     match types with
11115     | ["string"; other] ->
11116         let fname1, fname2 =
11117           match fields with
11118           | [f1; f2] -> name_of_field f1, name_of_field f2
11119           | _ -> assert false in
11120         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11121         name, false
11122
11123     | types ->
11124         pr "type %s = {\n" name;
11125         List.iter (
11126           fun (field, ftype) ->
11127             let fname = name_of_field field in
11128             pr "  %s_%s : %s;\n" name fname ftype
11129         ) (List.combine fields types);
11130         pr "}\n";
11131         (* Return the name of this type, and
11132          * false because it's not a simple type.
11133          *)
11134         name, false
11135   in
11136
11137   generate_types xs
11138
11139 let generate_parsers xs =
11140   (* As for generate_type above, generate_parser makes a parser for
11141    * some type, and returns the name of the parser it has generated.
11142    * Because it (may) need to print something, it should always be
11143    * called in BOL context.
11144    *)
11145   let rec generate_parser = function
11146     | Text ->                                (* string *)
11147         "string_child_or_empty"
11148     | Choice values ->                        (* [`val1|`val2|...] *)
11149         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11150           (String.concat "|"
11151              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11152     | ZeroOrMore rng ->                        (* <rng> list *)
11153         let pa = generate_parser rng in
11154         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11155     | OneOrMore rng ->                        (* <rng> list *)
11156         let pa = generate_parser rng in
11157         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11158                                         (* virt-inspector hack: bool *)
11159     | Optional (Attribute (name, [Value "1"])) ->
11160         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11161     | Optional rng ->                        (* <rng> list *)
11162         let pa = generate_parser rng in
11163         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11164                                         (* type name = { fields ... } *)
11165     | Element (name, fields) when is_attrs_interleave fields ->
11166         generate_parser_struct name (get_attrs_interleave fields)
11167     | Element (name, [field]) ->        (* type name = field *)
11168         let pa = generate_parser field in
11169         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11170         pr "let %s =\n" parser_name;
11171         pr "  %s\n" pa;
11172         pr "let parse_%s = %s\n" name parser_name;
11173         parser_name
11174     | Attribute (name, [field]) ->
11175         let pa = generate_parser field in
11176         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11177         pr "let %s =\n" parser_name;
11178         pr "  %s\n" pa;
11179         pr "let parse_%s = %s\n" name parser_name;
11180         parser_name
11181     | Element (name, fields) ->              (* type name = { fields ... } *)
11182         generate_parser_struct name ([], fields)
11183     | rng ->
11184         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11185
11186   and is_attrs_interleave = function
11187     | [Interleave _] -> true
11188     | Attribute _ :: fields -> is_attrs_interleave fields
11189     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11190     | _ -> false
11191
11192   and get_attrs_interleave = function
11193     | [Interleave fields] -> [], fields
11194     | ((Attribute _) as field) :: fields
11195     | ((Optional (Attribute _)) as field) :: fields ->
11196         let attrs, interleaves = get_attrs_interleave fields in
11197         (field :: attrs), interleaves
11198     | _ -> assert false
11199
11200   and generate_parsers xs =
11201     List.iter (fun x -> ignore (generate_parser x)) xs
11202
11203   and generate_parser_struct name (attrs, interleaves) =
11204     (* Generate parsers for the fields first.  We have to do this
11205      * before printing anything so we are still in BOL context.
11206      *)
11207     let fields = attrs @ interleaves in
11208     let pas = List.map generate_parser fields in
11209
11210     (* Generate an intermediate tuple from all the fields first.
11211      * If the type is just a string + another field, then we will
11212      * return this directly, otherwise it is turned into a record.
11213      *
11214      * RELAX NG note: This code treats <interleave> and plain lists of
11215      * fields the same.  In other words, it doesn't bother enforcing
11216      * any ordering of fields in the XML.
11217      *)
11218     pr "let parse_%s x =\n" name;
11219     pr "  let t = (\n    ";
11220     let comma = ref false in
11221     List.iter (
11222       fun x ->
11223         if !comma then pr ",\n    ";
11224         comma := true;
11225         match x with
11226         | Optional (Attribute (fname, [field])), pa ->
11227             pr "%s x" pa
11228         | Optional (Element (fname, [field])), pa ->
11229             pr "%s (optional_child %S x)" pa fname
11230         | Attribute (fname, [Text]), _ ->
11231             pr "attribute %S x" fname
11232         | (ZeroOrMore _ | OneOrMore _), pa ->
11233             pr "%s x" pa
11234         | Text, pa ->
11235             pr "%s x" pa
11236         | (field, pa) ->
11237             let fname = name_of_field field in
11238             pr "%s (child %S x)" pa fname
11239     ) (List.combine fields pas);
11240     pr "\n  ) in\n";
11241
11242     (match fields with
11243      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11244          pr "  t\n"
11245
11246      | _ ->
11247          pr "  (Obj.magic t : %s)\n" name
11248 (*
11249          List.iter (
11250            function
11251            | (Optional (Attribute (fname, [field])), pa) ->
11252                pr "  %s_%s =\n" name fname;
11253                pr "    %s x;\n" pa
11254            | (Optional (Element (fname, [field])), pa) ->
11255                pr "  %s_%s =\n" name fname;
11256                pr "    (let x = optional_child %S x in\n" fname;
11257                pr "     %s x);\n" pa
11258            | (field, pa) ->
11259                let fname = name_of_field field in
11260                pr "  %s_%s =\n" name fname;
11261                pr "    (let x = child %S x in\n" fname;
11262                pr "     %s x);\n" pa
11263          ) (List.combine fields pas);
11264          pr "}\n"
11265 *)
11266     );
11267     sprintf "parse_%s" name
11268   in
11269
11270   generate_parsers xs
11271
11272 (* Generate ocaml/guestfs_inspector.mli. *)
11273 let generate_ocaml_inspector_mli () =
11274   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11275
11276   pr "\
11277 (** This is an OCaml language binding to the external [virt-inspector]
11278     program.
11279
11280     For more information, please read the man page [virt-inspector(1)].
11281 *)
11282
11283 ";
11284
11285   generate_types grammar;
11286   pr "(** The nested information returned from the {!inspect} function. *)\n";
11287   pr "\n";
11288
11289   pr "\
11290 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11291 (** To inspect a libvirt domain called [name], pass a singleton
11292     list: [inspect [name]].  When using libvirt only, you may
11293     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11294
11295     To inspect a disk image or images, pass a list of the filenames
11296     of the disk images: [inspect filenames]
11297
11298     This function inspects the given guest or disk images and
11299     returns a list of operating system(s) found and a large amount
11300     of information about them.  In the vast majority of cases,
11301     a virtual machine only contains a single operating system.
11302
11303     If the optional [~xml] parameter is given, then this function
11304     skips running the external virt-inspector program and just
11305     parses the given XML directly (which is expected to be XML
11306     produced from a previous run of virt-inspector).  The list of
11307     names and connect URI are ignored in this case.
11308
11309     This function can throw a wide variety of exceptions, for example
11310     if the external virt-inspector program cannot be found, or if
11311     it doesn't generate valid XML.
11312 *)
11313 "
11314
11315 (* Generate ocaml/guestfs_inspector.ml. *)
11316 let generate_ocaml_inspector_ml () =
11317   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11318
11319   pr "open Unix\n";
11320   pr "\n";
11321
11322   generate_types grammar;
11323   pr "\n";
11324
11325   pr "\
11326 (* Misc functions which are used by the parser code below. *)
11327 let first_child = function
11328   | Xml.Element (_, _, c::_) -> c
11329   | Xml.Element (name, _, []) ->
11330       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11331   | Xml.PCData str ->
11332       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11333
11334 let string_child_or_empty = function
11335   | Xml.Element (_, _, [Xml.PCData s]) -> s
11336   | Xml.Element (_, _, []) -> \"\"
11337   | Xml.Element (x, _, _) ->
11338       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11339                 x ^ \" instead\")
11340   | Xml.PCData str ->
11341       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11342
11343 let optional_child name xml =
11344   let children = Xml.children xml in
11345   try
11346     Some (List.find (function
11347                      | Xml.Element (n, _, _) when n = name -> true
11348                      | _ -> false) children)
11349   with
11350     Not_found -> None
11351
11352 let child name xml =
11353   match optional_child name xml with
11354   | Some c -> c
11355   | None ->
11356       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11357
11358 let attribute name xml =
11359   try Xml.attrib xml name
11360   with Xml.No_attribute _ ->
11361     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11362
11363 ";
11364
11365   generate_parsers grammar;
11366   pr "\n";
11367
11368   pr "\
11369 (* Run external virt-inspector, then use parser to parse the XML. *)
11370 let inspect ?connect ?xml names =
11371   let xml =
11372     match xml with
11373     | None ->
11374         if names = [] then invalid_arg \"inspect: no names given\";
11375         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11376           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11377           names in
11378         let cmd = List.map Filename.quote cmd in
11379         let cmd = String.concat \" \" cmd in
11380         let chan = open_process_in cmd in
11381         let xml = Xml.parse_in chan in
11382         (match close_process_in chan with
11383          | WEXITED 0 -> ()
11384          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11385          | WSIGNALED i | WSTOPPED i ->
11386              failwith (\"external virt-inspector command died or stopped on sig \" ^
11387                        string_of_int i)
11388         );
11389         xml
11390     | Some doc ->
11391         Xml.parse_string doc in
11392   parse_operatingsystems xml
11393 "
11394
11395 (* This is used to generate the src/MAX_PROC_NR file which
11396  * contains the maximum procedure number, a surrogate for the
11397  * ABI version number.  See src/Makefile.am for the details.
11398  *)
11399 and generate_max_proc_nr () =
11400   let proc_nrs = List.map (
11401     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11402   ) daemon_functions in
11403
11404   let max_proc_nr = List.fold_left max 0 proc_nrs in
11405
11406   pr "%d\n" max_proc_nr
11407
11408 let output_to filename k =
11409   let filename_new = filename ^ ".new" in
11410   chan := open_out filename_new;
11411   k ();
11412   close_out !chan;
11413   chan := Pervasives.stdout;
11414
11415   (* Is the new file different from the current file? *)
11416   if Sys.file_exists filename && files_equal filename filename_new then
11417     unlink filename_new                 (* same, so skip it *)
11418   else (
11419     (* different, overwrite old one *)
11420     (try chmod filename 0o644 with Unix_error _ -> ());
11421     rename filename_new filename;
11422     chmod filename 0o444;
11423     printf "written %s\n%!" filename;
11424   )
11425
11426 let perror msg = function
11427   | Unix_error (err, _, _) ->
11428       eprintf "%s: %s\n" msg (error_message err)
11429   | exn ->
11430       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11431
11432 (* Main program. *)
11433 let () =
11434   let lock_fd =
11435     try openfile "HACKING" [O_RDWR] 0
11436     with
11437     | Unix_error (ENOENT, _, _) ->
11438         eprintf "\
11439 You are probably running this from the wrong directory.
11440 Run it from the top source directory using the command
11441   src/generator.ml
11442 ";
11443         exit 1
11444     | exn ->
11445         perror "open: HACKING" exn;
11446         exit 1 in
11447
11448   (* Acquire a lock so parallel builds won't try to run the generator
11449    * twice at the same time.  Subsequent builds will wait for the first
11450    * one to finish.  Note the lock is released implicitly when the
11451    * program exits.
11452    *)
11453   (try lockf lock_fd F_LOCK 1
11454    with exn ->
11455      perror "lock: HACKING" exn;
11456      exit 1);
11457
11458   check_functions ();
11459
11460   output_to "src/guestfs_protocol.x" generate_xdr;
11461   output_to "src/guestfs-structs.h" generate_structs_h;
11462   output_to "src/guestfs-actions.h" generate_actions_h;
11463   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11464   output_to "src/guestfs-actions.c" generate_client_actions;
11465   output_to "src/guestfs-bindtests.c" generate_bindtests;
11466   output_to "src/guestfs-structs.pod" generate_structs_pod;
11467   output_to "src/guestfs-actions.pod" generate_actions_pod;
11468   output_to "src/guestfs-availability.pod" generate_availability_pod;
11469   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11470   output_to "src/libguestfs.syms" generate_linker_script;
11471   output_to "daemon/actions.h" generate_daemon_actions_h;
11472   output_to "daemon/stubs.c" generate_daemon_actions;
11473   output_to "daemon/names.c" generate_daemon_names;
11474   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11475   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11476   output_to "capitests/tests.c" generate_tests;
11477   output_to "fish/cmds.c" generate_fish_cmds;
11478   output_to "fish/completion.c" generate_fish_completion;
11479   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11480   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11481   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11482   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11483   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11484   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11485   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11486   output_to "perl/Guestfs.xs" generate_perl_xs;
11487   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11488   output_to "perl/bindtests.pl" generate_perl_bindtests;
11489   output_to "python/guestfs-py.c" generate_python_c;
11490   output_to "python/guestfs.py" generate_python_py;
11491   output_to "python/bindtests.py" generate_python_bindtests;
11492   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11493   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11494   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11495
11496   List.iter (
11497     fun (typ, jtyp) ->
11498       let cols = cols_of_struct typ in
11499       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11500       output_to filename (generate_java_struct jtyp cols);
11501   ) java_structs;
11502
11503   output_to "java/Makefile.inc" generate_java_makefile_inc;
11504   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11505   output_to "java/Bindtests.java" generate_java_bindtests;
11506   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11507   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11508   output_to "csharp/Libguestfs.cs" generate_csharp;
11509
11510   (* Always generate this file last, and unconditionally.  It's used
11511    * by the Makefile to know when we must re-run the generator.
11512    *)
11513   let chan = open_out "src/stamp-generator" in
11514   fprintf chan "1\n";
11515   close_out chan;
11516
11517   printf "generated %d lines of code\n" !lines