9d190977c6cd58f0cf8678bd1758d7c61843050b
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1384
1385   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM volume group",
1477    "\
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>
2029 or C<guestfs_txz_in>.");
2030
2031   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2032    [],
2033    "pack directory into tarfile",
2034    "\
2035 This command packs the contents of C<directory> and downloads
2036 it to local file C<tarfile>.
2037
2038 To download a compressed tarball, use C<guestfs_tgz_out>
2039 or C<guestfs_txz_out>.");
2040
2041   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042    [InitBasicFS, Always, TestOutput (
2043       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044        ["cat"; "/hello"]], "hello\n")],
2045    "unpack compressed tarball to directory",
2046    "\
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2049
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2051
2052   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2053    [],
2054    "pack directory into compressed tarball",
2055    "\
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2058
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2060
2061   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062    [InitBasicFS, Always, TestLastFail (
2063       [["umount"; "/"];
2064        ["mount_ro"; "/dev/sda1"; "/"];
2065        ["touch"; "/new"]]);
2066     InitBasicFS, Always, TestOutput (
2067       [["write_file"; "/new"; "data"; "0"];
2068        ["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["cat"; "/new"]], "data")],
2071    "mount a guest disk, read-only",
2072    "\
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2075
2076   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2077    [],
2078    "mount a guest disk with mount options",
2079    "\
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2083
2084   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2085    [],
2086    "mount a guest disk with mount options and vfstype",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2091
2092   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2093    [],
2094    "debugging and internals",
2095    "\
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2098 qemu subprocess.
2099
2100 There is no comprehensive help for this command.  You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2103
2104   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105    [InitEmpty, Always, TestOutputList (
2106       [["part_disk"; "/dev/sda"; "mbr"];
2107        ["pvcreate"; "/dev/sda1"];
2108        ["vgcreate"; "VG"; "/dev/sda1"];
2109        ["lvcreate"; "LV1"; "VG"; "50"];
2110        ["lvcreate"; "LV2"; "VG"; "50"];
2111        ["lvremove"; "/dev/VG/LV1"];
2112        ["lvs"]], ["/dev/VG/LV2"]);
2113     InitEmpty, Always, TestOutputList (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["lvremove"; "/dev/VG"];
2120        ["lvs"]], []);
2121     InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG"];
2128        ["vgs"]], ["VG"])],
2129    "remove an LVM logical volume",
2130    "\
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2133
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2136
2137   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["vgremove"; "VG"];
2145        ["lvs"]], []);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["vgremove"; "VG"];
2153        ["vgs"]], [])],
2154    "remove an LVM volume group",
2155    "\
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2157
2158 This also forcibly removes all logical volumes in the volume
2159 group (if any).");
2160
2161   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162    [InitEmpty, Always, TestOutputListOfDevices (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["pvremove"; "/dev/sda1"];
2170        ["lvs"]], []);
2171     InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["vgs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["pvs"]], [])],
2189    "remove an LVM physical volume",
2190    "\
2191 This wipes a physical volume C<device> so that LVM will no longer
2192 recognise it.
2193
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2197
2198   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199    [InitBasicFS, Always, TestOutput (
2200       [["set_e2label"; "/dev/sda1"; "testlabel"];
2201        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202    "set the ext2/3/4 filesystem label",
2203    "\
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>.  Filesystem labels are limited to
2206 16 characters.
2207
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2210
2211   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2212    [],
2213    "get the ext2/3/4 filesystem label",
2214    "\
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2216 C<device>.");
2217
2218   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219    (let uuid = uuidgen () in
2220     [InitBasicFS, Always, TestOutput (
2221        [["set_e2uuid"; "/dev/sda1"; uuid];
2222         ["get_e2uuid"; "/dev/sda1"]], uuid);
2223      InitBasicFS, Always, TestOutput (
2224        [["set_e2uuid"; "/dev/sda1"; "clear"];
2225         ["get_e2uuid"; "/dev/sda1"]], "");
2226      (* We can't predict what UUIDs will be, so just check the commands run. *)
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229      InitBasicFS, Always, TestRun (
2230        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231    "set the ext2/3/4 filesystem UUID",
2232    "\
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>.  The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2240
2241   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2242    [],
2243    "get the ext2/3/4 filesystem UUID",
2244    "\
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device>.");
2247
2248   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249    [InitBasicFS, Always, TestOutputInt (
2250       [["umount"; "/dev/sda1"];
2251        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252     InitBasicFS, Always, TestOutputInt (
2253       [["umount"; "/dev/sda1"];
2254        ["zero"; "/dev/sda1"];
2255        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256    "run the filesystem checker",
2257    "\
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2260
2261 The returned integer is the status.  See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2263
2264 Notes:
2265
2266 =over 4
2267
2268 =item *
2269
2270 Multiple status codes can be summed together.
2271
2272 =item *
2273
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2276
2277 =item *
2278
2279 Checking or repairing NTFS volumes is not supported
2280 (by linux-ntfs).
2281
2282 =back
2283
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2285
2286   ("zero", (RErr, [Device "device"]), 85, [],
2287    [InitBasicFS, Always, TestOutput (
2288       [["umount"; "/dev/sda1"];
2289        ["zero"; "/dev/sda1"];
2290        ["file"; "/dev/sda1"]], "data")],
2291    "write zeroes to the device",
2292    "\
2293 This command writes zeroes over the first few blocks of C<device>.
2294
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device).  It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2298
2299 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2300
2301   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302    (* Test disabled because grub-install incompatible with virtio-blk driver.
2303     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2304     *)
2305    [InitBasicFS, Disabled, TestOutputTrue (
2306       [["grub_install"; "/"; "/dev/sda1"];
2307        ["is_dir"; "/boot"]])],
2308    "install GRUB",
2309    "\
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2312
2313   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["write_file"; "/old"; "file content"; "0"];
2316        ["cp"; "/old"; "/new"];
2317        ["cat"; "/new"]], "file content");
2318     InitBasicFS, Always, TestOutputTrue (
2319       [["write_file"; "/old"; "file content"; "0"];
2320        ["cp"; "/old"; "/new"];
2321        ["is_file"; "/old"]]);
2322     InitBasicFS, Always, TestOutput (
2323       [["write_file"; "/old"; "file content"; "0"];
2324        ["mkdir"; "/dir"];
2325        ["cp"; "/old"; "/dir/new"];
2326        ["cat"; "/dir/new"]], "file content")],
2327    "copy a file",
2328    "\
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2331
2332   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333    [InitBasicFS, Always, TestOutput (
2334       [["mkdir"; "/olddir"];
2335        ["mkdir"; "/newdir"];
2336        ["write_file"; "/olddir/file"; "file content"; "0"];
2337        ["cp_a"; "/olddir"; "/newdir"];
2338        ["cat"; "/newdir/olddir/file"]], "file content")],
2339    "copy a file or directory recursively",
2340    "\
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2343
2344   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["mv"; "/old"; "/new"];
2348        ["cat"; "/new"]], "file content");
2349     InitBasicFS, Always, TestOutputFalse (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mv"; "/old"; "/new"];
2352        ["is_file"; "/old"]])],
2353    "move a file",
2354    "\
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2357
2358   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359    [InitEmpty, Always, TestRun (
2360       [["drop_caches"; "3"]])],
2361    "drop kernel page cache, dentries and inodes",
2362    "\
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches.  The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2367
2368 Setting C<whattodrop> to 3 should drop everything.
2369
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2372
2373   ("dmesg", (RString "kmsgs", []), 91, [],
2374    [InitEmpty, Always, TestRun (
2375       [["dmesg"]])],
2376    "return kernel messages",
2377    "\
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel.  This is sometimes useful for extended
2380 debugging of problems.
2381
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2386
2387   ("ping_daemon", (RErr, []), 92, [],
2388    [InitEmpty, Always, TestRun (
2389       [["ping_daemon"]])],
2390    "ping the guest daemon",
2391    "\
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess.  Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2396
2397   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398    [InitBasicFS, Always, TestOutputTrue (
2399       [["write_file"; "/file1"; "contents of a file"; "0"];
2400        ["cp"; "/file1"; "/file2"];
2401        ["equal"; "/file1"; "/file2"]]);
2402     InitBasicFS, Always, TestOutputFalse (
2403       [["write_file"; "/file1"; "contents of a file"; "0"];
2404        ["write_file"; "/file2"; "contents of another file"; "0"];
2405        ["equal"; "/file1"; "/file2"]]);
2406     InitBasicFS, Always, TestLastFail (
2407       [["equal"; "/file1"; "/file2"]])],
2408    "test if two files have equal contents",
2409    "\
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2412
2413 The external L<cmp(1)> program is used for the comparison.");
2414
2415   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416    [InitISOFS, Always, TestOutputList (
2417       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418     InitISOFS, Always, TestOutputList (
2419       [["strings"; "/empty"]], [])],
2420    "print the printable strings in a file",
2421    "\
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2424
2425   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings_e"; "b"; "/known-5"]], []);
2428     InitBasicFS, Disabled, TestOutputList (
2429       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431    "print the printable strings in a file",
2432    "\
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2435
2436 See the L<strings(1)> manpage for the full list of encodings.
2437
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2440
2441 The returned strings are transcoded to UTF-8.");
2442
2443   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444    [InitISOFS, Always, TestOutput (
2445       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2446     (* Test for RHBZ#501888c2 regression which caused large hexdump
2447      * commands to segfault.
2448      *)
2449     InitISOFS, Always, TestRun (
2450       [["hexdump"; "/100krandom"]])],
2451    "dump a file in hexadecimal",
2452    "\
2453 This runs C<hexdump -C> on the given C<path>.  The result is
2454 the human-readable, canonical hex dump of the file.");
2455
2456   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457    [InitNone, Always, TestOutput (
2458       [["part_disk"; "/dev/sda"; "mbr"];
2459        ["mkfs"; "ext3"; "/dev/sda1"];
2460        ["mount_options"; ""; "/dev/sda1"; "/"];
2461        ["write_file"; "/new"; "test file"; "0"];
2462        ["umount"; "/dev/sda1"];
2463        ["zerofree"; "/dev/sda1"];
2464        ["mount_options"; ""; "/dev/sda1"; "/"];
2465        ["cat"; "/new"]], "test file")],
2466    "zero unused inodes and disk blocks on ext2/3 filesystem",
2467    "\
2468 This runs the I<zerofree> program on C<device>.  This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2471 more effectively.
2472
2473 You should B<not> run this program if the filesystem is
2474 mounted.
2475
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2478
2479   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2480    [],
2481    "resize an LVM physical volume",
2482    "\
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2485
2486   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487                        Int "cyls"; Int "heads"; Int "sectors";
2488                        String "line"]), 99, [DangerWillRobinson],
2489    [],
2490    "modify a single partition on a block device",
2491    "\
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2494
2495 For other parameters, see C<guestfs_sfdisk>.  You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2497
2498 See also: C<guestfs_part_add>");
2499
2500   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2501    [],
2502    "display the partition table",
2503    "\
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command.  It is
2506 not intended to be parsed.
2507
2508 See also: C<guestfs_part_list>");
2509
2510   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2511    [],
2512    "display the kernel geometry",
2513    "\
2514 This displays the kernel's idea of the geometry of C<device>.
2515
2516 The result is in human-readable format, and not designed to
2517 be parsed.");
2518
2519   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2520    [],
2521    "display the disk geometry from the partition table",
2522    "\
2523 This displays the disk geometry of C<device> read from the
2524 partition table.  Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2532    [],
2533    "activate or deactivate all volume groups",
2534    "\
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2539 then those devices disappear.
2540
2541 This command is the same as running C<vgchange -a y|n>");
2542
2543   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate some volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2554
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2557
2558   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559    [InitNone, Always, TestOutput (
2560       [["part_disk"; "/dev/sda"; "mbr"];
2561        ["pvcreate"; "/dev/sda1"];
2562        ["vgcreate"; "VG"; "/dev/sda1"];
2563        ["lvcreate"; "LV"; "VG"; "10"];
2564        ["mkfs"; "ext2"; "/dev/VG/LV"];
2565        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566        ["write_file"; "/new"; "test content"; "0"];
2567        ["umount"; "/"];
2568        ["lvresize"; "/dev/VG/LV"; "20"];
2569        ["e2fsck_f"; "/dev/VG/LV"];
2570        ["resize2fs"; "/dev/VG/LV"];
2571        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572        ["cat"; "/new"]], "test content")],
2573    "resize an LVM logical volume",
2574    "\
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>.  When reducing, data in the reduced part
2577 is lost.");
2578
2579   ("resize2fs", (RErr, [Device "device"]), 106, [],
2580    [], (* lvresize tests this *)
2581    "resize an ext2/ext3 filesystem",
2582    "\
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2585
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command.  For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2591
2592   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593    [InitBasicFS, Always, TestOutputList (
2594       [["find"; "/"]], ["lost+found"]);
2595     InitBasicFS, Always, TestOutputList (
2596       [["touch"; "/a"];
2597        ["mkdir"; "/b"];
2598        ["touch"; "/b/c"];
2599        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600     InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["find"; "/a/b/"]], ["c"; "c/d"])],
2604    "find all files and directories",
2605    "\
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>.  It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2610
2611 This returns a list of strings I<without any prefix>.  Thus
2612 if the directory structure was:
2613
2614  /tmp/a
2615  /tmp/b
2616  /tmp/c/d
2617
2618 then the returned list from C<guestfs_find> C</tmp> would be
2619 4 elements:
2620
2621  a
2622  b
2623  c
2624  c/d
2625
2626 If C<directory> is not a directory, then this command returns
2627 an error.
2628
2629 The returned list is sorted.
2630
2631 See also C<guestfs_find0>.");
2632
2633   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634    [], (* lvresize tests this *)
2635    "check an ext2/ext3 filesystem",
2636    "\
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2640
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.).  Normally you should use C<guestfs_fsck>.");
2643
2644   ("sleep", (RErr, [Int "secs"]), 109, [],
2645    [InitNone, Always, TestRun (
2646       [["sleep"; "1"]])],
2647    "sleep for some seconds",
2648    "\
2649 Sleep for C<secs> seconds.");
2650
2651   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652    [InitNone, Always, TestOutputInt (
2653       [["part_disk"; "/dev/sda"; "mbr"];
2654        ["mkfs"; "ntfs"; "/dev/sda1"];
2655        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656     InitNone, Always, TestOutputInt (
2657       [["part_disk"; "/dev/sda"; "mbr"];
2658        ["mkfs"; "ext2"; "/dev/sda1"];
2659        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660    "probe NTFS volume",
2661    "\
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2665
2666 C<rw> is a boolean flag.  Set it to true if you want to test
2667 if the volume can be mounted read-write.  Set it to false if
2668 you want to test if the volume can be mounted read-only.
2669
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2673
2674   ("sh", (RString "output", [String "command"]), 111, [],
2675    [], (* XXX needs tests *)
2676    "run a command via the shell",
2677    "\
2678 This call runs a command from the guest filesystem via the
2679 guest's C</bin/sh>.
2680
2681 This is like C<guestfs_command>, but passes the command to:
2682
2683  /bin/sh -c \"command\"
2684
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2687 and so on.
2688
2689 All the provisos about C<guestfs_command> apply to this call.");
2690
2691   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692    [], (* XXX needs tests *)
2693    "run a command via the shell returning lines",
2694    "\
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2697
2698 See also: C<guestfs_command_lines>");
2699
2700   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702     * code in stubs.c, since all valid glob patterns must start with "/".
2703     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2704     *)
2705    [InitBasicFS, Always, TestOutputList (
2706       [["mkdir_p"; "/a/b/c"];
2707        ["touch"; "/a/b/c/d"];
2708        ["touch"; "/a/b/c/e"];
2709        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710     InitBasicFS, Always, TestOutputList (
2711       [["mkdir_p"; "/a/b/c"];
2712        ["touch"; "/a/b/c/d"];
2713        ["touch"; "/a/b/c/e"];
2714        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715     InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/*/x/*"]], [])],
2720    "expand a wildcard path",
2721    "\
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2724 used by the shell.
2725
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2728
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2732
2733   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735       [["scrub_device"; "/dev/sdc"]])],
2736    "scrub (securely wipe) a device",
2737    "\
2738 This command writes patterns over C<device> to make data retrieval
2739 more difficult.
2740
2741 It is an interface to the L<scrub(1)> program.  See that
2742 manual page for more details.");
2743
2744   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745    [InitBasicFS, Always, TestRun (
2746       [["write_file"; "/file"; "content"; "0"];
2747        ["scrub_file"; "/file"]])],
2748    "scrub (securely wipe) a file",
2749    "\
2750 This command writes patterns over a file to make data retrieval
2751 more difficult.
2752
2753 The file is I<removed> after scrubbing.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759    [], (* XXX needs testing *)
2760    "scrub (securely wipe) free space",
2761    "\
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2766 containing C<dir>.
2767
2768 It is an interface to the L<scrub(1)> program.  See that
2769 manual page for more details.");
2770
2771   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772    [InitBasicFS, Always, TestRun (
2773       [["mkdir"; "/tmp"];
2774        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775    "create a temporary directory",
2776    "\
2777 This command creates a temporary directory.  The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2780 \"XXXXXX\".
2781
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2784
2785 The name of the temporary directory that was created
2786 is returned.
2787
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2790
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2793
2794 See also: L<mkdtemp(3)>");
2795
2796   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["wc_l"; "/10klines"]], 10000)],
2799    "count lines in a file",
2800    "\
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2803
2804   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805    [InitISOFS, Always, TestOutputInt (
2806       [["wc_w"; "/10klines"]], 10000)],
2807    "count words in a file",
2808    "\
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2811
2812   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813    [InitISOFS, Always, TestOutputInt (
2814       [["wc_c"; "/100kallspaces"]], 102400)],
2815    "count characters in a file",
2816    "\
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2819
2820   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821    [InitISOFS, Always, TestOutputList (
2822       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823    "return first 10 lines of a file",
2824    "\
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2827
2828   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829    [InitISOFS, Always, TestOutputList (
2830       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833     InitISOFS, Always, TestOutputList (
2834       [["head_n"; "0"; "/10klines"]], [])],
2835    "return first N lines of a file",
2836    "\
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2839
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2842
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2844
2845   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846    [InitISOFS, Always, TestOutputList (
2847       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848    "return last 10 lines of a file",
2849    "\
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2852
2853   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854    [InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858     InitISOFS, Always, TestOutputList (
2859       [["tail_n"; "0"; "/10klines"]], [])],
2860    "return last N lines of a file",
2861    "\
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2864
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2867
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2869
2870   ("df", (RString "output", []), 125, [],
2871    [], (* XXX Tricky to test because it depends on the exact format
2872         * of the 'df' command and other imponderables.
2873         *)
2874    "report file system disk space usage",
2875    "\
2876 This command runs the C<df> command to report disk space used.
2877
2878 This command is mostly useful for interactive sessions.  It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2881
2882   ("df_h", (RString "output", []), 126, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage (human readable)",
2887    "\
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2890
2891 This command is mostly useful for interactive sessions.  It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2894
2895   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896    [InitISOFS, Always, TestOutputInt (
2897       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898    "estimate file space usage",
2899    "\
2900 This command runs the C<du -s> command to estimate file space
2901 usage for C<path>.
2902
2903 C<path> can be a file or a directory.  If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2906
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2909
2910   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911    [InitISOFS, Always, TestOutputList (
2912       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913    "list files in an initrd",
2914    "\
2915 This command lists out files contained in an initrd.
2916
2917 The files are listed without any initial C</> character.  The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical).  Directory names are listed as separate items.
2920
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd.  We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2924
2925   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2926    [],
2927    "mount a file using the loop device",
2928    "\
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point.  It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2932
2933   ("mkswap", (RErr, [Device "device"]), 130, [],
2934    [InitEmpty, Always, TestRun (
2935       [["part_disk"; "/dev/sda"; "mbr"];
2936        ["mkswap"; "/dev/sda1"]])],
2937    "create a swap partition",
2938    "\
2939 Create a swap partition on C<device>.");
2940
2941   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942    [InitEmpty, Always, TestRun (
2943       [["part_disk"; "/dev/sda"; "mbr"];
2944        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945    "create a swap partition with a label",
2946    "\
2947 Create a swap partition on C<device> with label C<label>.
2948
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition.  This appears to be
2951 a limitation of the kernel or swap tools.");
2952
2953   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954    (let uuid = uuidgen () in
2955     [InitEmpty, Always, TestRun (
2956        [["part_disk"; "/dev/sda"; "mbr"];
2957         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958    "create a swap partition with an explicit UUID",
2959    "\
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2961
2962   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963    [InitBasicFS, Always, TestOutputStruct (
2964       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967     InitBasicFS, Always, TestOutputStruct (
2968       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970    "make block, character or FIFO devices",
2971    "\
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2974
2975 The C<mode> parameter should be the mode, using the standard
2976 constants.  C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.");
2979
2980   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2981    [InitBasicFS, Always, TestOutputStruct (
2982       [["mkfifo"; "0o777"; "/node"];
2983        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2984    "make FIFO (named pipe)",
2985    "\
2986 This call creates a FIFO (named pipe) called C<path> with
2987 mode C<mode>.  It is just a convenient wrapper around
2988 C<guestfs_mknod>.");
2989
2990   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2994    "make block device node",
2995    "\
2996 This call creates a block device node called C<path> with
2997 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2998 It is just a convenient wrapper around C<guestfs_mknod>.");
2999
3000   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3001    [InitBasicFS, Always, TestOutputStruct (
3002       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3004    "make char device node",
3005    "\
3006 This call creates a char device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3009
3010   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3011    [], (* XXX umask is one of those stateful things that we should
3012         * reset between each test.
3013         *)
3014    "set file mode creation mask (umask)",
3015    "\
3016 This function sets the mask used for creating new files and
3017 device nodes to C<mask & 0777>.
3018
3019 Typical umask values would be C<022> which creates new files
3020 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3021 C<002> which creates new files with permissions like
3022 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3023
3024 The default umask is C<022>.  This is important because it
3025 means that directories and device nodes will be created with
3026 C<0644> or C<0755> mode even if you specify C<0777>.
3027
3028 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3029
3030 This call returns the previous umask.");
3031
3032   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3033    [],
3034    "read directories entries",
3035    "\
3036 This returns the list of directory entries in directory C<dir>.
3037
3038 All entries in the directory are returned, including C<.> and
3039 C<..>.  The entries are I<not> sorted, but returned in the same
3040 order as the underlying filesystem.
3041
3042 Also this call returns basic file type information about each
3043 file.  The C<ftyp> field will contain one of the following characters:
3044
3045 =over 4
3046
3047 =item 'b'
3048
3049 Block special
3050
3051 =item 'c'
3052
3053 Char special
3054
3055 =item 'd'
3056
3057 Directory
3058
3059 =item 'f'
3060
3061 FIFO (named pipe)
3062
3063 =item 'l'
3064
3065 Symbolic link
3066
3067 =item 'r'
3068
3069 Regular file
3070
3071 =item 's'
3072
3073 Socket
3074
3075 =item 'u'
3076
3077 Unknown file type
3078
3079 =item '?'
3080
3081 The L<readdir(3)> returned a C<d_type> field with an
3082 unexpected value
3083
3084 =back
3085
3086 This function is primarily intended for use by programs.  To
3087 get a simple list of names, use C<guestfs_ls>.  To get a printable
3088 directory for human consumption, use C<guestfs_ll>.");
3089
3090   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3091    [],
3092    "create partitions on a block device",
3093    "\
3094 This is a simplified interface to the C<guestfs_sfdisk>
3095 command, where partition sizes are specified in megabytes
3096 only (rounded to the nearest cylinder) and you don't need
3097 to specify the cyls, heads and sectors parameters which
3098 were rarely if ever used anyway.
3099
3100 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3101 and C<guestfs_part_disk>");
3102
3103   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3104    [],
3105    "determine file type inside a compressed file",
3106    "\
3107 This command runs C<file> after first decompressing C<path>
3108 using C<method>.
3109
3110 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3111
3112 Since 1.0.63, use C<guestfs_file> instead which can now
3113 process compressed files.");
3114
3115   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3116    [],
3117    "list extended attributes of a file or directory",
3118    "\
3119 This call lists the extended attributes of the file or directory
3120 C<path>.
3121
3122 At the system call level, this is a combination of the
3123 L<listxattr(2)> and L<getxattr(2)> calls.
3124
3125 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3126
3127   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3128    [],
3129    "list extended attributes of a file or directory",
3130    "\
3131 This is the same as C<guestfs_getxattrs>, but if C<path>
3132 is a symbolic link, then it returns the extended attributes
3133 of the link itself.");
3134
3135   ("setxattr", (RErr, [String "xattr";
3136                        String "val"; Int "vallen"; (* will be BufferIn *)
3137                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3138    [],
3139    "set extended attribute of a file or directory",
3140    "\
3141 This call sets the extended attribute named C<xattr>
3142 of the file C<path> to the value C<val> (of length C<vallen>).
3143 The value is arbitrary 8 bit data.
3144
3145 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3146
3147   ("lsetxattr", (RErr, [String "xattr";
3148                         String "val"; Int "vallen"; (* will be BufferIn *)
3149                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3150    [],
3151    "set extended attribute of a file or directory",
3152    "\
3153 This is the same as C<guestfs_setxattr>, but if C<path>
3154 is a symbolic link, then it sets an extended attribute
3155 of the link itself.");
3156
3157   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3158    [],
3159    "remove extended attribute of a file or directory",
3160    "\
3161 This call removes the extended attribute named C<xattr>
3162 of the file C<path>.
3163
3164 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3165
3166   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3167    [],
3168    "remove extended attribute of a file or directory",
3169    "\
3170 This is the same as C<guestfs_removexattr>, but if C<path>
3171 is a symbolic link, then it removes an extended attribute
3172 of the link itself.");
3173
3174   ("mountpoints", (RHashtable "mps", []), 147, [],
3175    [],
3176    "show mountpoints",
3177    "\
3178 This call is similar to C<guestfs_mounts>.  That call returns
3179 a list of devices.  This one returns a hash table (map) of
3180 device name to directory where the device is mounted.");
3181
3182   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3183    (* This is a special case: while you would expect a parameter
3184     * of type "Pathname", that doesn't work, because it implies
3185     * NEED_ROOT in the generated calling code in stubs.c, and
3186     * this function cannot use NEED_ROOT.
3187     *)
3188    [],
3189    "create a mountpoint",
3190    "\
3191 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3192 specialized calls that can be used to create extra mountpoints
3193 before mounting the first filesystem.
3194
3195 These calls are I<only> necessary in some very limited circumstances,
3196 mainly the case where you want to mount a mix of unrelated and/or
3197 read-only filesystems together.
3198
3199 For example, live CDs often contain a \"Russian doll\" nest of
3200 filesystems, an ISO outer layer, with a squashfs image inside, with
3201 an ext2/3 image inside that.  You can unpack this as follows
3202 in guestfish:
3203
3204  add-ro Fedora-11-i686-Live.iso
3205  run
3206  mkmountpoint /cd
3207  mkmountpoint /squash
3208  mkmountpoint /ext3
3209  mount /dev/sda /cd
3210  mount-loop /cd/LiveOS/squashfs.img /squash
3211  mount-loop /squash/LiveOS/ext3fs.img /ext3
3212
3213 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3214
3215   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3216    [],
3217    "remove a mountpoint",
3218    "\
3219 This calls removes a mountpoint that was previously created
3220 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3221 for full details.");
3222
3223   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3224    [InitISOFS, Always, TestOutputBuffer (
3225       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3226    "read a file",
3227    "\
3228 This calls returns the contents of the file C<path> as a
3229 buffer.
3230
3231 Unlike C<guestfs_cat>, this function can correctly
3232 handle files that contain embedded ASCII NUL characters.
3233 However unlike C<guestfs_download>, this function is limited
3234 in the total size of file that can be handled.");
3235
3236   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3237    [InitISOFS, Always, TestOutputList (
3238       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3239     InitISOFS, Always, TestOutputList (
3240       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3241    "return lines matching a pattern",
3242    "\
3243 This calls the external C<grep> program and returns the
3244 matching lines.");
3245
3246   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3247    [InitISOFS, Always, TestOutputList (
3248       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3249    "return lines matching a pattern",
3250    "\
3251 This calls the external C<egrep> program and returns the
3252 matching lines.");
3253
3254   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3255    [InitISOFS, Always, TestOutputList (
3256       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3257    "return lines matching a pattern",
3258    "\
3259 This calls the external C<fgrep> program and returns the
3260 matching lines.");
3261
3262   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3263    [InitISOFS, Always, TestOutputList (
3264       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3265    "return lines matching a pattern",
3266    "\
3267 This calls the external C<grep -i> program and returns the
3268 matching lines.");
3269
3270   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3271    [InitISOFS, Always, TestOutputList (
3272       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3273    "return lines matching a pattern",
3274    "\
3275 This calls the external C<egrep -i> program and returns the
3276 matching lines.");
3277
3278   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3279    [InitISOFS, Always, TestOutputList (
3280       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3281    "return lines matching a pattern",
3282    "\
3283 This calls the external C<fgrep -i> program and returns the
3284 matching lines.");
3285
3286   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputList (
3288       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3289    "return lines matching a pattern",
3290    "\
3291 This calls the external C<zgrep> program and returns the
3292 matching lines.");
3293
3294   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3295    [InitISOFS, Always, TestOutputList (
3296       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3297    "return lines matching a pattern",
3298    "\
3299 This calls the external C<zegrep> program and returns the
3300 matching lines.");
3301
3302   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3303    [InitISOFS, Always, TestOutputList (
3304       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3305    "return lines matching a pattern",
3306    "\
3307 This calls the external C<zfgrep> program and returns the
3308 matching lines.");
3309
3310   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3311    [InitISOFS, Always, TestOutputList (
3312       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3313    "return lines matching a pattern",
3314    "\
3315 This calls the external C<zgrep -i> program and returns the
3316 matching lines.");
3317
3318   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3319    [InitISOFS, Always, TestOutputList (
3320       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<zegrep -i> program and returns the
3324 matching lines.");
3325
3326   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<zfgrep -i> program and returns the
3332 matching lines.");
3333
3334   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3335    [InitISOFS, Always, TestOutput (
3336       [["realpath"; "/../directory"]], "/directory")],
3337    "canonicalized absolute pathname",
3338    "\
3339 Return the canonicalized absolute pathname of C<path>.  The
3340 returned path has no C<.>, C<..> or symbolic link path elements.");
3341
3342   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3343    [InitBasicFS, Always, TestOutputStruct (
3344       [["touch"; "/a"];
3345        ["ln"; "/a"; "/b"];
3346        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3347    "create a hard link",
3348    "\
3349 This command creates a hard link using the C<ln> command.");
3350
3351   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3352    [InitBasicFS, Always, TestOutputStruct (
3353       [["touch"; "/a"];
3354        ["touch"; "/b"];
3355        ["ln_f"; "/a"; "/b"];
3356        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357    "create a hard link",
3358    "\
3359 This command creates a hard link using the C<ln -f> command.
3360 The C<-f> option removes the link (C<linkname>) if it exists already.");
3361
3362   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3363    [InitBasicFS, Always, TestOutputStruct (
3364       [["touch"; "/a"];
3365        ["ln_s"; "a"; "/b"];
3366        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3367    "create a symbolic link",
3368    "\
3369 This command creates a symbolic link using the C<ln -s> command.");
3370
3371   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3372    [InitBasicFS, Always, TestOutput (
3373       [["mkdir_p"; "/a/b"];
3374        ["touch"; "/a/b/c"];
3375        ["ln_sf"; "../d"; "/a/b/c"];
3376        ["readlink"; "/a/b/c"]], "../d")],
3377    "create a symbolic link",
3378    "\
3379 This command creates a symbolic link using the C<ln -sf> command,
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3381
3382   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3383    [] (* XXX tested above *),
3384    "read the target of a symbolic link",
3385    "\
3386 This command reads the target of a symbolic link.");
3387
3388   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3389    [InitBasicFS, Always, TestOutputStruct (
3390       [["fallocate"; "/a"; "1000000"];
3391        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3392    "preallocate a file in the guest filesystem",
3393    "\
3394 This command preallocates a file (containing zero bytes) named
3395 C<path> of size C<len> bytes.  If the file exists already, it
3396 is overwritten.
3397
3398 Do not confuse this with the guestfish-specific
3399 C<alloc> command which allocates a file in the host and
3400 attaches it as a device.");
3401
3402   ("swapon_device", (RErr, [Device "device"]), 170, [],
3403    [InitPartition, Always, TestRun (
3404       [["mkswap"; "/dev/sda1"];
3405        ["swapon_device"; "/dev/sda1"];
3406        ["swapoff_device"; "/dev/sda1"]])],
3407    "enable swap on device",
3408    "\
3409 This command enables the libguestfs appliance to use the
3410 swap device or partition named C<device>.  The increased
3411 memory is made available for all commands, for example
3412 those run using C<guestfs_command> or C<guestfs_sh>.
3413
3414 Note that you should not swap to existing guest swap
3415 partitions unless you know what you are doing.  They may
3416 contain hibernation information, or other information that
3417 the guest doesn't want you to trash.  You also risk leaking
3418 information about the host to the guest this way.  Instead,
3419 attach a new host device to the guest and swap on that.");
3420
3421   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3422    [], (* XXX tested by swapon_device *)
3423    "disable swap on device",
3424    "\
3425 This command disables the libguestfs appliance swap
3426 device or partition named C<device>.
3427 See C<guestfs_swapon_device>.");
3428
3429   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3430    [InitBasicFS, Always, TestRun (
3431       [["fallocate"; "/swap"; "8388608"];
3432        ["mkswap_file"; "/swap"];
3433        ["swapon_file"; "/swap"];
3434        ["swapoff_file"; "/swap"]])],
3435    "enable swap on file",
3436    "\
3437 This command enables swap to a file.
3438 See C<guestfs_swapon_device> for other notes.");
3439
3440   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3441    [], (* XXX tested by swapon_file *)
3442    "disable swap on file",
3443    "\
3444 This command disables the libguestfs appliance swap on file.");
3445
3446   ("swapon_label", (RErr, [String "label"]), 174, [],
3447    [InitEmpty, Always, TestRun (
3448       [["part_disk"; "/dev/sdb"; "mbr"];
3449        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3450        ["swapon_label"; "swapit"];
3451        ["swapoff_label"; "swapit"];
3452        ["zero"; "/dev/sdb"];
3453        ["blockdev_rereadpt"; "/dev/sdb"]])],
3454    "enable swap on labeled swap partition",
3455    "\
3456 This command enables swap to a labeled swap partition.
3457 See C<guestfs_swapon_device> for other notes.");
3458
3459   ("swapoff_label", (RErr, [String "label"]), 175, [],
3460    [], (* XXX tested by swapon_label *)
3461    "disable swap on labeled swap partition",
3462    "\
3463 This command disables the libguestfs appliance swap on
3464 labeled swap partition.");
3465
3466   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3467    (let uuid = uuidgen () in
3468     [InitEmpty, Always, TestRun (
3469        [["mkswap_U"; uuid; "/dev/sdb"];
3470         ["swapon_uuid"; uuid];
3471         ["swapoff_uuid"; uuid]])]),
3472    "enable swap on swap partition by UUID",
3473    "\
3474 This command enables swap to a swap partition with the given UUID.
3475 See C<guestfs_swapon_device> for other notes.");
3476
3477   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3478    [], (* XXX tested by swapon_uuid *)
3479    "disable swap on swap partition by UUID",
3480    "\
3481 This command disables the libguestfs appliance swap partition
3482 with the given UUID.");
3483
3484   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3485    [InitBasicFS, Always, TestRun (
3486       [["fallocate"; "/swap"; "8388608"];
3487        ["mkswap_file"; "/swap"]])],
3488    "create a swap file",
3489    "\
3490 Create a swap file.
3491
3492 This command just writes a swap file signature to an existing
3493 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3494
3495   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3496    [InitISOFS, Always, TestRun (
3497       [["inotify_init"; "0"]])],
3498    "create an inotify handle",
3499    "\
3500 This command creates a new inotify handle.
3501 The inotify subsystem can be used to notify events which happen to
3502 objects in the guest filesystem.
3503
3504 C<maxevents> is the maximum number of events which will be
3505 queued up between calls to C<guestfs_inotify_read> or
3506 C<guestfs_inotify_files>.
3507 If this is passed as C<0>, then the kernel (or previously set)
3508 default is used.  For Linux 2.6.29 the default was 16384 events.
3509 Beyond this limit, the kernel throws away events, but records
3510 the fact that it threw them away by setting a flag
3511 C<IN_Q_OVERFLOW> in the returned structure list (see
3512 C<guestfs_inotify_read>).
3513
3514 Before any events are generated, you have to add some
3515 watches to the internal watch list.  See:
3516 C<guestfs_inotify_add_watch>,
3517 C<guestfs_inotify_rm_watch> and
3518 C<guestfs_inotify_watch_all>.
3519
3520 Queued up events should be read periodically by calling
3521 C<guestfs_inotify_read>
3522 (or C<guestfs_inotify_files> which is just a helpful
3523 wrapper around C<guestfs_inotify_read>).  If you don't
3524 read the events out often enough then you risk the internal
3525 queue overflowing.
3526
3527 The handle should be closed after use by calling
3528 C<guestfs_inotify_close>.  This also removes any
3529 watches automatically.
3530
3531 See also L<inotify(7)> for an overview of the inotify interface
3532 as exposed by the Linux kernel, which is roughly what we expose
3533 via libguestfs.  Note that there is one global inotify handle
3534 per libguestfs instance.");
3535
3536   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3537    [InitBasicFS, Always, TestOutputList (
3538       [["inotify_init"; "0"];
3539        ["inotify_add_watch"; "/"; "1073741823"];
3540        ["touch"; "/a"];
3541        ["touch"; "/b"];
3542        ["inotify_files"]], ["a"; "b"])],
3543    "add an inotify watch",
3544    "\
3545 Watch C<path> for the events listed in C<mask>.
3546
3547 Note that if C<path> is a directory then events within that
3548 directory are watched, but this does I<not> happen recursively
3549 (in subdirectories).
3550
3551 Note for non-C or non-Linux callers: the inotify events are
3552 defined by the Linux kernel ABI and are listed in
3553 C</usr/include/sys/inotify.h>.");
3554
3555   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3556    [],
3557    "remove an inotify watch",
3558    "\
3559 Remove a previously defined inotify watch.
3560 See C<guestfs_inotify_add_watch>.");
3561
3562   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3563    [],
3564    "return list of inotify events",
3565    "\
3566 Return the complete queue of events that have happened
3567 since the previous read call.
3568
3569 If no events have happened, this returns an empty list.
3570
3571 I<Note>: In order to make sure that all events have been
3572 read, you must call this function repeatedly until it
3573 returns an empty list.  The reason is that the call will
3574 read events up to the maximum appliance-to-host message
3575 size and leave remaining events in the queue.");
3576
3577   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3578    [],
3579    "return list of watched files that had events",
3580    "\
3581 This function is a helpful wrapper around C<guestfs_inotify_read>
3582 which just returns a list of pathnames of objects that were
3583 touched.  The returned pathnames are sorted and deduplicated.");
3584
3585   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3586    [],
3587    "close the inotify handle",
3588    "\
3589 This closes the inotify handle which was previously
3590 opened by inotify_init.  It removes all watches, throws
3591 away any pending events, and deallocates all resources.");
3592
3593   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3594    [],
3595    "set SELinux security context",
3596    "\
3597 This sets the SELinux security context of the daemon
3598 to the string C<context>.
3599
3600 See the documentation about SELINUX in L<guestfs(3)>.");
3601
3602   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3603    [],
3604    "get SELinux security context",
3605    "\
3606 This gets the SELinux security context of the daemon.
3607
3608 See the documentation about SELINUX in L<guestfs(3)>,
3609 and C<guestfs_setcon>");
3610
3611   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3612    [InitEmpty, Always, TestOutput (
3613       [["part_disk"; "/dev/sda"; "mbr"];
3614        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3615        ["mount_options"; ""; "/dev/sda1"; "/"];
3616        ["write_file"; "/new"; "new file contents"; "0"];
3617        ["cat"; "/new"]], "new file contents")],
3618    "make a filesystem with block size",
3619    "\
3620 This call is similar to C<guestfs_mkfs>, but it allows you to
3621 control the block size of the resulting filesystem.  Supported
3622 block sizes depend on the filesystem type, but typically they
3623 are C<1024>, C<2048> or C<4096> only.");
3624
3625   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3626    [InitEmpty, Always, TestOutput (
3627       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3628        ["mke2journal"; "4096"; "/dev/sda1"];
3629        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3630        ["mount_options"; ""; "/dev/sda2"; "/"];
3631        ["write_file"; "/new"; "new file contents"; "0"];
3632        ["cat"; "/new"]], "new file contents")],
3633    "make ext2/3/4 external journal",
3634    "\
3635 This creates an ext2 external journal on C<device>.  It is equivalent
3636 to the command:
3637
3638  mke2fs -O journal_dev -b blocksize device");
3639
3640   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3641    [InitEmpty, Always, TestOutput (
3642       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3644        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3645        ["mount_options"; ""; "/dev/sda2"; "/"];
3646        ["write_file"; "/new"; "new file contents"; "0"];
3647        ["cat"; "/new"]], "new file contents")],
3648    "make ext2/3/4 external journal with label",
3649    "\
3650 This creates an ext2 external journal on C<device> with label C<label>.");
3651
3652   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3653    (let uuid = uuidgen () in
3654     [InitEmpty, Always, TestOutput (
3655        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3656         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3657         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3658         ["mount_options"; ""; "/dev/sda2"; "/"];
3659         ["write_file"; "/new"; "new file contents"; "0"];
3660         ["cat"; "/new"]], "new file contents")]),
3661    "make ext2/3/4 external journal with UUID",
3662    "\
3663 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3664
3665   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3666    [],
3667    "make ext2/3/4 filesystem with external journal",
3668    "\
3669 This creates an ext2/3/4 filesystem on C<device> with
3670 an external journal on C<journal>.  It is equivalent
3671 to the command:
3672
3673  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3674
3675 See also C<guestfs_mke2journal>.");
3676
3677   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3678    [],
3679    "make ext2/3/4 filesystem with external journal",
3680    "\
3681 This creates an ext2/3/4 filesystem on C<device> with
3682 an external journal on the journal labeled C<label>.
3683
3684 See also C<guestfs_mke2journal_L>.");
3685
3686   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3687    [],
3688    "make ext2/3/4 filesystem with external journal",
3689    "\
3690 This creates an ext2/3/4 filesystem on C<device> with
3691 an external journal on the journal with UUID C<uuid>.
3692
3693 See also C<guestfs_mke2journal_U>.");
3694
3695   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3696    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3697    "load a kernel module",
3698    "\
3699 This loads a kernel module in the appliance.
3700
3701 The kernel module must have been whitelisted when libguestfs
3702 was built (see C<appliance/kmod.whitelist.in> in the source).");
3703
3704   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3705    [InitNone, Always, TestOutput (
3706       [["echo_daemon"; "This is a test"]], "This is a test"
3707     )],
3708    "echo arguments back to the client",
3709    "\
3710 This command concatenate the list of C<words> passed with single spaces between
3711 them and returns the resulting string.
3712
3713 You can use this command to test the connection through to the daemon.
3714
3715 See also C<guestfs_ping_daemon>.");
3716
3717   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3718    [], (* There is a regression test for this. *)
3719    "find all files and directories, returning NUL-separated list",
3720    "\
3721 This command lists out all files and directories, recursively,
3722 starting at C<directory>, placing the resulting list in the
3723 external file called C<files>.
3724
3725 This command works the same way as C<guestfs_find> with the
3726 following exceptions:
3727
3728 =over 4
3729
3730 =item *
3731
3732 The resulting list is written to an external file.
3733
3734 =item *
3735
3736 Items (filenames) in the result are separated
3737 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3738
3739 =item *
3740
3741 This command is not limited in the number of names that it
3742 can return.
3743
3744 =item *
3745
3746 The result list is not sorted.
3747
3748 =back");
3749
3750   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3751    [InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3755     InitISOFS, Always, TestOutput (
3756       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3757     InitISOFS, Always, TestLastFail (
3758       [["case_sensitive_path"; "/Known-1/"]]);
3759     InitBasicFS, Always, TestOutput (
3760       [["mkdir"; "/a"];
3761        ["mkdir"; "/a/bbb"];
3762        ["touch"; "/a/bbb/c"];
3763        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3764     InitBasicFS, Always, TestOutput (
3765       [["mkdir"; "/a"];
3766        ["mkdir"; "/a/bbb"];
3767        ["touch"; "/a/bbb/c"];
3768        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3769     InitBasicFS, Always, TestLastFail (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3774    "return true path on case-insensitive filesystem",
3775    "\
3776 This can be used to resolve case insensitive paths on
3777 a filesystem which is case sensitive.  The use case is
3778 to resolve paths which you have read from Windows configuration
3779 files or the Windows Registry, to the true path.
3780
3781 The command handles a peculiarity of the Linux ntfs-3g
3782 filesystem driver (and probably others), which is that although
3783 the underlying filesystem is case-insensitive, the driver
3784 exports the filesystem to Linux as case-sensitive.
3785
3786 One consequence of this is that special directories such
3787 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3788 (or other things) depending on the precise details of how
3789 they were created.  In Windows itself this would not be
3790 a problem.
3791
3792 Bug or feature?  You decide:
3793 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3794
3795 This function resolves the true case of each element in the
3796 path and returns the case-sensitive path.
3797
3798 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3799 might return C<\"/WINDOWS/system32\"> (the exact return value
3800 would depend on details of how the directories were originally
3801 created under Windows).
3802
3803 I<Note>:
3804 This function does not handle drive names, backslashes etc.
3805
3806 See also C<guestfs_realpath>.");
3807
3808   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3809    [InitBasicFS, Always, TestOutput (
3810       [["vfs_type"; "/dev/sda1"]], "ext2")],
3811    "get the Linux VFS type corresponding to a mounted device",
3812    "\
3813 This command gets the block device type corresponding to
3814 a mounted device called C<device>.
3815
3816 Usually the result is the name of the Linux VFS module that
3817 is used to mount this device (probably determined automatically
3818 if you used the C<guestfs_mount> call).");
3819
3820   ("truncate", (RErr, [Pathname "path"]), 199, [],
3821    [InitBasicFS, Always, TestOutputStruct (
3822       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3823        ["truncate"; "/test"];
3824        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3825    "truncate a file to zero size",
3826    "\
3827 This command truncates C<path> to a zero-length file.  The
3828 file must exist already.");
3829
3830   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3831    [InitBasicFS, Always, TestOutputStruct (
3832       [["touch"; "/test"];
3833        ["truncate_size"; "/test"; "1000"];
3834        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3835    "truncate a file to a particular size",
3836    "\
3837 This command truncates C<path> to size C<size> bytes.  The file
3838 must exist already.  If the file is smaller than C<size> then
3839 the file is extended to the required size with null bytes.");
3840
3841   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3842    [InitBasicFS, Always, TestOutputStruct (
3843       [["touch"; "/test"];
3844        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3845        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3846    "set timestamp of a file with nanosecond precision",
3847    "\
3848 This command sets the timestamps of a file with nanosecond
3849 precision.
3850
3851 C<atsecs, atnsecs> are the last access time (atime) in secs and
3852 nanoseconds from the epoch.
3853
3854 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3855 secs and nanoseconds from the epoch.
3856
3857 If the C<*nsecs> field contains the special value C<-1> then
3858 the corresponding timestamp is set to the current time.  (The
3859 C<*secs> field is ignored in this case).
3860
3861 If the C<*nsecs> field contains the special value C<-2> then
3862 the corresponding timestamp is left unchanged.  (The
3863 C<*secs> field is ignored in this case).");
3864
3865   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3866    [InitBasicFS, Always, TestOutputStruct (
3867       [["mkdir_mode"; "/test"; "0o111"];
3868        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3869    "create a directory with a particular mode",
3870    "\
3871 This command creates a directory, setting the initial permissions
3872 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3873
3874   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3875    [], (* XXX *)
3876    "change file owner and group",
3877    "\
3878 Change the file owner to C<owner> and group to C<group>.
3879 This is like C<guestfs_chown> but if C<path> is a symlink then
3880 the link itself is changed, not the target.
3881
3882 Only numeric uid and gid are supported.  If you want to use
3883 names, you will need to locate and parse the password file
3884 yourself (Augeas support makes this relatively easy).");
3885
3886   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3887    [], (* XXX *)
3888    "lstat on multiple files",
3889    "\
3890 This call allows you to perform the C<guestfs_lstat> operation
3891 on multiple files, where all files are in the directory C<path>.
3892 C<names> is the list of files from this directory.
3893
3894 On return you get a list of stat structs, with a one-to-one
3895 correspondence to the C<names> list.  If any name did not exist
3896 or could not be lstat'd, then the C<ino> field of that structure
3897 is set to C<-1>.
3898
3899 This call is intended for programs that want to efficiently
3900 list a directory contents without making many round-trips.
3901 See also C<guestfs_lxattrlist> for a similarly efficient call
3902 for getting extended attributes.  Very long directory listings
3903 might cause the protocol message size to be exceeded, causing
3904 this call to fail.  The caller must split up such requests
3905 into smaller groups of names.");
3906
3907   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3908    [], (* XXX *)
3909    "lgetxattr on multiple files",
3910    "\
3911 This call allows you to get the extended attributes
3912 of multiple files, where all files are in the directory C<path>.
3913 C<names> is the list of files from this directory.
3914
3915 On return you get a flat list of xattr structs which must be
3916 interpreted sequentially.  The first xattr struct always has a zero-length
3917 C<attrname>.  C<attrval> in this struct is zero-length
3918 to indicate there was an error doing C<lgetxattr> for this
3919 file, I<or> is a C string which is a decimal number
3920 (the number of following attributes for this file, which could
3921 be C<\"0\">).  Then after the first xattr struct are the
3922 zero or more attributes for the first named file.
3923 This repeats for the second and subsequent files.
3924
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lstatlist> for a similarly efficient call
3928 for getting standard stats.  Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail.  The caller must split up such requests
3931 into smaller groups of names.");
3932
3933   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3934    [], (* XXX *)
3935    "readlink on multiple files",
3936    "\
3937 This call allows you to do a C<readlink> operation
3938 on multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3940
3941 On return you get a list of strings, with a one-to-one
3942 correspondence to the C<names> list.  Each string is the
3943 value of the symbol link.
3944
3945 If the C<readlink(2)> operation fails on any name, then
3946 the corresponding result string is the empty string C<\"\">.
3947 However the whole operation is completed even if there
3948 were C<readlink(2)> errors, and so you can call this
3949 function with names where you don't know if they are
3950 symbolic links already (albeit slightly less efficient).
3951
3952 This call is intended for programs that want to efficiently
3953 list a directory contents without making many round-trips.
3954 Very long directory listings might cause the protocol
3955 message size to be exceeded, causing
3956 this call to fail.  The caller must split up such requests
3957 into smaller groups of names.");
3958
3959   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3960    [InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/known-4"; "1"; "3"]], "\n");
3962     InitISOFS, Always, TestOutputBuffer (
3963       [["pread"; "/empty"; "0"; "100"]], "")],
3964    "read part of a file",
3965    "\
3966 This command lets you read part of a file.  It reads C<count>
3967 bytes of the file, starting at C<offset>, from file C<path>.
3968
3969 This may read fewer bytes than requested.  For further details
3970 see the L<pread(2)> system call.");
3971
3972   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3973    [InitEmpty, Always, TestRun (
3974       [["part_init"; "/dev/sda"; "gpt"]])],
3975    "create an empty partition table",
3976    "\
3977 This creates an empty partition table on C<device> of one of the
3978 partition types listed below.  Usually C<parttype> should be
3979 either C<msdos> or C<gpt> (for large disks).
3980
3981 Initially there are no partitions.  Following this, you should
3982 call C<guestfs_part_add> for each partition required.
3983
3984 Possible values for C<parttype> are:
3985
3986 =over 4
3987
3988 =item B<efi> | B<gpt>
3989
3990 Intel EFI / GPT partition table.
3991
3992 This is recommended for >= 2 TB partitions that will be accessed
3993 from Linux and Intel-based Mac OS X.  It also has limited backwards
3994 compatibility with the C<mbr> format.
3995
3996 =item B<mbr> | B<msdos>
3997
3998 The standard PC \"Master Boot Record\" (MBR) format used
3999 by MS-DOS and Windows.  This partition type will B<only> work
4000 for device sizes up to 2 TB.  For large disks we recommend
4001 using C<gpt>.
4002
4003 =back
4004
4005 Other partition table types that may work but are not
4006 supported include:
4007
4008 =over 4
4009
4010 =item B<aix>
4011
4012 AIX disk labels.
4013
4014 =item B<amiga> | B<rdb>
4015
4016 Amiga \"Rigid Disk Block\" format.
4017
4018 =item B<bsd>
4019
4020 BSD disk labels.
4021
4022 =item B<dasd>
4023
4024 DASD, used on IBM mainframes.
4025
4026 =item B<dvh>
4027
4028 MIPS/SGI volumes.
4029
4030 =item B<mac>
4031
4032 Old Mac partition format.  Modern Macs use C<gpt>.
4033
4034 =item B<pc98>
4035
4036 NEC PC-98 format, common in Japan apparently.
4037
4038 =item B<sun>
4039
4040 Sun disk labels.
4041
4042 =back");
4043
4044   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4045    [InitEmpty, Always, TestRun (
4046       [["part_init"; "/dev/sda"; "mbr"];
4047        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4048     InitEmpty, Always, TestRun (
4049       [["part_init"; "/dev/sda"; "gpt"];
4050        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4051        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4052     InitEmpty, Always, TestRun (
4053       [["part_init"; "/dev/sda"; "mbr"];
4054        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4055        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4056        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4057        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4058    "add a partition to the device",
4059    "\
4060 This command adds a partition to C<device>.  If there is no partition
4061 table on the device, call C<guestfs_part_init> first.
4062
4063 The C<prlogex> parameter is the type of partition.  Normally you
4064 should pass C<p> or C<primary> here, but MBR partition tables also
4065 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4066 types.
4067
4068 C<startsect> and C<endsect> are the start and end of the partition
4069 in I<sectors>.  C<endsect> may be negative, which means it counts
4070 backwards from the end of the disk (C<-1> is the last sector).
4071
4072 Creating a partition which covers the whole disk is not so easy.
4073 Use C<guestfs_part_disk> to do that.");
4074
4075   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4076    [InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "mbr"]]);
4078     InitEmpty, Always, TestRun (
4079       [["part_disk"; "/dev/sda"; "gpt"]])],
4080    "partition whole disk with a single primary partition",
4081    "\
4082 This command is simply a combination of C<guestfs_part_init>
4083 followed by C<guestfs_part_add> to create a single primary partition
4084 covering the whole disk.
4085
4086 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4087 but other possible values are described in C<guestfs_part_init>.");
4088
4089   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4090    [InitEmpty, Always, TestRun (
4091       [["part_disk"; "/dev/sda"; "mbr"];
4092        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4093    "make a partition bootable",
4094    "\
4095 This sets the bootable flag on partition numbered C<partnum> on
4096 device C<device>.  Note that partitions are numbered from 1.
4097
4098 The bootable flag is used by some PC BIOSes to determine which
4099 partition to boot from.  It is by no means universally recognized,
4100 and in any case if your operating system installed a boot
4101 sector on the device itself, then that takes precedence.");
4102
4103   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4104    [InitEmpty, Always, TestRun (
4105       [["part_disk"; "/dev/sda"; "gpt"];
4106        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4107    "set partition name",
4108    "\
4109 This sets the partition name on partition numbered C<partnum> on
4110 device C<device>.  Note that partitions are numbered from 1.
4111
4112 The partition name can only be set on certain types of partition
4113 table.  This works on C<gpt> but not on C<mbr> partitions.");
4114
4115   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4116    [], (* XXX Add a regression test for this. *)
4117    "list partitions on a device",
4118    "\
4119 This command parses the partition table on C<device> and
4120 returns the list of partitions found.
4121
4122 The fields in the returned structure are:
4123
4124 =over 4
4125
4126 =item B<part_num>
4127
4128 Partition number, counting from 1.
4129
4130 =item B<part_start>
4131
4132 Start of the partition I<in bytes>.  To get sectors you have to
4133 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4134
4135 =item B<part_end>
4136
4137 End of the partition in bytes.
4138
4139 =item B<part_size>
4140
4141 Size of the partition in bytes.
4142
4143 =back");
4144
4145   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4146    [InitEmpty, Always, TestOutput (
4147       [["part_disk"; "/dev/sda"; "gpt"];
4148        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4149    "get the partition table type",
4150    "\
4151 This command examines the partition table on C<device> and
4152 returns the partition table type (format) being used.
4153
4154 Common return values include: C<msdos> (a DOS/Windows style MBR
4155 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4156 values are possible, although unusual.  See C<guestfs_part_init>
4157 for a full list.");
4158
4159   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4160    [InitBasicFS, Always, TestOutputBuffer (
4161       [["fill"; "0x63"; "10"; "/test"];
4162        ["read_file"; "/test"]], "cccccccccc")],
4163    "fill a file with octets",
4164    "\
4165 This command creates a new file called C<path>.  The initial
4166 content of the file is C<len> octets of C<c>, where C<c>
4167 must be a number in the range C<[0..255]>.
4168
4169 To fill a file with zero bytes (sparsely), it is
4170 much more efficient to use C<guestfs_truncate_size>.");
4171
4172   ("available", (RErr, [StringList "groups"]), 216, [],
4173    [InitNone, Always, TestRun [["available"; ""]]],
4174    "test availability of some parts of the API",
4175    "\
4176 This command is used to check the availability of some
4177 groups of functionality in the appliance, which not all builds of
4178 the libguestfs appliance will be able to provide.
4179
4180 The libguestfs groups, and the functions that those
4181 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4182
4183 The argument C<groups> is a list of group names, eg:
4184 C<[\"inotify\", \"augeas\"]> would check for the availability of
4185 the Linux inotify functions and Augeas (configuration file
4186 editing) functions.
4187
4188 The command returns no error if I<all> requested groups are available.
4189
4190 It fails with an error if one or more of the requested
4191 groups is unavailable in the appliance.
4192
4193 If an unknown group name is included in the
4194 list of groups then an error is always returned.
4195
4196 I<Notes:>
4197
4198 =over 4
4199
4200 =item *
4201
4202 You must call C<guestfs_launch> before calling this function.
4203
4204 The reason is because we don't know what groups are
4205 supported by the appliance/daemon until it is running and can
4206 be queried.
4207
4208 =item *
4209
4210 If a group of functions is available, this does not necessarily
4211 mean that they will work.  You still have to check for errors
4212 when calling individual API functions even if they are
4213 available.
4214
4215 =item *
4216
4217 It is usually the job of distro packagers to build
4218 complete functionality into the libguestfs appliance.
4219 Upstream libguestfs, if built from source with all
4220 requirements satisfied, will support everything.
4221
4222 =item *
4223
4224 This call was added in version C<1.0.80>.  In previous
4225 versions of libguestfs all you could do would be to speculatively
4226 execute a command to find out if the daemon implemented it.
4227 See also C<guestfs_version>.
4228
4229 =back");
4230
4231   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4232    [InitBasicFS, Always, TestOutputBuffer (
4233       [["write_file"; "/src"; "hello, world"; "0"];
4234        ["dd"; "/src"; "/dest"];
4235        ["read_file"; "/dest"]], "hello, world")],
4236    "copy from source to destination using dd",
4237    "\
4238 This command copies from one source device or file C<src>
4239 to another destination device or file C<dest>.  Normally you
4240 would use this to copy to or from a device or partition, for
4241 example to duplicate a filesystem.
4242
4243 If the destination is a device, it must be as large or larger
4244 than the source file or device, otherwise the copy will fail.
4245 This command cannot do partial copies (see C<guestfs_copy_size>).");
4246
4247   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4248    [InitBasicFS, Always, TestOutputInt (
4249       [["write_file"; "/file"; "hello, world"; "0"];
4250        ["filesize"; "/file"]], 12)],
4251    "return the size of the file in bytes",
4252    "\
4253 This command returns the size of C<file> in bytes.
4254
4255 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4256 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4257 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4258
4259   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4260    [InitBasicFSonLVM, Always, TestOutputList (
4261       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4262        ["lvs"]], ["/dev/VG/LV2"])],
4263    "rename an LVM logical volume",
4264    "\
4265 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4266
4267   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4268    [InitBasicFSonLVM, Always, TestOutputList (
4269       [["umount"; "/"];
4270        ["vg_activate"; "false"; "VG"];
4271        ["vgrename"; "VG"; "VG2"];
4272        ["vg_activate"; "true"; "VG2"];
4273        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4274        ["vgs"]], ["VG2"])],
4275    "rename an LVM volume group",
4276    "\
4277 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4278
4279   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4280    [InitISOFS, Always, TestOutputBuffer (
4281       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4282    "list the contents of a single file in an initrd",
4283    "\
4284 This command unpacks the file C<filename> from the initrd file
4285 called C<initrdpath>.  The filename must be given I<without> the
4286 initial C</> character.
4287
4288 For example, in guestfish you could use the following command
4289 to examine the boot script (usually called C</init>)
4290 contained in a Linux initrd or initramfs image:
4291
4292  initrd-cat /boot/initrd-<version>.img init
4293
4294 See also C<guestfs_initrd_list>.");
4295
4296   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4297    [],
4298    "get the UUID of a physical volume",
4299    "\
4300 This command returns the UUID of the LVM PV C<device>.");
4301
4302   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4303    [],
4304    "get the UUID of a volume group",
4305    "\
4306 This command returns the UUID of the LVM VG named C<vgname>.");
4307
4308   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4309    [],
4310    "get the UUID of a logical volume",
4311    "\
4312 This command returns the UUID of the LVM LV C<device>.");
4313
4314   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4315    [],
4316    "get the PV UUIDs containing the volume group",
4317    "\
4318 Given a VG called C<vgname>, this returns the UUIDs of all
4319 the physical volumes that this volume group resides on.
4320
4321 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4322 calls to associate physical volumes and volume groups.
4323
4324 See also C<guestfs_vglvuuids>.");
4325
4326   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4327    [],
4328    "get the LV UUIDs of all LVs in the volume group",
4329    "\
4330 Given a VG called C<vgname>, this returns the UUIDs of all
4331 the logical volumes created in this volume group.
4332
4333 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4334 calls to associate logical volumes and volume groups.
4335
4336 See also C<guestfs_vgpvuuids>.");
4337
4338   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4339    [InitBasicFS, Always, TestOutputBuffer (
4340       [["write_file"; "/src"; "hello, world"; "0"];
4341        ["copy_size"; "/src"; "/dest"; "5"];
4342        ["read_file"; "/dest"]], "hello")],
4343    "copy size bytes from source to destination using dd",
4344    "\
4345 This command copies exactly C<size> bytes from one source device
4346 or file C<src> to another destination device or file C<dest>.
4347
4348 Note this will fail if the source is too short or if the destination
4349 is not large enough.");
4350
4351   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4352    [InitBasicFSonLVM, Always, TestRun (
4353       [["zero_device"; "/dev/VG/LV"]])],
4354    "write zeroes to an entire device",
4355    "\
4356 This command writes zeroes over the entire C<device>.  Compare
4357 with C<guestfs_zero> which just zeroes the first few blocks of
4358 a device.");
4359
4360   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4361    [InitBasicFS, Always, TestOutput (
4362       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4363        ["cat"; "/hello"]], "hello\n")],
4364    "unpack compressed tarball to directory",
4365    "\
4366 This command uploads and unpacks local file C<tarball> (an
4367 I<xz compressed> tar file) into C<directory>.");
4368
4369   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4370    [],
4371    "pack directory into compressed tarball",
4372    "\
4373 This command packs the contents of C<directory> and downloads
4374 it to local file C<tarball> (as an xz compressed tar archive).");
4375
4376 ]
4377
4378 let all_functions = non_daemon_functions @ daemon_functions
4379
4380 (* In some places we want the functions to be displayed sorted
4381  * alphabetically, so this is useful:
4382  *)
4383 let all_functions_sorted =
4384   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4385                compare n1 n2) all_functions
4386
4387 (* Field types for structures. *)
4388 type field =
4389   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4390   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4391   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4392   | FUInt32
4393   | FInt32
4394   | FUInt64
4395   | FInt64
4396   | FBytes                      (* Any int measure that counts bytes. *)
4397   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4398   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4399
4400 (* Because we generate extra parsing code for LVM command line tools,
4401  * we have to pull out the LVM columns separately here.
4402  *)
4403 let lvm_pv_cols = [
4404   "pv_name", FString;
4405   "pv_uuid", FUUID;
4406   "pv_fmt", FString;
4407   "pv_size", FBytes;
4408   "dev_size", FBytes;
4409   "pv_free", FBytes;
4410   "pv_used", FBytes;
4411   "pv_attr", FString (* XXX *);
4412   "pv_pe_count", FInt64;
4413   "pv_pe_alloc_count", FInt64;
4414   "pv_tags", FString;
4415   "pe_start", FBytes;
4416   "pv_mda_count", FInt64;
4417   "pv_mda_free", FBytes;
4418   (* Not in Fedora 10:
4419      "pv_mda_size", FBytes;
4420   *)
4421 ]
4422 let lvm_vg_cols = [
4423   "vg_name", FString;
4424   "vg_uuid", FUUID;
4425   "vg_fmt", FString;
4426   "vg_attr", FString (* XXX *);
4427   "vg_size", FBytes;
4428   "vg_free", FBytes;
4429   "vg_sysid", FString;
4430   "vg_extent_size", FBytes;
4431   "vg_extent_count", FInt64;
4432   "vg_free_count", FInt64;
4433   "max_lv", FInt64;
4434   "max_pv", FInt64;
4435   "pv_count", FInt64;
4436   "lv_count", FInt64;
4437   "snap_count", FInt64;
4438   "vg_seqno", FInt64;
4439   "vg_tags", FString;
4440   "vg_mda_count", FInt64;
4441   "vg_mda_free", FBytes;
4442   (* Not in Fedora 10:
4443      "vg_mda_size", FBytes;
4444   *)
4445 ]
4446 let lvm_lv_cols = [
4447   "lv_name", FString;
4448   "lv_uuid", FUUID;
4449   "lv_attr", FString (* XXX *);
4450   "lv_major", FInt64;
4451   "lv_minor", FInt64;
4452   "lv_kernel_major", FInt64;
4453   "lv_kernel_minor", FInt64;
4454   "lv_size", FBytes;
4455   "seg_count", FInt64;
4456   "origin", FString;
4457   "snap_percent", FOptPercent;
4458   "copy_percent", FOptPercent;
4459   "move_pv", FString;
4460   "lv_tags", FString;
4461   "mirror_log", FString;
4462   "modules", FString;
4463 ]
4464
4465 (* Names and fields in all structures (in RStruct and RStructList)
4466  * that we support.
4467  *)
4468 let structs = [
4469   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4470    * not use this struct in any new code.
4471    *)
4472   "int_bool", [
4473     "i", FInt32;                (* for historical compatibility *)
4474     "b", FInt32;                (* for historical compatibility *)
4475   ];
4476
4477   (* LVM PVs, VGs, LVs. *)
4478   "lvm_pv", lvm_pv_cols;
4479   "lvm_vg", lvm_vg_cols;
4480   "lvm_lv", lvm_lv_cols;
4481
4482   (* Column names and types from stat structures.
4483    * NB. Can't use things like 'st_atime' because glibc header files
4484    * define some of these as macros.  Ugh.
4485    *)
4486   "stat", [
4487     "dev", FInt64;
4488     "ino", FInt64;
4489     "mode", FInt64;
4490     "nlink", FInt64;
4491     "uid", FInt64;
4492     "gid", FInt64;
4493     "rdev", FInt64;
4494     "size", FInt64;
4495     "blksize", FInt64;
4496     "blocks", FInt64;
4497     "atime", FInt64;
4498     "mtime", FInt64;
4499     "ctime", FInt64;
4500   ];
4501   "statvfs", [
4502     "bsize", FInt64;
4503     "frsize", FInt64;
4504     "blocks", FInt64;
4505     "bfree", FInt64;
4506     "bavail", FInt64;
4507     "files", FInt64;
4508     "ffree", FInt64;
4509     "favail", FInt64;
4510     "fsid", FInt64;
4511     "flag", FInt64;
4512     "namemax", FInt64;
4513   ];
4514
4515   (* Column names in dirent structure. *)
4516   "dirent", [
4517     "ino", FInt64;
4518     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4519     "ftyp", FChar;
4520     "name", FString;
4521   ];
4522
4523   (* Version numbers. *)
4524   "version", [
4525     "major", FInt64;
4526     "minor", FInt64;
4527     "release", FInt64;
4528     "extra", FString;
4529   ];
4530
4531   (* Extended attribute. *)
4532   "xattr", [
4533     "attrname", FString;
4534     "attrval", FBuffer;
4535   ];
4536
4537   (* Inotify events. *)
4538   "inotify_event", [
4539     "in_wd", FInt64;
4540     "in_mask", FUInt32;
4541     "in_cookie", FUInt32;
4542     "in_name", FString;
4543   ];
4544
4545   (* Partition table entry. *)
4546   "partition", [
4547     "part_num", FInt32;
4548     "part_start", FBytes;
4549     "part_end", FBytes;
4550     "part_size", FBytes;
4551   ];
4552 ] (* end of structs *)
4553
4554 (* Ugh, Java has to be different ..
4555  * These names are also used by the Haskell bindings.
4556  *)
4557 let java_structs = [
4558   "int_bool", "IntBool";
4559   "lvm_pv", "PV";
4560   "lvm_vg", "VG";
4561   "lvm_lv", "LV";
4562   "stat", "Stat";
4563   "statvfs", "StatVFS";
4564   "dirent", "Dirent";
4565   "version", "Version";
4566   "xattr", "XAttr";
4567   "inotify_event", "INotifyEvent";
4568   "partition", "Partition";
4569 ]
4570
4571 (* What structs are actually returned. *)
4572 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4573
4574 (* Returns a list of RStruct/RStructList structs that are returned
4575  * by any function.  Each element of returned list is a pair:
4576  *
4577  * (structname, RStructOnly)
4578  *    == there exists function which returns RStruct (_, structname)
4579  * (structname, RStructListOnly)
4580  *    == there exists function which returns RStructList (_, structname)
4581  * (structname, RStructAndList)
4582  *    == there are functions returning both RStruct (_, structname)
4583  *                                      and RStructList (_, structname)
4584  *)
4585 let rstructs_used_by functions =
4586   (* ||| is a "logical OR" for rstructs_used_t *)
4587   let (|||) a b =
4588     match a, b with
4589     | RStructAndList, _
4590     | _, RStructAndList -> RStructAndList
4591     | RStructOnly, RStructListOnly
4592     | RStructListOnly, RStructOnly -> RStructAndList
4593     | RStructOnly, RStructOnly -> RStructOnly
4594     | RStructListOnly, RStructListOnly -> RStructListOnly
4595   in
4596
4597   let h = Hashtbl.create 13 in
4598
4599   (* if elem->oldv exists, update entry using ||| operator,
4600    * else just add elem->newv to the hash
4601    *)
4602   let update elem newv =
4603     try  let oldv = Hashtbl.find h elem in
4604          Hashtbl.replace h elem (newv ||| oldv)
4605     with Not_found -> Hashtbl.add h elem newv
4606   in
4607
4608   List.iter (
4609     fun (_, style, _, _, _, _, _) ->
4610       match fst style with
4611       | RStruct (_, structname) -> update structname RStructOnly
4612       | RStructList (_, structname) -> update structname RStructListOnly
4613       | _ -> ()
4614   ) functions;
4615
4616   (* return key->values as a list of (key,value) *)
4617   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4618
4619 (* Used for testing language bindings. *)
4620 type callt =
4621   | CallString of string
4622   | CallOptString of string option
4623   | CallStringList of string list
4624   | CallInt of int
4625   | CallInt64 of int64
4626   | CallBool of bool
4627
4628 (* Used to memoize the result of pod2text. *)
4629 let pod2text_memo_filename = "src/.pod2text.data"
4630 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4631   try
4632     let chan = open_in pod2text_memo_filename in
4633     let v = input_value chan in
4634     close_in chan;
4635     v
4636   with
4637     _ -> Hashtbl.create 13
4638 let pod2text_memo_updated () =
4639   let chan = open_out pod2text_memo_filename in
4640   output_value chan pod2text_memo;
4641   close_out chan
4642
4643 (* Useful functions.
4644  * Note we don't want to use any external OCaml libraries which
4645  * makes this a bit harder than it should be.
4646  *)
4647 module StringMap = Map.Make (String)
4648
4649 let failwithf fs = ksprintf failwith fs
4650
4651 let unique = let i = ref 0 in fun () -> incr i; !i
4652
4653 let replace_char s c1 c2 =
4654   let s2 = String.copy s in
4655   let r = ref false in
4656   for i = 0 to String.length s2 - 1 do
4657     if String.unsafe_get s2 i = c1 then (
4658       String.unsafe_set s2 i c2;
4659       r := true
4660     )
4661   done;
4662   if not !r then s else s2
4663
4664 let isspace c =
4665   c = ' '
4666   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4667
4668 let triml ?(test = isspace) str =
4669   let i = ref 0 in
4670   let n = ref (String.length str) in
4671   while !n > 0 && test str.[!i]; do
4672     decr n;
4673     incr i
4674   done;
4675   if !i = 0 then str
4676   else String.sub str !i !n
4677
4678 let trimr ?(test = isspace) str =
4679   let n = ref (String.length str) in
4680   while !n > 0 && test str.[!n-1]; do
4681     decr n
4682   done;
4683   if !n = String.length str then str
4684   else String.sub str 0 !n
4685
4686 let trim ?(test = isspace) str =
4687   trimr ~test (triml ~test str)
4688
4689 let rec find s sub =
4690   let len = String.length s in
4691   let sublen = String.length sub in
4692   let rec loop i =
4693     if i <= len-sublen then (
4694       let rec loop2 j =
4695         if j < sublen then (
4696           if s.[i+j] = sub.[j] then loop2 (j+1)
4697           else -1
4698         ) else
4699           i (* found *)
4700       in
4701       let r = loop2 0 in
4702       if r = -1 then loop (i+1) else r
4703     ) else
4704       -1 (* not found *)
4705   in
4706   loop 0
4707
4708 let rec replace_str s s1 s2 =
4709   let len = String.length s in
4710   let sublen = String.length s1 in
4711   let i = find s s1 in
4712   if i = -1 then s
4713   else (
4714     let s' = String.sub s 0 i in
4715     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4716     s' ^ s2 ^ replace_str s'' s1 s2
4717   )
4718
4719 let rec string_split sep str =
4720   let len = String.length str in
4721   let seplen = String.length sep in
4722   let i = find str sep in
4723   if i = -1 then [str]
4724   else (
4725     let s' = String.sub str 0 i in
4726     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4727     s' :: string_split sep s''
4728   )
4729
4730 let files_equal n1 n2 =
4731   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4732   match Sys.command cmd with
4733   | 0 -> true
4734   | 1 -> false
4735   | i -> failwithf "%s: failed with error code %d" cmd i
4736
4737 let rec filter_map f = function
4738   | [] -> []
4739   | x :: xs ->
4740       match f x with
4741       | Some y -> y :: filter_map f xs
4742       | None -> filter_map f xs
4743
4744 let rec find_map f = function
4745   | [] -> raise Not_found
4746   | x :: xs ->
4747       match f x with
4748       | Some y -> y
4749       | None -> find_map f xs
4750
4751 let iteri f xs =
4752   let rec loop i = function
4753     | [] -> ()
4754     | x :: xs -> f i x; loop (i+1) xs
4755   in
4756   loop 0 xs
4757
4758 let mapi f xs =
4759   let rec loop i = function
4760     | [] -> []
4761     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4762   in
4763   loop 0 xs
4764
4765 let count_chars c str =
4766   let count = ref 0 in
4767   for i = 0 to String.length str - 1 do
4768     if c = String.unsafe_get str i then incr count
4769   done;
4770   !count
4771
4772 let name_of_argt = function
4773   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4774   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4775   | FileIn n | FileOut n -> n
4776
4777 let java_name_of_struct typ =
4778   try List.assoc typ java_structs
4779   with Not_found ->
4780     failwithf
4781       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4782
4783 let cols_of_struct typ =
4784   try List.assoc typ structs
4785   with Not_found ->
4786     failwithf "cols_of_struct: unknown struct %s" typ
4787
4788 let seq_of_test = function
4789   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4790   | TestOutputListOfDevices (s, _)
4791   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4792   | TestOutputTrue s | TestOutputFalse s
4793   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4794   | TestOutputStruct (s, _)
4795   | TestLastFail s -> s
4796
4797 (* Handling for function flags. *)
4798 let protocol_limit_warning =
4799   "Because of the message protocol, there is a transfer limit
4800 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4801
4802 let danger_will_robinson =
4803   "B<This command is dangerous.  Without careful use you
4804 can easily destroy all your data>."
4805
4806 let deprecation_notice flags =
4807   try
4808     let alt =
4809       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4810     let txt =
4811       sprintf "This function is deprecated.
4812 In new code, use the C<%s> call instead.
4813
4814 Deprecated functions will not be removed from the API, but the
4815 fact that they are deprecated indicates that there are problems
4816 with correct use of these functions." alt in
4817     Some txt
4818   with
4819     Not_found -> None
4820
4821 (* Create list of optional groups. *)
4822 let optgroups =
4823   let h = Hashtbl.create 13 in
4824   List.iter (
4825     fun (name, _, _, flags, _, _, _) ->
4826       List.iter (
4827         function
4828         | Optional group ->
4829             let names = try Hashtbl.find h group with Not_found -> [] in
4830             Hashtbl.replace h group (name :: names)
4831         | _ -> ()
4832       ) flags
4833   ) daemon_functions;
4834   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4835   let groups =
4836     List.map (
4837       fun group -> group, List.sort compare (Hashtbl.find h group)
4838     ) groups in
4839   List.sort (fun x y -> compare (fst x) (fst y)) groups
4840
4841 (* Check function names etc. for consistency. *)
4842 let check_functions () =
4843   let contains_uppercase str =
4844     let len = String.length str in
4845     let rec loop i =
4846       if i >= len then false
4847       else (
4848         let c = str.[i] in
4849         if c >= 'A' && c <= 'Z' then true
4850         else loop (i+1)
4851       )
4852     in
4853     loop 0
4854   in
4855
4856   (* Check function names. *)
4857   List.iter (
4858     fun (name, _, _, _, _, _, _) ->
4859       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4860         failwithf "function name %s does not need 'guestfs' prefix" name;
4861       if name = "" then
4862         failwithf "function name is empty";
4863       if name.[0] < 'a' || name.[0] > 'z' then
4864         failwithf "function name %s must start with lowercase a-z" name;
4865       if String.contains name '-' then
4866         failwithf "function name %s should not contain '-', use '_' instead."
4867           name
4868   ) all_functions;
4869
4870   (* Check function parameter/return names. *)
4871   List.iter (
4872     fun (name, style, _, _, _, _, _) ->
4873       let check_arg_ret_name n =
4874         if contains_uppercase n then
4875           failwithf "%s param/ret %s should not contain uppercase chars"
4876             name n;
4877         if String.contains n '-' || String.contains n '_' then
4878           failwithf "%s param/ret %s should not contain '-' or '_'"
4879             name n;
4880         if n = "value" then
4881           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;
4882         if n = "int" || n = "char" || n = "short" || n = "long" then
4883           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4884         if n = "i" || n = "n" then
4885           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4886         if n = "argv" || n = "args" then
4887           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4888
4889         (* List Haskell, OCaml and C keywords here.
4890          * http://www.haskell.org/haskellwiki/Keywords
4891          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4892          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4893          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4894          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4895          * Omitting _-containing words, since they're handled above.
4896          * Omitting the OCaml reserved word, "val", is ok,
4897          * and saves us from renaming several parameters.
4898          *)
4899         let reserved = [
4900           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4901           "char"; "class"; "const"; "constraint"; "continue"; "data";
4902           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4903           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4904           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4905           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4906           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4907           "interface";
4908           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4909           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4910           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4911           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4912           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4913           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4914           "volatile"; "when"; "where"; "while";
4915           ] in
4916         if List.mem n reserved then
4917           failwithf "%s has param/ret using reserved word %s" name n;
4918       in
4919
4920       (match fst style with
4921        | RErr -> ()
4922        | RInt n | RInt64 n | RBool n
4923        | RConstString n | RConstOptString n | RString n
4924        | RStringList n | RStruct (n, _) | RStructList (n, _)
4925        | RHashtable n | RBufferOut n ->
4926            check_arg_ret_name n
4927       );
4928       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4929   ) all_functions;
4930
4931   (* Check short descriptions. *)
4932   List.iter (
4933     fun (name, _, _, _, _, shortdesc, _) ->
4934       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4935         failwithf "short description of %s should begin with lowercase." name;
4936       let c = shortdesc.[String.length shortdesc-1] in
4937       if c = '\n' || c = '.' then
4938         failwithf "short description of %s should not end with . or \\n." name
4939   ) all_functions;
4940
4941   (* Check long dscriptions. *)
4942   List.iter (
4943     fun (name, _, _, _, _, _, longdesc) ->
4944       if longdesc.[String.length longdesc-1] = '\n' then
4945         failwithf "long description of %s should not end with \\n." name
4946   ) all_functions;
4947
4948   (* Check proc_nrs. *)
4949   List.iter (
4950     fun (name, _, proc_nr, _, _, _, _) ->
4951       if proc_nr <= 0 then
4952         failwithf "daemon function %s should have proc_nr > 0" name
4953   ) daemon_functions;
4954
4955   List.iter (
4956     fun (name, _, proc_nr, _, _, _, _) ->
4957       if proc_nr <> -1 then
4958         failwithf "non-daemon function %s should have proc_nr -1" name
4959   ) non_daemon_functions;
4960
4961   let proc_nrs =
4962     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4963       daemon_functions in
4964   let proc_nrs =
4965     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4966   let rec loop = function
4967     | [] -> ()
4968     | [_] -> ()
4969     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4970         loop rest
4971     | (name1,nr1) :: (name2,nr2) :: _ ->
4972         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4973           name1 name2 nr1 nr2
4974   in
4975   loop proc_nrs;
4976
4977   (* Check tests. *)
4978   List.iter (
4979     function
4980       (* Ignore functions that have no tests.  We generate a
4981        * warning when the user does 'make check' instead.
4982        *)
4983     | name, _, _, _, [], _, _ -> ()
4984     | name, _, _, _, tests, _, _ ->
4985         let funcs =
4986           List.map (
4987             fun (_, _, test) ->
4988               match seq_of_test test with
4989               | [] ->
4990                   failwithf "%s has a test containing an empty sequence" name
4991               | cmds -> List.map List.hd cmds
4992           ) tests in
4993         let funcs = List.flatten funcs in
4994
4995         let tested = List.mem name funcs in
4996
4997         if not tested then
4998           failwithf "function %s has tests but does not test itself" name
4999   ) all_functions
5000
5001 (* 'pr' prints to the current output file. *)
5002 let chan = ref Pervasives.stdout
5003 let lines = ref 0
5004 let pr fs =
5005   ksprintf
5006     (fun str ->
5007        let i = count_chars '\n' str in
5008        lines := !lines + i;
5009        output_string !chan str
5010     ) fs
5011
5012 let copyright_years =
5013   let this_year = 1900 + (localtime (time ())).tm_year in
5014   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5015
5016 (* Generate a header block in a number of standard styles. *)
5017 type comment_style =
5018     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5019 type license = GPLv2plus | LGPLv2plus
5020
5021 let generate_header ?(extra_inputs = []) comment license =
5022   let inputs = "src/generator.ml" :: extra_inputs in
5023   let c = match comment with
5024     | CStyle ->         pr "/* "; " *"
5025     | CPlusPlusStyle -> pr "// "; "//"
5026     | HashStyle ->      pr "# ";  "#"
5027     | OCamlStyle ->     pr "(* "; " *"
5028     | HaskellStyle ->   pr "{- "; "  " in
5029   pr "libguestfs generated file\n";
5030   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5031   List.iter (pr "%s   %s\n" c) inputs;
5032   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5033   pr "%s\n" c;
5034   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5035   pr "%s\n" c;
5036   (match license with
5037    | GPLv2plus ->
5038        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5039        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5040        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5041        pr "%s (at your option) any later version.\n" c;
5042        pr "%s\n" c;
5043        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5044        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5045        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5046        pr "%s GNU General Public License for more details.\n" c;
5047        pr "%s\n" c;
5048        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5049        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5050        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5051
5052    | LGPLv2plus ->
5053        pr "%s This library is free software; you can redistribute it and/or\n" c;
5054        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5055        pr "%s License as published by the Free Software Foundation; either\n" c;
5056        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5057        pr "%s\n" c;
5058        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5059        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5060        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5061        pr "%s Lesser General Public License for more details.\n" c;
5062        pr "%s\n" c;
5063        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5064        pr "%s License along with this library; if not, write to the Free Software\n" c;
5065        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5066   );
5067   (match comment with
5068    | CStyle -> pr " */\n"
5069    | CPlusPlusStyle
5070    | HashStyle -> ()
5071    | OCamlStyle -> pr " *)\n"
5072    | HaskellStyle -> pr "-}\n"
5073   );
5074   pr "\n"
5075
5076 (* Start of main code generation functions below this line. *)
5077
5078 (* Generate the pod documentation for the C API. *)
5079 let rec generate_actions_pod () =
5080   List.iter (
5081     fun (shortname, style, _, flags, _, _, longdesc) ->
5082       if not (List.mem NotInDocs flags) then (
5083         let name = "guestfs_" ^ shortname in
5084         pr "=head2 %s\n\n" name;
5085         pr " ";
5086         generate_prototype ~extern:false ~handle:"handle" name style;
5087         pr "\n\n";
5088         pr "%s\n\n" longdesc;
5089         (match fst style with
5090          | RErr ->
5091              pr "This function returns 0 on success or -1 on error.\n\n"
5092          | RInt _ ->
5093              pr "On error this function returns -1.\n\n"
5094          | RInt64 _ ->
5095              pr "On error this function returns -1.\n\n"
5096          | RBool _ ->
5097              pr "This function returns a C truth value on success or -1 on error.\n\n"
5098          | RConstString _ ->
5099              pr "This function returns a string, or NULL on error.
5100 The string is owned by the guest handle and must I<not> be freed.\n\n"
5101          | RConstOptString _ ->
5102              pr "This function returns a string which may be NULL.
5103 There is way to return an error from this function.
5104 The string is owned by the guest handle and must I<not> be freed.\n\n"
5105          | RString _ ->
5106              pr "This function returns a string, or NULL on error.
5107 I<The caller must free the returned string after use>.\n\n"
5108          | RStringList _ ->
5109              pr "This function returns a NULL-terminated array of strings
5110 (like L<environ(3)>), or NULL if there was an error.
5111 I<The caller must free the strings and the array after use>.\n\n"
5112          | RStruct (_, typ) ->
5113              pr "This function returns a C<struct guestfs_%s *>,
5114 or NULL if there was an error.
5115 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5116          | RStructList (_, typ) ->
5117              pr "This function returns a C<struct guestfs_%s_list *>
5118 (see E<lt>guestfs-structs.hE<gt>),
5119 or NULL if there was an error.
5120 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5121          | RHashtable _ ->
5122              pr "This function returns a NULL-terminated array of
5123 strings, or NULL if there was an error.
5124 The array of strings will always have length C<2n+1>, where
5125 C<n> keys and values alternate, followed by the trailing NULL entry.
5126 I<The caller must free the strings and the array after use>.\n\n"
5127          | RBufferOut _ ->
5128              pr "This function returns a buffer, or NULL on error.
5129 The size of the returned buffer is written to C<*size_r>.
5130 I<The caller must free the returned buffer after use>.\n\n"
5131         );
5132         if List.mem ProtocolLimitWarning flags then
5133           pr "%s\n\n" protocol_limit_warning;
5134         if List.mem DangerWillRobinson flags then
5135           pr "%s\n\n" danger_will_robinson;
5136         match deprecation_notice flags with
5137         | None -> ()
5138         | Some txt -> pr "%s\n\n" txt
5139       )
5140   ) all_functions_sorted
5141
5142 and generate_structs_pod () =
5143   (* Structs documentation. *)
5144   List.iter (
5145     fun (typ, cols) ->
5146       pr "=head2 guestfs_%s\n" typ;
5147       pr "\n";
5148       pr " struct guestfs_%s {\n" typ;
5149       List.iter (
5150         function
5151         | name, FChar -> pr "   char %s;\n" name
5152         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5153         | name, FInt32 -> pr "   int32_t %s;\n" name
5154         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5155         | name, FInt64 -> pr "   int64_t %s;\n" name
5156         | name, FString -> pr "   char *%s;\n" name
5157         | name, FBuffer ->
5158             pr "   /* The next two fields describe a byte array. */\n";
5159             pr "   uint32_t %s_len;\n" name;
5160             pr "   char *%s;\n" name
5161         | name, FUUID ->
5162             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5163             pr "   char %s[32];\n" name
5164         | name, FOptPercent ->
5165             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5166             pr "   float %s;\n" name
5167       ) cols;
5168       pr " };\n";
5169       pr " \n";
5170       pr " struct guestfs_%s_list {\n" typ;
5171       pr "   uint32_t len; /* Number of elements in list. */\n";
5172       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5173       pr " };\n";
5174       pr " \n";
5175       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5176       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5177         typ typ;
5178       pr "\n"
5179   ) structs
5180
5181 and generate_availability_pod () =
5182   (* Availability documentation. *)
5183   pr "=over 4\n";
5184   pr "\n";
5185   List.iter (
5186     fun (group, functions) ->
5187       pr "=item B<%s>\n" group;
5188       pr "\n";
5189       pr "The following functions:\n";
5190       List.iter (pr "L</guestfs_%s>\n") functions;
5191       pr "\n"
5192   ) optgroups;
5193   pr "=back\n";
5194   pr "\n"
5195
5196 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5197  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5198  *
5199  * We have to use an underscore instead of a dash because otherwise
5200  * rpcgen generates incorrect code.
5201  *
5202  * This header is NOT exported to clients, but see also generate_structs_h.
5203  *)
5204 and generate_xdr () =
5205   generate_header CStyle LGPLv2plus;
5206
5207   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5208   pr "typedef string str<>;\n";
5209   pr "\n";
5210
5211   (* Internal structures. *)
5212   List.iter (
5213     function
5214     | typ, cols ->
5215         pr "struct guestfs_int_%s {\n" typ;
5216         List.iter (function
5217                    | name, FChar -> pr "  char %s;\n" name
5218                    | name, FString -> pr "  string %s<>;\n" name
5219                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5220                    | name, FUUID -> pr "  opaque %s[32];\n" name
5221                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5222                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5223                    | name, FOptPercent -> pr "  float %s;\n" name
5224                   ) cols;
5225         pr "};\n";
5226         pr "\n";
5227         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5228         pr "\n";
5229   ) structs;
5230
5231   List.iter (
5232     fun (shortname, style, _, _, _, _, _) ->
5233       let name = "guestfs_" ^ shortname in
5234
5235       (match snd style with
5236        | [] -> ()
5237        | args ->
5238            pr "struct %s_args {\n" name;
5239            List.iter (
5240              function
5241              | Pathname n | Device n | Dev_or_Path n | String n ->
5242                  pr "  string %s<>;\n" n
5243              | OptString n -> pr "  str *%s;\n" n
5244              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5245              | Bool n -> pr "  bool %s;\n" n
5246              | Int n -> pr "  int %s;\n" n
5247              | Int64 n -> pr "  hyper %s;\n" n
5248              | FileIn _ | FileOut _ -> ()
5249            ) args;
5250            pr "};\n\n"
5251       );
5252       (match fst style with
5253        | RErr -> ()
5254        | RInt n ->
5255            pr "struct %s_ret {\n" name;
5256            pr "  int %s;\n" n;
5257            pr "};\n\n"
5258        | RInt64 n ->
5259            pr "struct %s_ret {\n" name;
5260            pr "  hyper %s;\n" n;
5261            pr "};\n\n"
5262        | RBool n ->
5263            pr "struct %s_ret {\n" name;
5264            pr "  bool %s;\n" n;
5265            pr "};\n\n"
5266        | RConstString _ | RConstOptString _ ->
5267            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5268        | RString n ->
5269            pr "struct %s_ret {\n" name;
5270            pr "  string %s<>;\n" n;
5271            pr "};\n\n"
5272        | RStringList n ->
5273            pr "struct %s_ret {\n" name;
5274            pr "  str %s<>;\n" n;
5275            pr "};\n\n"
5276        | RStruct (n, typ) ->
5277            pr "struct %s_ret {\n" name;
5278            pr "  guestfs_int_%s %s;\n" typ n;
5279            pr "};\n\n"
5280        | RStructList (n, typ) ->
5281            pr "struct %s_ret {\n" name;
5282            pr "  guestfs_int_%s_list %s;\n" typ n;
5283            pr "};\n\n"
5284        | RHashtable n ->
5285            pr "struct %s_ret {\n" name;
5286            pr "  str %s<>;\n" n;
5287            pr "};\n\n"
5288        | RBufferOut n ->
5289            pr "struct %s_ret {\n" name;
5290            pr "  opaque %s<>;\n" n;
5291            pr "};\n\n"
5292       );
5293   ) daemon_functions;
5294
5295   (* Table of procedure numbers. *)
5296   pr "enum guestfs_procedure {\n";
5297   List.iter (
5298     fun (shortname, _, proc_nr, _, _, _, _) ->
5299       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5300   ) daemon_functions;
5301   pr "  GUESTFS_PROC_NR_PROCS\n";
5302   pr "};\n";
5303   pr "\n";
5304
5305   (* Having to choose a maximum message size is annoying for several
5306    * reasons (it limits what we can do in the API), but it (a) makes
5307    * the protocol a lot simpler, and (b) provides a bound on the size
5308    * of the daemon which operates in limited memory space.
5309    *)
5310   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5311   pr "\n";
5312
5313   (* Message header, etc. *)
5314   pr "\
5315 /* The communication protocol is now documented in the guestfs(3)
5316  * manpage.
5317  */
5318
5319 const GUESTFS_PROGRAM = 0x2000F5F5;
5320 const GUESTFS_PROTOCOL_VERSION = 1;
5321
5322 /* These constants must be larger than any possible message length. */
5323 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5324 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5325
5326 enum guestfs_message_direction {
5327   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5328   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5329 };
5330
5331 enum guestfs_message_status {
5332   GUESTFS_STATUS_OK = 0,
5333   GUESTFS_STATUS_ERROR = 1
5334 };
5335
5336 const GUESTFS_ERROR_LEN = 256;
5337
5338 struct guestfs_message_error {
5339   string error_message<GUESTFS_ERROR_LEN>;
5340 };
5341
5342 struct guestfs_message_header {
5343   unsigned prog;                     /* GUESTFS_PROGRAM */
5344   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5345   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5346   guestfs_message_direction direction;
5347   unsigned serial;                   /* message serial number */
5348   guestfs_message_status status;
5349 };
5350
5351 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5352
5353 struct guestfs_chunk {
5354   int cancel;                        /* if non-zero, transfer is cancelled */
5355   /* data size is 0 bytes if the transfer has finished successfully */
5356   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5357 };
5358 "
5359
5360 (* Generate the guestfs-structs.h file. *)
5361 and generate_structs_h () =
5362   generate_header CStyle LGPLv2plus;
5363
5364   (* This is a public exported header file containing various
5365    * structures.  The structures are carefully written to have
5366    * exactly the same in-memory format as the XDR structures that
5367    * we use on the wire to the daemon.  The reason for creating
5368    * copies of these structures here is just so we don't have to
5369    * export the whole of guestfs_protocol.h (which includes much
5370    * unrelated and XDR-dependent stuff that we don't want to be
5371    * public, or required by clients).
5372    *
5373    * To reiterate, we will pass these structures to and from the
5374    * client with a simple assignment or memcpy, so the format
5375    * must be identical to what rpcgen / the RFC defines.
5376    *)
5377
5378   (* Public structures. *)
5379   List.iter (
5380     fun (typ, cols) ->
5381       pr "struct guestfs_%s {\n" typ;
5382       List.iter (
5383         function
5384         | name, FChar -> pr "  char %s;\n" name
5385         | name, FString -> pr "  char *%s;\n" name
5386         | name, FBuffer ->
5387             pr "  uint32_t %s_len;\n" name;
5388             pr "  char *%s;\n" name
5389         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5390         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5391         | name, FInt32 -> pr "  int32_t %s;\n" name
5392         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5393         | name, FInt64 -> pr "  int64_t %s;\n" name
5394         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5395       ) cols;
5396       pr "};\n";
5397       pr "\n";
5398       pr "struct guestfs_%s_list {\n" typ;
5399       pr "  uint32_t len;\n";
5400       pr "  struct guestfs_%s *val;\n" typ;
5401       pr "};\n";
5402       pr "\n";
5403       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5404       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5405       pr "\n"
5406   ) structs
5407
5408 (* Generate the guestfs-actions.h file. *)
5409 and generate_actions_h () =
5410   generate_header CStyle LGPLv2plus;
5411   List.iter (
5412     fun (shortname, style, _, _, _, _, _) ->
5413       let name = "guestfs_" ^ shortname in
5414       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5415         name style
5416   ) all_functions
5417
5418 (* Generate the guestfs-internal-actions.h file. *)
5419 and generate_internal_actions_h () =
5420   generate_header CStyle LGPLv2plus;
5421   List.iter (
5422     fun (shortname, style, _, _, _, _, _) ->
5423       let name = "guestfs__" ^ shortname in
5424       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5425         name style
5426   ) non_daemon_functions
5427
5428 (* Generate the client-side dispatch stubs. *)
5429 and generate_client_actions () =
5430   generate_header CStyle LGPLv2plus;
5431
5432   pr "\
5433 #include <stdio.h>
5434 #include <stdlib.h>
5435 #include <stdint.h>
5436 #include <string.h>
5437 #include <inttypes.h>
5438
5439 #include \"guestfs.h\"
5440 #include \"guestfs-internal.h\"
5441 #include \"guestfs-internal-actions.h\"
5442 #include \"guestfs_protocol.h\"
5443
5444 #define error guestfs_error
5445 //#define perrorf guestfs_perrorf
5446 #define safe_malloc guestfs_safe_malloc
5447 #define safe_realloc guestfs_safe_realloc
5448 //#define safe_strdup guestfs_safe_strdup
5449 #define safe_memdup guestfs_safe_memdup
5450
5451 /* Check the return message from a call for validity. */
5452 static int
5453 check_reply_header (guestfs_h *g,
5454                     const struct guestfs_message_header *hdr,
5455                     unsigned int proc_nr, unsigned int serial)
5456 {
5457   if (hdr->prog != GUESTFS_PROGRAM) {
5458     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5459     return -1;
5460   }
5461   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5462     error (g, \"wrong protocol version (%%d/%%d)\",
5463            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5464     return -1;
5465   }
5466   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5467     error (g, \"unexpected message direction (%%d/%%d)\",
5468            hdr->direction, GUESTFS_DIRECTION_REPLY);
5469     return -1;
5470   }
5471   if (hdr->proc != proc_nr) {
5472     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5473     return -1;
5474   }
5475   if (hdr->serial != serial) {
5476     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5477     return -1;
5478   }
5479
5480   return 0;
5481 }
5482
5483 /* Check we are in the right state to run a high-level action. */
5484 static int
5485 check_state (guestfs_h *g, const char *caller)
5486 {
5487   if (!guestfs__is_ready (g)) {
5488     if (guestfs__is_config (g) || guestfs__is_launching (g))
5489       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5490         caller);
5491     else
5492       error (g, \"%%s called from the wrong state, %%d != READY\",
5493         caller, guestfs__get_state (g));
5494     return -1;
5495   }
5496   return 0;
5497 }
5498
5499 ";
5500
5501   (* Generate code to generate guestfish call traces. *)
5502   let trace_call shortname style =
5503     pr "  if (guestfs__get_trace (g)) {\n";
5504
5505     let needs_i =
5506       List.exists (function
5507                    | StringList _ | DeviceList _ -> true
5508                    | _ -> false) (snd style) in
5509     if needs_i then (
5510       pr "    int i;\n";
5511       pr "\n"
5512     );
5513
5514     pr "    printf (\"%s\");\n" shortname;
5515     List.iter (
5516       function
5517       | String n                        (* strings *)
5518       | Device n
5519       | Pathname n
5520       | Dev_or_Path n
5521       | FileIn n
5522       | FileOut n ->
5523           (* guestfish doesn't support string escaping, so neither do we *)
5524           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5525       | OptString n ->                  (* string option *)
5526           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5527           pr "    else printf (\" null\");\n"
5528       | StringList n
5529       | DeviceList n ->                 (* string list *)
5530           pr "    putchar (' ');\n";
5531           pr "    putchar ('\"');\n";
5532           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5533           pr "      if (i > 0) putchar (' ');\n";
5534           pr "      fputs (%s[i], stdout);\n" n;
5535           pr "    }\n";
5536           pr "    putchar ('\"');\n";
5537       | Bool n ->                       (* boolean *)
5538           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5539       | Int n ->                        (* int *)
5540           pr "    printf (\" %%d\", %s);\n" n
5541       | Int64 n ->
5542           pr "    printf (\" %%\" PRIi64, %s);\n" n
5543     ) (snd style);
5544     pr "    putchar ('\\n');\n";
5545     pr "  }\n";
5546     pr "\n";
5547   in
5548
5549   (* For non-daemon functions, generate a wrapper around each function. *)
5550   List.iter (
5551     fun (shortname, style, _, _, _, _, _) ->
5552       let name = "guestfs_" ^ shortname in
5553
5554       generate_prototype ~extern:false ~semicolon:false ~newline:true
5555         ~handle:"g" name style;
5556       pr "{\n";
5557       trace_call shortname style;
5558       pr "  return guestfs__%s " shortname;
5559       generate_c_call_args ~handle:"g" style;
5560       pr ";\n";
5561       pr "}\n";
5562       pr "\n"
5563   ) non_daemon_functions;
5564
5565   (* Client-side stubs for each function. *)
5566   List.iter (
5567     fun (shortname, style, _, _, _, _, _) ->
5568       let name = "guestfs_" ^ shortname in
5569
5570       (* Generate the action stub. *)
5571       generate_prototype ~extern:false ~semicolon:false ~newline:true
5572         ~handle:"g" name style;
5573
5574       let error_code =
5575         match fst style with
5576         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5577         | RConstString _ | RConstOptString _ ->
5578             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5579         | RString _ | RStringList _
5580         | RStruct _ | RStructList _
5581         | RHashtable _ | RBufferOut _ ->
5582             "NULL" in
5583
5584       pr "{\n";
5585
5586       (match snd style with
5587        | [] -> ()
5588        | _ -> pr "  struct %s_args args;\n" name
5589       );
5590
5591       pr "  guestfs_message_header hdr;\n";
5592       pr "  guestfs_message_error err;\n";
5593       let has_ret =
5594         match fst style with
5595         | RErr -> false
5596         | RConstString _ | RConstOptString _ ->
5597             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5598         | RInt _ | RInt64 _
5599         | RBool _ | RString _ | RStringList _
5600         | RStruct _ | RStructList _
5601         | RHashtable _ | RBufferOut _ ->
5602             pr "  struct %s_ret ret;\n" name;
5603             true in
5604
5605       pr "  int serial;\n";
5606       pr "  int r;\n";
5607       pr "\n";
5608       trace_call shortname style;
5609       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5610       pr "  guestfs___set_busy (g);\n";
5611       pr "\n";
5612
5613       (* Send the main header and arguments. *)
5614       (match snd style with
5615        | [] ->
5616            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5617              (String.uppercase shortname)
5618        | args ->
5619            List.iter (
5620              function
5621              | Pathname n | Device n | Dev_or_Path n | String n ->
5622                  pr "  args.%s = (char *) %s;\n" n n
5623              | OptString n ->
5624                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5625              | StringList n | DeviceList n ->
5626                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5627                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5628              | Bool n ->
5629                  pr "  args.%s = %s;\n" n n
5630              | Int n ->
5631                  pr "  args.%s = %s;\n" n n
5632              | Int64 n ->
5633                  pr "  args.%s = %s;\n" n n
5634              | FileIn _ | FileOut _ -> ()
5635            ) args;
5636            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5637              (String.uppercase shortname);
5638            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5639              name;
5640       );
5641       pr "  if (serial == -1) {\n";
5642       pr "    guestfs___end_busy (g);\n";
5643       pr "    return %s;\n" error_code;
5644       pr "  }\n";
5645       pr "\n";
5646
5647       (* Send any additional files (FileIn) requested. *)
5648       let need_read_reply_label = ref false in
5649       List.iter (
5650         function
5651         | FileIn n ->
5652             pr "  r = guestfs___send_file (g, %s);\n" n;
5653             pr "  if (r == -1) {\n";
5654             pr "    guestfs___end_busy (g);\n";
5655             pr "    return %s;\n" error_code;
5656             pr "  }\n";
5657             pr "  if (r == -2) /* daemon cancelled */\n";
5658             pr "    goto read_reply;\n";
5659             need_read_reply_label := true;
5660             pr "\n";
5661         | _ -> ()
5662       ) (snd style);
5663
5664       (* Wait for the reply from the remote end. *)
5665       if !need_read_reply_label then pr " read_reply:\n";
5666       pr "  memset (&hdr, 0, sizeof hdr);\n";
5667       pr "  memset (&err, 0, sizeof err);\n";
5668       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5669       pr "\n";
5670       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5671       if not has_ret then
5672         pr "NULL, NULL"
5673       else
5674         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5675       pr ");\n";
5676
5677       pr "  if (r == -1) {\n";
5678       pr "    guestfs___end_busy (g);\n";
5679       pr "    return %s;\n" error_code;
5680       pr "  }\n";
5681       pr "\n";
5682
5683       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5684         (String.uppercase shortname);
5685       pr "    guestfs___end_busy (g);\n";
5686       pr "    return %s;\n" error_code;
5687       pr "  }\n";
5688       pr "\n";
5689
5690       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5691       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5692       pr "    free (err.error_message);\n";
5693       pr "    guestfs___end_busy (g);\n";
5694       pr "    return %s;\n" error_code;
5695       pr "  }\n";
5696       pr "\n";
5697
5698       (* Expecting to receive further files (FileOut)? *)
5699       List.iter (
5700         function
5701         | FileOut n ->
5702             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5703             pr "    guestfs___end_busy (g);\n";
5704             pr "    return %s;\n" error_code;
5705             pr "  }\n";
5706             pr "\n";
5707         | _ -> ()
5708       ) (snd style);
5709
5710       pr "  guestfs___end_busy (g);\n";
5711
5712       (match fst style with
5713        | RErr -> pr "  return 0;\n"
5714        | RInt n | RInt64 n | RBool n ->
5715            pr "  return ret.%s;\n" n
5716        | RConstString _ | RConstOptString _ ->
5717            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5718        | RString n ->
5719            pr "  return ret.%s; /* caller will free */\n" n
5720        | RStringList n | RHashtable n ->
5721            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5722            pr "  ret.%s.%s_val =\n" n n;
5723            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5724            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5725              n n;
5726            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5727            pr "  return ret.%s.%s_val;\n" n n
5728        | RStruct (n, _) ->
5729            pr "  /* caller will free this */\n";
5730            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5731        | RStructList (n, _) ->
5732            pr "  /* caller will free this */\n";
5733            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5734        | RBufferOut n ->
5735            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5736            pr "   * _val might be NULL here.  To make the API saner for\n";
5737            pr "   * callers, we turn this case into a unique pointer (using\n";
5738            pr "   * malloc(1)).\n";
5739            pr "   */\n";
5740            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5741            pr "    *size_r = ret.%s.%s_len;\n" n n;
5742            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5743            pr "  } else {\n";
5744            pr "    free (ret.%s.%s_val);\n" n n;
5745            pr "    char *p = safe_malloc (g, 1);\n";
5746            pr "    *size_r = ret.%s.%s_len;\n" n n;
5747            pr "    return p;\n";
5748            pr "  }\n";
5749       );
5750
5751       pr "}\n\n"
5752   ) daemon_functions;
5753
5754   (* Functions to free structures. *)
5755   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5756   pr " * structure format is identical to the XDR format.  See note in\n";
5757   pr " * generator.ml.\n";
5758   pr " */\n";
5759   pr "\n";
5760
5761   List.iter (
5762     fun (typ, _) ->
5763       pr "void\n";
5764       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5765       pr "{\n";
5766       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5767       pr "  free (x);\n";
5768       pr "}\n";
5769       pr "\n";
5770
5771       pr "void\n";
5772       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5773       pr "{\n";
5774       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5775       pr "  free (x);\n";
5776       pr "}\n";
5777       pr "\n";
5778
5779   ) structs;
5780
5781 (* Generate daemon/actions.h. *)
5782 and generate_daemon_actions_h () =
5783   generate_header CStyle GPLv2plus;
5784
5785   pr "#include \"../src/guestfs_protocol.h\"\n";
5786   pr "\n";
5787
5788   List.iter (
5789     fun (name, style, _, _, _, _, _) ->
5790       generate_prototype
5791         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5792         name style;
5793   ) daemon_functions
5794
5795 (* Generate the linker script which controls the visibility of
5796  * symbols in the public ABI and ensures no other symbols get
5797  * exported accidentally.
5798  *)
5799 and generate_linker_script () =
5800   generate_header HashStyle GPLv2plus;
5801
5802   let globals = [
5803     "guestfs_create";
5804     "guestfs_close";
5805     "guestfs_get_error_handler";
5806     "guestfs_get_out_of_memory_handler";
5807     "guestfs_last_error";
5808     "guestfs_set_error_handler";
5809     "guestfs_set_launch_done_callback";
5810     "guestfs_set_log_message_callback";
5811     "guestfs_set_out_of_memory_handler";
5812     "guestfs_set_subprocess_quit_callback";
5813
5814     (* Unofficial parts of the API: the bindings code use these
5815      * functions, so it is useful to export them.
5816      *)
5817     "guestfs_safe_calloc";
5818     "guestfs_safe_malloc";
5819   ] in
5820   let functions =
5821     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5822       all_functions in
5823   let structs =
5824     List.concat (
5825       List.map (fun (typ, _) ->
5826                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5827         structs
5828     ) in
5829   let globals = List.sort compare (globals @ functions @ structs) in
5830
5831   pr "{\n";
5832   pr "    global:\n";
5833   List.iter (pr "        %s;\n") globals;
5834   pr "\n";
5835
5836   pr "    local:\n";
5837   pr "        *;\n";
5838   pr "};\n"
5839
5840 (* Generate the server-side stubs. *)
5841 and generate_daemon_actions () =
5842   generate_header CStyle GPLv2plus;
5843
5844   pr "#include <config.h>\n";
5845   pr "\n";
5846   pr "#include <stdio.h>\n";
5847   pr "#include <stdlib.h>\n";
5848   pr "#include <string.h>\n";
5849   pr "#include <inttypes.h>\n";
5850   pr "#include <rpc/types.h>\n";
5851   pr "#include <rpc/xdr.h>\n";
5852   pr "\n";
5853   pr "#include \"daemon.h\"\n";
5854   pr "#include \"c-ctype.h\"\n";
5855   pr "#include \"../src/guestfs_protocol.h\"\n";
5856   pr "#include \"actions.h\"\n";
5857   pr "\n";
5858
5859   List.iter (
5860     fun (name, style, _, _, _, _, _) ->
5861       (* Generate server-side stubs. *)
5862       pr "static void %s_stub (XDR *xdr_in)\n" name;
5863       pr "{\n";
5864       let error_code =
5865         match fst style with
5866         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5867         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5868         | RBool _ -> pr "  int r;\n"; "-1"
5869         | RConstString _ | RConstOptString _ ->
5870             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5871         | RString _ -> pr "  char *r;\n"; "NULL"
5872         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5873         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5874         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5875         | RBufferOut _ ->
5876             pr "  size_t size = 1;\n";
5877             pr "  char *r;\n";
5878             "NULL" in
5879
5880       (match snd style with
5881        | [] -> ()
5882        | args ->
5883            pr "  struct guestfs_%s_args args;\n" name;
5884            List.iter (
5885              function
5886              | Device n | Dev_or_Path n
5887              | Pathname n
5888              | String n -> ()
5889              | OptString n -> pr "  char *%s;\n" n
5890              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5891              | Bool n -> pr "  int %s;\n" n
5892              | Int n -> pr "  int %s;\n" n
5893              | Int64 n -> pr "  int64_t %s;\n" n
5894              | FileIn _ | FileOut _ -> ()
5895            ) args
5896       );
5897       pr "\n";
5898
5899       (match snd style with
5900        | [] -> ()
5901        | args ->
5902            pr "  memset (&args, 0, sizeof args);\n";
5903            pr "\n";
5904            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5905            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5906            pr "    return;\n";
5907            pr "  }\n";
5908            let pr_args n =
5909              pr "  char *%s = args.%s;\n" n n
5910            in
5911            let pr_list_handling_code n =
5912              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5913              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5914              pr "  if (%s == NULL) {\n" n;
5915              pr "    reply_with_perror (\"realloc\");\n";
5916              pr "    goto done;\n";
5917              pr "  }\n";
5918              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5919              pr "  args.%s.%s_val = %s;\n" n n n;
5920            in
5921            List.iter (
5922              function
5923              | Pathname n ->
5924                  pr_args n;
5925                  pr "  ABS_PATH (%s, goto done);\n" n;
5926              | Device n ->
5927                  pr_args n;
5928                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5929              | Dev_or_Path n ->
5930                  pr_args n;
5931                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5932              | String n -> pr_args n
5933              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5934              | StringList n ->
5935                  pr_list_handling_code n;
5936              | DeviceList n ->
5937                  pr_list_handling_code n;
5938                  pr "  /* Ensure that each is a device,\n";
5939                  pr "   * and perform device name translation. */\n";
5940                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5941                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5942                  pr "  }\n";
5943              | Bool n -> pr "  %s = args.%s;\n" n n
5944              | Int n -> pr "  %s = args.%s;\n" n n
5945              | Int64 n -> pr "  %s = args.%s;\n" n n
5946              | FileIn _ | FileOut _ -> ()
5947            ) args;
5948            pr "\n"
5949       );
5950
5951
5952       (* this is used at least for do_equal *)
5953       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5954         (* Emit NEED_ROOT just once, even when there are two or
5955            more Pathname args *)
5956         pr "  NEED_ROOT (goto done);\n";
5957       );
5958
5959       (* Don't want to call the impl with any FileIn or FileOut
5960        * parameters, since these go "outside" the RPC protocol.
5961        *)
5962       let args' =
5963         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5964           (snd style) in
5965       pr "  r = do_%s " name;
5966       generate_c_call_args (fst style, args');
5967       pr ";\n";
5968
5969       (match fst style with
5970        | RErr | RInt _ | RInt64 _ | RBool _
5971        | RConstString _ | RConstOptString _
5972        | RString _ | RStringList _ | RHashtable _
5973        | RStruct (_, _) | RStructList (_, _) ->
5974            pr "  if (r == %s)\n" error_code;
5975            pr "    /* do_%s has already called reply_with_error */\n" name;
5976            pr "    goto done;\n";
5977            pr "\n"
5978        | RBufferOut _ ->
5979            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5980            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5981            pr "   */\n";
5982            pr "  if (size == 1 && r == %s)\n" error_code;
5983            pr "    /* do_%s has already called reply_with_error */\n" name;
5984            pr "    goto done;\n";
5985            pr "\n"
5986       );
5987
5988       (* If there are any FileOut parameters, then the impl must
5989        * send its own reply.
5990        *)
5991       let no_reply =
5992         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5993       if no_reply then
5994         pr "  /* do_%s has already sent a reply */\n" name
5995       else (
5996         match fst style with
5997         | RErr -> pr "  reply (NULL, NULL);\n"
5998         | RInt n | RInt64 n | RBool n ->
5999             pr "  struct guestfs_%s_ret ret;\n" name;
6000             pr "  ret.%s = r;\n" n;
6001             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6002               name
6003         | RConstString _ | RConstOptString _ ->
6004             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6005         | RString n ->
6006             pr "  struct guestfs_%s_ret ret;\n" name;
6007             pr "  ret.%s = r;\n" n;
6008             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6009               name;
6010             pr "  free (r);\n"
6011         | RStringList n | RHashtable n ->
6012             pr "  struct guestfs_%s_ret ret;\n" name;
6013             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6014             pr "  ret.%s.%s_val = r;\n" n n;
6015             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6016               name;
6017             pr "  free_strings (r);\n"
6018         | RStruct (n, _) ->
6019             pr "  struct guestfs_%s_ret ret;\n" name;
6020             pr "  ret.%s = *r;\n" n;
6021             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6022               name;
6023             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6024               name
6025         | RStructList (n, _) ->
6026             pr "  struct guestfs_%s_ret ret;\n" name;
6027             pr "  ret.%s = *r;\n" n;
6028             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6029               name;
6030             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6031               name
6032         | RBufferOut n ->
6033             pr "  struct guestfs_%s_ret ret;\n" name;
6034             pr "  ret.%s.%s_val = r;\n" n n;
6035             pr "  ret.%s.%s_len = size;\n" n n;
6036             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6037               name;
6038             pr "  free (r);\n"
6039       );
6040
6041       (* Free the args. *)
6042       (match snd style with
6043        | [] ->
6044            pr "done: ;\n";
6045        | _ ->
6046            pr "done:\n";
6047            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6048              name
6049       );
6050
6051       pr "}\n\n";
6052   ) daemon_functions;
6053
6054   (* Dispatch function. *)
6055   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6056   pr "{\n";
6057   pr "  switch (proc_nr) {\n";
6058
6059   List.iter (
6060     fun (name, style, _, _, _, _, _) ->
6061       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6062       pr "      %s_stub (xdr_in);\n" name;
6063       pr "      break;\n"
6064   ) daemon_functions;
6065
6066   pr "    default:\n";
6067   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";
6068   pr "  }\n";
6069   pr "}\n";
6070   pr "\n";
6071
6072   (* LVM columns and tokenization functions. *)
6073   (* XXX This generates crap code.  We should rethink how we
6074    * do this parsing.
6075    *)
6076   List.iter (
6077     function
6078     | typ, cols ->
6079         pr "static const char *lvm_%s_cols = \"%s\";\n"
6080           typ (String.concat "," (List.map fst cols));
6081         pr "\n";
6082
6083         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6084         pr "{\n";
6085         pr "  char *tok, *p, *next;\n";
6086         pr "  int i, j;\n";
6087         pr "\n";
6088         (*
6089           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6090           pr "\n";
6091         *)
6092         pr "  if (!str) {\n";
6093         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6094         pr "    return -1;\n";
6095         pr "  }\n";
6096         pr "  if (!*str || c_isspace (*str)) {\n";
6097         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6098         pr "    return -1;\n";
6099         pr "  }\n";
6100         pr "  tok = str;\n";
6101         List.iter (
6102           fun (name, coltype) ->
6103             pr "  if (!tok) {\n";
6104             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6105             pr "    return -1;\n";
6106             pr "  }\n";
6107             pr "  p = strchrnul (tok, ',');\n";
6108             pr "  if (*p) next = p+1; else next = NULL;\n";
6109             pr "  *p = '\\0';\n";
6110             (match coltype with
6111              | FString ->
6112                  pr "  r->%s = strdup (tok);\n" name;
6113                  pr "  if (r->%s == NULL) {\n" name;
6114                  pr "    perror (\"strdup\");\n";
6115                  pr "    return -1;\n";
6116                  pr "  }\n"
6117              | FUUID ->
6118                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6119                  pr "    if (tok[j] == '\\0') {\n";
6120                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6121                  pr "      return -1;\n";
6122                  pr "    } else if (tok[j] != '-')\n";
6123                  pr "      r->%s[i++] = tok[j];\n" name;
6124                  pr "  }\n";
6125              | FBytes ->
6126                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6127                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6128                  pr "    return -1;\n";
6129                  pr "  }\n";
6130              | FInt64 ->
6131                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6132                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6133                  pr "    return -1;\n";
6134                  pr "  }\n";
6135              | FOptPercent ->
6136                  pr "  if (tok[0] == '\\0')\n";
6137                  pr "    r->%s = -1;\n" name;
6138                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6139                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6140                  pr "    return -1;\n";
6141                  pr "  }\n";
6142              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6143                  assert false (* can never be an LVM column *)
6144             );
6145             pr "  tok = next;\n";
6146         ) cols;
6147
6148         pr "  if (tok != NULL) {\n";
6149         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6150         pr "    return -1;\n";
6151         pr "  }\n";
6152         pr "  return 0;\n";
6153         pr "}\n";
6154         pr "\n";
6155
6156         pr "guestfs_int_lvm_%s_list *\n" typ;
6157         pr "parse_command_line_%ss (void)\n" typ;
6158         pr "{\n";
6159         pr "  char *out, *err;\n";
6160         pr "  char *p, *pend;\n";
6161         pr "  int r, i;\n";
6162         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6163         pr "  void *newp;\n";
6164         pr "\n";
6165         pr "  ret = malloc (sizeof *ret);\n";
6166         pr "  if (!ret) {\n";
6167         pr "    reply_with_perror (\"malloc\");\n";
6168         pr "    return NULL;\n";
6169         pr "  }\n";
6170         pr "\n";
6171         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6172         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6173         pr "\n";
6174         pr "  r = command (&out, &err,\n";
6175         pr "           \"lvm\", \"%ss\",\n" typ;
6176         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6177         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6178         pr "  if (r == -1) {\n";
6179         pr "    reply_with_error (\"%%s\", err);\n";
6180         pr "    free (out);\n";
6181         pr "    free (err);\n";
6182         pr "    free (ret);\n";
6183         pr "    return NULL;\n";
6184         pr "  }\n";
6185         pr "\n";
6186         pr "  free (err);\n";
6187         pr "\n";
6188         pr "  /* Tokenize each line of the output. */\n";
6189         pr "  p = out;\n";
6190         pr "  i = 0;\n";
6191         pr "  while (p) {\n";
6192         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6193         pr "    if (pend) {\n";
6194         pr "      *pend = '\\0';\n";
6195         pr "      pend++;\n";
6196         pr "    }\n";
6197         pr "\n";
6198         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6199         pr "      p++;\n";
6200         pr "\n";
6201         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6202         pr "      p = pend;\n";
6203         pr "      continue;\n";
6204         pr "    }\n";
6205         pr "\n";
6206         pr "    /* Allocate some space to store this next entry. */\n";
6207         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6208         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6209         pr "    if (newp == NULL) {\n";
6210         pr "      reply_with_perror (\"realloc\");\n";
6211         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6212         pr "      free (ret);\n";
6213         pr "      free (out);\n";
6214         pr "      return NULL;\n";
6215         pr "    }\n";
6216         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6217         pr "\n";
6218         pr "    /* Tokenize the next entry. */\n";
6219         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6220         pr "    if (r == -1) {\n";
6221         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6222         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6223         pr "      free (ret);\n";
6224         pr "      free (out);\n";
6225         pr "      return NULL;\n";
6226         pr "    }\n";
6227         pr "\n";
6228         pr "    ++i;\n";
6229         pr "    p = pend;\n";
6230         pr "  }\n";
6231         pr "\n";
6232         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6233         pr "\n";
6234         pr "  free (out);\n";
6235         pr "  return ret;\n";
6236         pr "}\n"
6237
6238   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6239
6240 (* Generate a list of function names, for debugging in the daemon.. *)
6241 and generate_daemon_names () =
6242   generate_header CStyle GPLv2plus;
6243
6244   pr "#include <config.h>\n";
6245   pr "\n";
6246   pr "#include \"daemon.h\"\n";
6247   pr "\n";
6248
6249   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6250   pr "const char *function_names[] = {\n";
6251   List.iter (
6252     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6253   ) daemon_functions;
6254   pr "};\n";
6255
6256 (* Generate the optional groups for the daemon to implement
6257  * guestfs_available.
6258  *)
6259 and generate_daemon_optgroups_c () =
6260   generate_header CStyle GPLv2plus;
6261
6262   pr "#include <config.h>\n";
6263   pr "\n";
6264   pr "#include \"daemon.h\"\n";
6265   pr "#include \"optgroups.h\"\n";
6266   pr "\n";
6267
6268   pr "struct optgroup optgroups[] = {\n";
6269   List.iter (
6270     fun (group, _) ->
6271       pr "  { \"%s\", optgroup_%s_available },\n" group group
6272   ) optgroups;
6273   pr "  { NULL, NULL }\n";
6274   pr "};\n"
6275
6276 and generate_daemon_optgroups_h () =
6277   generate_header CStyle GPLv2plus;
6278
6279   List.iter (
6280     fun (group, _) ->
6281       pr "extern int optgroup_%s_available (void);\n" group
6282   ) optgroups
6283
6284 (* Generate the tests. *)
6285 and generate_tests () =
6286   generate_header CStyle GPLv2plus;
6287
6288   pr "\
6289 #include <stdio.h>
6290 #include <stdlib.h>
6291 #include <string.h>
6292 #include <unistd.h>
6293 #include <sys/types.h>
6294 #include <fcntl.h>
6295
6296 #include \"guestfs.h\"
6297 #include \"guestfs-internal.h\"
6298
6299 static guestfs_h *g;
6300 static int suppress_error = 0;
6301
6302 static void print_error (guestfs_h *g, void *data, const char *msg)
6303 {
6304   if (!suppress_error)
6305     fprintf (stderr, \"%%s\\n\", msg);
6306 }
6307
6308 /* FIXME: nearly identical code appears in fish.c */
6309 static void print_strings (char *const *argv)
6310 {
6311   int argc;
6312
6313   for (argc = 0; argv[argc] != NULL; ++argc)
6314     printf (\"\\t%%s\\n\", argv[argc]);
6315 }
6316
6317 /*
6318 static void print_table (char const *const *argv)
6319 {
6320   int i;
6321
6322   for (i = 0; argv[i] != NULL; i += 2)
6323     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6324 }
6325 */
6326
6327 ";
6328
6329   (* Generate a list of commands which are not tested anywhere. *)
6330   pr "static void no_test_warnings (void)\n";
6331   pr "{\n";
6332
6333   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6334   List.iter (
6335     fun (_, _, _, _, tests, _, _) ->
6336       let tests = filter_map (
6337         function
6338         | (_, (Always|If _|Unless _), test) -> Some test
6339         | (_, Disabled, _) -> None
6340       ) tests in
6341       let seq = List.concat (List.map seq_of_test tests) in
6342       let cmds_tested = List.map List.hd seq in
6343       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6344   ) all_functions;
6345
6346   List.iter (
6347     fun (name, _, _, _, _, _, _) ->
6348       if not (Hashtbl.mem hash name) then
6349         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6350   ) all_functions;
6351
6352   pr "}\n";
6353   pr "\n";
6354
6355   (* Generate the actual tests.  Note that we generate the tests
6356    * in reverse order, deliberately, so that (in general) the
6357    * newest tests run first.  This makes it quicker and easier to
6358    * debug them.
6359    *)
6360   let test_names =
6361     List.map (
6362       fun (name, _, _, flags, tests, _, _) ->
6363         mapi (generate_one_test name flags) tests
6364     ) (List.rev all_functions) in
6365   let test_names = List.concat test_names in
6366   let nr_tests = List.length test_names in
6367
6368   pr "\
6369 int main (int argc, char *argv[])
6370 {
6371   char c = 0;
6372   unsigned long int n_failed = 0;
6373   const char *filename;
6374   int fd;
6375   int nr_tests, test_num = 0;
6376
6377   setbuf (stdout, NULL);
6378
6379   no_test_warnings ();
6380
6381   g = guestfs_create ();
6382   if (g == NULL) {
6383     printf (\"guestfs_create FAILED\\n\");
6384     exit (EXIT_FAILURE);
6385   }
6386
6387   guestfs_set_error_handler (g, print_error, NULL);
6388
6389   guestfs_set_path (g, \"../appliance\");
6390
6391   filename = \"test1.img\";
6392   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6393   if (fd == -1) {
6394     perror (filename);
6395     exit (EXIT_FAILURE);
6396   }
6397   if (lseek (fd, %d, SEEK_SET) == -1) {
6398     perror (\"lseek\");
6399     close (fd);
6400     unlink (filename);
6401     exit (EXIT_FAILURE);
6402   }
6403   if (write (fd, &c, 1) == -1) {
6404     perror (\"write\");
6405     close (fd);
6406     unlink (filename);
6407     exit (EXIT_FAILURE);
6408   }
6409   if (close (fd) == -1) {
6410     perror (filename);
6411     unlink (filename);
6412     exit (EXIT_FAILURE);
6413   }
6414   if (guestfs_add_drive (g, filename) == -1) {
6415     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6416     exit (EXIT_FAILURE);
6417   }
6418
6419   filename = \"test2.img\";
6420   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6421   if (fd == -1) {
6422     perror (filename);
6423     exit (EXIT_FAILURE);
6424   }
6425   if (lseek (fd, %d, SEEK_SET) == -1) {
6426     perror (\"lseek\");
6427     close (fd);
6428     unlink (filename);
6429     exit (EXIT_FAILURE);
6430   }
6431   if (write (fd, &c, 1) == -1) {
6432     perror (\"write\");
6433     close (fd);
6434     unlink (filename);
6435     exit (EXIT_FAILURE);
6436   }
6437   if (close (fd) == -1) {
6438     perror (filename);
6439     unlink (filename);
6440     exit (EXIT_FAILURE);
6441   }
6442   if (guestfs_add_drive (g, filename) == -1) {
6443     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6444     exit (EXIT_FAILURE);
6445   }
6446
6447   filename = \"test3.img\";
6448   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6449   if (fd == -1) {
6450     perror (filename);
6451     exit (EXIT_FAILURE);
6452   }
6453   if (lseek (fd, %d, SEEK_SET) == -1) {
6454     perror (\"lseek\");
6455     close (fd);
6456     unlink (filename);
6457     exit (EXIT_FAILURE);
6458   }
6459   if (write (fd, &c, 1) == -1) {
6460     perror (\"write\");
6461     close (fd);
6462     unlink (filename);
6463     exit (EXIT_FAILURE);
6464   }
6465   if (close (fd) == -1) {
6466     perror (filename);
6467     unlink (filename);
6468     exit (EXIT_FAILURE);
6469   }
6470   if (guestfs_add_drive (g, filename) == -1) {
6471     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6472     exit (EXIT_FAILURE);
6473   }
6474
6475   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6476     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6477     exit (EXIT_FAILURE);
6478   }
6479
6480   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6481   alarm (600);
6482
6483   if (guestfs_launch (g) == -1) {
6484     printf (\"guestfs_launch FAILED\\n\");
6485     exit (EXIT_FAILURE);
6486   }
6487
6488   /* Cancel previous alarm. */
6489   alarm (0);
6490
6491   nr_tests = %d;
6492
6493 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6494
6495   iteri (
6496     fun i test_name ->
6497       pr "  test_num++;\n";
6498       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6499       pr "  if (%s () == -1) {\n" test_name;
6500       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6501       pr "    n_failed++;\n";
6502       pr "  }\n";
6503   ) test_names;
6504   pr "\n";
6505
6506   pr "  guestfs_close (g);\n";
6507   pr "  unlink (\"test1.img\");\n";
6508   pr "  unlink (\"test2.img\");\n";
6509   pr "  unlink (\"test3.img\");\n";
6510   pr "\n";
6511
6512   pr "  if (n_failed > 0) {\n";
6513   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6514   pr "    exit (EXIT_FAILURE);\n";
6515   pr "  }\n";
6516   pr "\n";
6517
6518   pr "  exit (EXIT_SUCCESS);\n";
6519   pr "}\n"
6520
6521 and generate_one_test name flags i (init, prereq, test) =
6522   let test_name = sprintf "test_%s_%d" name i in
6523
6524   pr "\
6525 static int %s_skip (void)
6526 {
6527   const char *str;
6528
6529   str = getenv (\"TEST_ONLY\");
6530   if (str)
6531     return strstr (str, \"%s\") == NULL;
6532   str = getenv (\"SKIP_%s\");
6533   if (str && STREQ (str, \"1\")) return 1;
6534   str = getenv (\"SKIP_TEST_%s\");
6535   if (str && STREQ (str, \"1\")) return 1;
6536   return 0;
6537 }
6538
6539 " test_name name (String.uppercase test_name) (String.uppercase name);
6540
6541   (match prereq with
6542    | Disabled | Always -> ()
6543    | If code | Unless code ->
6544        pr "static int %s_prereq (void)\n" test_name;
6545        pr "{\n";
6546        pr "  %s\n" code;
6547        pr "}\n";
6548        pr "\n";
6549   );
6550
6551   pr "\
6552 static int %s (void)
6553 {
6554   if (%s_skip ()) {
6555     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6556     return 0;
6557   }
6558
6559 " test_name test_name test_name;
6560
6561   (* Optional functions should only be tested if the relevant
6562    * support is available in the daemon.
6563    *)
6564   List.iter (
6565     function
6566     | Optional group ->
6567         pr "  {\n";
6568         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6569         pr "    int r;\n";
6570         pr "    suppress_error = 1;\n";
6571         pr "    r = guestfs_available (g, (char **) groups);\n";
6572         pr "    suppress_error = 0;\n";
6573         pr "    if (r == -1) {\n";
6574         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6575         pr "      return 0;\n";
6576         pr "    }\n";
6577         pr "  }\n";
6578     | _ -> ()
6579   ) flags;
6580
6581   (match prereq with
6582    | Disabled ->
6583        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6584    | If _ ->
6585        pr "  if (! %s_prereq ()) {\n" test_name;
6586        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6587        pr "    return 0;\n";
6588        pr "  }\n";
6589        pr "\n";
6590        generate_one_test_body name i test_name init test;
6591    | Unless _ ->
6592        pr "  if (%s_prereq ()) {\n" test_name;
6593        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6594        pr "    return 0;\n";
6595        pr "  }\n";
6596        pr "\n";
6597        generate_one_test_body name i test_name init test;
6598    | Always ->
6599        generate_one_test_body name i test_name init test
6600   );
6601
6602   pr "  return 0;\n";
6603   pr "}\n";
6604   pr "\n";
6605   test_name
6606
6607 and generate_one_test_body name i test_name init test =
6608   (match init with
6609    | InitNone (* XXX at some point, InitNone and InitEmpty became
6610                * folded together as the same thing.  Really we should
6611                * make InitNone do nothing at all, but the tests may
6612                * need to be checked to make sure this is OK.
6613                *)
6614    | InitEmpty ->
6615        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6616        List.iter (generate_test_command_call test_name)
6617          [["blockdev_setrw"; "/dev/sda"];
6618           ["umount_all"];
6619           ["lvm_remove_all"]]
6620    | InitPartition ->
6621        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6622        List.iter (generate_test_command_call test_name)
6623          [["blockdev_setrw"; "/dev/sda"];
6624           ["umount_all"];
6625           ["lvm_remove_all"];
6626           ["part_disk"; "/dev/sda"; "mbr"]]
6627    | InitBasicFS ->
6628        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6629        List.iter (generate_test_command_call test_name)
6630          [["blockdev_setrw"; "/dev/sda"];
6631           ["umount_all"];
6632           ["lvm_remove_all"];
6633           ["part_disk"; "/dev/sda"; "mbr"];
6634           ["mkfs"; "ext2"; "/dev/sda1"];
6635           ["mount_options"; ""; "/dev/sda1"; "/"]]
6636    | InitBasicFSonLVM ->
6637        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6638          test_name;
6639        List.iter (generate_test_command_call test_name)
6640          [["blockdev_setrw"; "/dev/sda"];
6641           ["umount_all"];
6642           ["lvm_remove_all"];
6643           ["part_disk"; "/dev/sda"; "mbr"];
6644           ["pvcreate"; "/dev/sda1"];
6645           ["vgcreate"; "VG"; "/dev/sda1"];
6646           ["lvcreate"; "LV"; "VG"; "8"];
6647           ["mkfs"; "ext2"; "/dev/VG/LV"];
6648           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6649    | InitISOFS ->
6650        pr "  /* InitISOFS for %s */\n" test_name;
6651        List.iter (generate_test_command_call test_name)
6652          [["blockdev_setrw"; "/dev/sda"];
6653           ["umount_all"];
6654           ["lvm_remove_all"];
6655           ["mount_ro"; "/dev/sdd"; "/"]]
6656   );
6657
6658   let get_seq_last = function
6659     | [] ->
6660         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6661           test_name
6662     | seq ->
6663         let seq = List.rev seq in
6664         List.rev (List.tl seq), List.hd seq
6665   in
6666
6667   match test with
6668   | TestRun seq ->
6669       pr "  /* TestRun for %s (%d) */\n" name i;
6670       List.iter (generate_test_command_call test_name) seq
6671   | TestOutput (seq, expected) ->
6672       pr "  /* TestOutput for %s (%d) */\n" name i;
6673       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6674       let seq, last = get_seq_last seq in
6675       let test () =
6676         pr "    if (STRNEQ (r, expected)) {\n";
6677         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6678         pr "      return -1;\n";
6679         pr "    }\n"
6680       in
6681       List.iter (generate_test_command_call test_name) seq;
6682       generate_test_command_call ~test test_name last
6683   | TestOutputList (seq, expected) ->
6684       pr "  /* TestOutputList for %s (%d) */\n" name i;
6685       let seq, last = get_seq_last seq in
6686       let test () =
6687         iteri (
6688           fun i str ->
6689             pr "    if (!r[%d]) {\n" i;
6690             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6691             pr "      print_strings (r);\n";
6692             pr "      return -1;\n";
6693             pr "    }\n";
6694             pr "    {\n";
6695             pr "      const char *expected = \"%s\";\n" (c_quote str);
6696             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6697             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6698             pr "        return -1;\n";
6699             pr "      }\n";
6700             pr "    }\n"
6701         ) expected;
6702         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6703         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6704           test_name;
6705         pr "      print_strings (r);\n";
6706         pr "      return -1;\n";
6707         pr "    }\n"
6708       in
6709       List.iter (generate_test_command_call test_name) seq;
6710       generate_test_command_call ~test test_name last
6711   | TestOutputListOfDevices (seq, expected) ->
6712       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6713       let seq, last = get_seq_last seq in
6714       let test () =
6715         iteri (
6716           fun i str ->
6717             pr "    if (!r[%d]) {\n" i;
6718             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6719             pr "      print_strings (r);\n";
6720             pr "      return -1;\n";
6721             pr "    }\n";
6722             pr "    {\n";
6723             pr "      const char *expected = \"%s\";\n" (c_quote str);
6724             pr "      r[%d][5] = 's';\n" i;
6725             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6726             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6727             pr "        return -1;\n";
6728             pr "      }\n";
6729             pr "    }\n"
6730         ) expected;
6731         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6732         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6733           test_name;
6734         pr "      print_strings (r);\n";
6735         pr "      return -1;\n";
6736         pr "    }\n"
6737       in
6738       List.iter (generate_test_command_call test_name) seq;
6739       generate_test_command_call ~test test_name last
6740   | TestOutputInt (seq, expected) ->
6741       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6742       let seq, last = get_seq_last seq in
6743       let test () =
6744         pr "    if (r != %d) {\n" expected;
6745         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6746           test_name expected;
6747         pr "               (int) 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   | TestOutputIntOp (seq, op, expected) ->
6754       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6755       let seq, last = get_seq_last seq in
6756       let test () =
6757         pr "    if (! (r %s %d)) {\n" op expected;
6758         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6759           test_name op expected;
6760         pr "               (int) r);\n";
6761         pr "      return -1;\n";
6762         pr "    }\n"
6763       in
6764       List.iter (generate_test_command_call test_name) seq;
6765       generate_test_command_call ~test test_name last
6766   | TestOutputTrue seq ->
6767       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6768       let seq, last = get_seq_last seq in
6769       let test () =
6770         pr "    if (!r) {\n";
6771         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6772           test_name;
6773         pr "      return -1;\n";
6774         pr "    }\n"
6775       in
6776       List.iter (generate_test_command_call test_name) seq;
6777       generate_test_command_call ~test test_name last
6778   | TestOutputFalse seq ->
6779       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6780       let seq, last = get_seq_last seq in
6781       let test () =
6782         pr "    if (r) {\n";
6783         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6784           test_name;
6785         pr "      return -1;\n";
6786         pr "    }\n"
6787       in
6788       List.iter (generate_test_command_call test_name) seq;
6789       generate_test_command_call ~test test_name last
6790   | TestOutputLength (seq, expected) ->
6791       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6792       let seq, last = get_seq_last seq in
6793       let test () =
6794         pr "    int j;\n";
6795         pr "    for (j = 0; j < %d; ++j)\n" expected;
6796         pr "      if (r[j] == NULL) {\n";
6797         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6798           test_name;
6799         pr "        print_strings (r);\n";
6800         pr "        return -1;\n";
6801         pr "      }\n";
6802         pr "    if (r[j] != NULL) {\n";
6803         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6804           test_name;
6805         pr "      print_strings (r);\n";
6806         pr "      return -1;\n";
6807         pr "    }\n"
6808       in
6809       List.iter (generate_test_command_call test_name) seq;
6810       generate_test_command_call ~test test_name last
6811   | TestOutputBuffer (seq, expected) ->
6812       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6813       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6814       let seq, last = get_seq_last seq in
6815       let len = String.length expected in
6816       let test () =
6817         pr "    if (size != %d) {\n" len;
6818         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6819         pr "      return -1;\n";
6820         pr "    }\n";
6821         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6822         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6823         pr "      return -1;\n";
6824         pr "    }\n"
6825       in
6826       List.iter (generate_test_command_call test_name) seq;
6827       generate_test_command_call ~test test_name last
6828   | TestOutputStruct (seq, checks) ->
6829       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6830       let seq, last = get_seq_last seq in
6831       let test () =
6832         List.iter (
6833           function
6834           | CompareWithInt (field, expected) ->
6835               pr "    if (r->%s != %d) {\n" field expected;
6836               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6837                 test_name field expected;
6838               pr "               (int) r->%s);\n" field;
6839               pr "      return -1;\n";
6840               pr "    }\n"
6841           | CompareWithIntOp (field, op, expected) ->
6842               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6843               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6844                 test_name field op expected;
6845               pr "               (int) r->%s);\n" field;
6846               pr "      return -1;\n";
6847               pr "    }\n"
6848           | CompareWithString (field, expected) ->
6849               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6850               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6851                 test_name field expected;
6852               pr "               r->%s);\n" field;
6853               pr "      return -1;\n";
6854               pr "    }\n"
6855           | CompareFieldsIntEq (field1, field2) ->
6856               pr "    if (r->%s != r->%s) {\n" field1 field2;
6857               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6858                 test_name field1 field2;
6859               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6860               pr "      return -1;\n";
6861               pr "    }\n"
6862           | CompareFieldsStrEq (field1, field2) ->
6863               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6864               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6865                 test_name field1 field2;
6866               pr "               r->%s, r->%s);\n" field1 field2;
6867               pr "      return -1;\n";
6868               pr "    }\n"
6869         ) checks
6870       in
6871       List.iter (generate_test_command_call test_name) seq;
6872       generate_test_command_call ~test test_name last
6873   | TestLastFail seq ->
6874       pr "  /* TestLastFail for %s (%d) */\n" name i;
6875       let seq, last = get_seq_last seq in
6876       List.iter (generate_test_command_call test_name) seq;
6877       generate_test_command_call test_name ~expect_error:true last
6878
6879 (* Generate the code to run a command, leaving the result in 'r'.
6880  * If you expect to get an error then you should set expect_error:true.
6881  *)
6882 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6883   match cmd with
6884   | [] -> assert false
6885   | name :: args ->
6886       (* Look up the command to find out what args/ret it has. *)
6887       let style =
6888         try
6889           let _, style, _, _, _, _, _ =
6890             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6891           style
6892         with Not_found ->
6893           failwithf "%s: in test, command %s was not found" test_name name in
6894
6895       if List.length (snd style) <> List.length args then
6896         failwithf "%s: in test, wrong number of args given to %s"
6897           test_name name;
6898
6899       pr "  {\n";
6900
6901       List.iter (
6902         function
6903         | OptString n, "NULL" -> ()
6904         | Pathname n, arg
6905         | Device n, arg
6906         | Dev_or_Path n, arg
6907         | String n, arg
6908         | OptString n, arg ->
6909             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6910         | Int _, _
6911         | Int64 _, _
6912         | Bool _, _
6913         | FileIn _, _ | FileOut _, _ -> ()
6914         | StringList n, "" | DeviceList n, "" ->
6915             pr "    const char *const %s[1] = { NULL };\n" n
6916         | StringList n, arg | DeviceList n, arg ->
6917             let strs = string_split " " arg in
6918             iteri (
6919               fun i str ->
6920                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6921             ) strs;
6922             pr "    const char *const %s[] = {\n" n;
6923             iteri (
6924               fun i _ -> pr "      %s_%d,\n" n i
6925             ) strs;
6926             pr "      NULL\n";
6927             pr "    };\n";
6928       ) (List.combine (snd style) args);
6929
6930       let error_code =
6931         match fst style with
6932         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6933         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6934         | RConstString _ | RConstOptString _ ->
6935             pr "    const char *r;\n"; "NULL"
6936         | RString _ -> pr "    char *r;\n"; "NULL"
6937         | RStringList _ | RHashtable _ ->
6938             pr "    char **r;\n";
6939             pr "    int i;\n";
6940             "NULL"
6941         | RStruct (_, typ) ->
6942             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6943         | RStructList (_, typ) ->
6944             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6945         | RBufferOut _ ->
6946             pr "    char *r;\n";
6947             pr "    size_t size;\n";
6948             "NULL" in
6949
6950       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6951       pr "    r = guestfs_%s (g" name;
6952
6953       (* Generate the parameters. *)
6954       List.iter (
6955         function
6956         | OptString _, "NULL" -> pr ", NULL"
6957         | Pathname n, _
6958         | Device n, _ | Dev_or_Path n, _
6959         | String n, _
6960         | OptString n, _ ->
6961             pr ", %s" n
6962         | FileIn _, arg | FileOut _, arg ->
6963             pr ", \"%s\"" (c_quote arg)
6964         | StringList n, _ | DeviceList n, _ ->
6965             pr ", (char **) %s" n
6966         | Int _, arg ->
6967             let i =
6968               try int_of_string arg
6969               with Failure "int_of_string" ->
6970                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6971             pr ", %d" i
6972         | Int64 _, arg ->
6973             let i =
6974               try Int64.of_string arg
6975               with Failure "int_of_string" ->
6976                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6977             pr ", %Ld" i
6978         | Bool _, arg ->
6979             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6980       ) (List.combine (snd style) args);
6981
6982       (match fst style with
6983        | RBufferOut _ -> pr ", &size"
6984        | _ -> ()
6985       );
6986
6987       pr ");\n";
6988
6989       if not expect_error then
6990         pr "    if (r == %s)\n" error_code
6991       else
6992         pr "    if (r != %s)\n" error_code;
6993       pr "      return -1;\n";
6994
6995       (* Insert the test code. *)
6996       (match test with
6997        | None -> ()
6998        | Some f -> f ()
6999       );
7000
7001       (match fst style with
7002        | RErr | RInt _ | RInt64 _ | RBool _
7003        | RConstString _ | RConstOptString _ -> ()
7004        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7005        | RStringList _ | RHashtable _ ->
7006            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7007            pr "      free (r[i]);\n";
7008            pr "    free (r);\n"
7009        | RStruct (_, typ) ->
7010            pr "    guestfs_free_%s (r);\n" typ
7011        | RStructList (_, typ) ->
7012            pr "    guestfs_free_%s_list (r);\n" typ
7013       );
7014
7015       pr "  }\n"
7016
7017 and c_quote str =
7018   let str = replace_str str "\r" "\\r" in
7019   let str = replace_str str "\n" "\\n" in
7020   let str = replace_str str "\t" "\\t" in
7021   let str = replace_str str "\000" "\\0" in
7022   str
7023
7024 (* Generate a lot of different functions for guestfish. *)
7025 and generate_fish_cmds () =
7026   generate_header CStyle GPLv2plus;
7027
7028   let all_functions =
7029     List.filter (
7030       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7031     ) all_functions in
7032   let all_functions_sorted =
7033     List.filter (
7034       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7035     ) all_functions_sorted in
7036
7037   pr "#include <config.h>\n";
7038   pr "\n";
7039   pr "#include <stdio.h>\n";
7040   pr "#include <stdlib.h>\n";
7041   pr "#include <string.h>\n";
7042   pr "#include <inttypes.h>\n";
7043   pr "\n";
7044   pr "#include <guestfs.h>\n";
7045   pr "#include \"c-ctype.h\"\n";
7046   pr "#include \"full-write.h\"\n";
7047   pr "#include \"xstrtol.h\"\n";
7048   pr "#include \"fish.h\"\n";
7049   pr "\n";
7050
7051   (* list_commands function, which implements guestfish -h *)
7052   pr "void list_commands (void)\n";
7053   pr "{\n";
7054   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7055   pr "  list_builtin_commands ();\n";
7056   List.iter (
7057     fun (name, _, _, flags, _, shortdesc, _) ->
7058       let name = replace_char name '_' '-' in
7059       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7060         name shortdesc
7061   ) all_functions_sorted;
7062   pr "  printf (\"    %%s\\n\",";
7063   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7064   pr "}\n";
7065   pr "\n";
7066
7067   (* display_command function, which implements guestfish -h cmd *)
7068   pr "void display_command (const char *cmd)\n";
7069   pr "{\n";
7070   List.iter (
7071     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7072       let name2 = replace_char name '_' '-' in
7073       let alias =
7074         try find_map (function FishAlias n -> Some n | _ -> None) flags
7075         with Not_found -> name in
7076       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7077       let synopsis =
7078         match snd style with
7079         | [] -> name2
7080         | args ->
7081             sprintf "%s %s"
7082               name2 (String.concat " " (List.map name_of_argt args)) in
7083
7084       let warnings =
7085         if List.mem ProtocolLimitWarning flags then
7086           ("\n\n" ^ protocol_limit_warning)
7087         else "" in
7088
7089       (* For DangerWillRobinson commands, we should probably have
7090        * guestfish prompt before allowing you to use them (especially
7091        * in interactive mode). XXX
7092        *)
7093       let warnings =
7094         warnings ^
7095           if List.mem DangerWillRobinson flags then
7096             ("\n\n" ^ danger_will_robinson)
7097           else "" in
7098
7099       let warnings =
7100         warnings ^
7101           match deprecation_notice flags with
7102           | None -> ""
7103           | Some txt -> "\n\n" ^ txt in
7104
7105       let describe_alias =
7106         if name <> alias then
7107           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7108         else "" in
7109
7110       pr "  if (";
7111       pr "STRCASEEQ (cmd, \"%s\")" name;
7112       if name <> name2 then
7113         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7114       if name <> alias then
7115         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7116       pr ")\n";
7117       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7118         name2 shortdesc
7119         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7120          "=head1 DESCRIPTION\n\n" ^
7121          longdesc ^ warnings ^ describe_alias);
7122       pr "  else\n"
7123   ) all_functions;
7124   pr "    display_builtin_command (cmd);\n";
7125   pr "}\n";
7126   pr "\n";
7127
7128   let emit_print_list_function typ =
7129     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7130       typ typ typ;
7131     pr "{\n";
7132     pr "  unsigned int i;\n";
7133     pr "\n";
7134     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7135     pr "    printf (\"[%%d] = {\\n\", i);\n";
7136     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7137     pr "    printf (\"}\\n\");\n";
7138     pr "  }\n";
7139     pr "}\n";
7140     pr "\n";
7141   in
7142
7143   (* print_* functions *)
7144   List.iter (
7145     fun (typ, cols) ->
7146       let needs_i =
7147         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7148
7149       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7150       pr "{\n";
7151       if needs_i then (
7152         pr "  unsigned int i;\n";
7153         pr "\n"
7154       );
7155       List.iter (
7156         function
7157         | name, FString ->
7158             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7159         | name, FUUID ->
7160             pr "  printf (\"%%s%s: \", indent);\n" name;
7161             pr "  for (i = 0; i < 32; ++i)\n";
7162             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7163             pr "  printf (\"\\n\");\n"
7164         | name, FBuffer ->
7165             pr "  printf (\"%%s%s: \", indent);\n" name;
7166             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7167             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7168             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7169             pr "    else\n";
7170             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7171             pr "  printf (\"\\n\");\n"
7172         | name, (FUInt64|FBytes) ->
7173             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7174               name typ name
7175         | name, FInt64 ->
7176             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7177               name typ name
7178         | name, FUInt32 ->
7179             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7180               name typ name
7181         | name, FInt32 ->
7182             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7183               name typ name
7184         | name, FChar ->
7185             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7186               name typ name
7187         | name, FOptPercent ->
7188             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7189               typ name name typ name;
7190             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7191       ) cols;
7192       pr "}\n";
7193       pr "\n";
7194   ) structs;
7195
7196   (* Emit a print_TYPE_list function definition only if that function is used. *)
7197   List.iter (
7198     function
7199     | typ, (RStructListOnly | RStructAndList) ->
7200         (* generate the function for typ *)
7201         emit_print_list_function typ
7202     | typ, _ -> () (* empty *)
7203   ) (rstructs_used_by all_functions);
7204
7205   (* Emit a print_TYPE function definition only if that function is used. *)
7206   List.iter (
7207     function
7208     | typ, (RStructOnly | RStructAndList) ->
7209         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7210         pr "{\n";
7211         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7212         pr "}\n";
7213         pr "\n";
7214     | typ, _ -> () (* empty *)
7215   ) (rstructs_used_by all_functions);
7216
7217   (* run_<action> actions *)
7218   List.iter (
7219     fun (name, style, _, flags, _, _, _) ->
7220       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7221       pr "{\n";
7222       (match fst style with
7223        | RErr
7224        | RInt _
7225        | RBool _ -> pr "  int r;\n"
7226        | RInt64 _ -> pr "  int64_t r;\n"
7227        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7228        | RString _ -> pr "  char *r;\n"
7229        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7230        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7231        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7232        | RBufferOut _ ->
7233            pr "  char *r;\n";
7234            pr "  size_t size;\n";
7235       );
7236       List.iter (
7237         function
7238         | Device n
7239         | String n
7240         | OptString n
7241         | FileIn n
7242         | FileOut n -> pr "  const char *%s;\n" n
7243         | Pathname n
7244         | Dev_or_Path n -> pr "  char *%s;\n" n
7245         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7246         | Bool n -> pr "  int %s;\n" n
7247         | Int n -> pr "  int %s;\n" n
7248         | Int64 n -> pr "  int64_t %s;\n" n
7249       ) (snd style);
7250
7251       (* Check and convert parameters. *)
7252       let argc_expected = List.length (snd style) in
7253       pr "  if (argc != %d) {\n" argc_expected;
7254       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7255         argc_expected;
7256       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7257       pr "    return -1;\n";
7258       pr "  }\n";
7259
7260       let parse_integer fn fntyp rtyp range name i =
7261         pr "  {\n";
7262         pr "    strtol_error xerr;\n";
7263         pr "    %s r;\n" fntyp;
7264         pr "\n";
7265         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7266         pr "    if (xerr != LONGINT_OK) {\n";
7267         pr "      fprintf (stderr,\n";
7268         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7269         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7270         pr "      return -1;\n";
7271         pr "    }\n";
7272         (match range with
7273          | None -> ()
7274          | Some (min, max, comment) ->
7275              pr "    /* %s */\n" comment;
7276              pr "    if (r < %s || r > %s) {\n" min max;
7277              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7278                name;
7279              pr "      return -1;\n";
7280              pr "    }\n";
7281              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7282         );
7283         pr "    %s = r;\n" name;
7284         pr "  }\n";
7285       in
7286
7287       iteri (
7288         fun i ->
7289           function
7290           | Device name
7291           | String name ->
7292               pr "  %s = argv[%d];\n" name i
7293           | Pathname name
7294           | Dev_or_Path name ->
7295               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7296               pr "  if (%s == NULL) return -1;\n" name
7297           | OptString name ->
7298               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7299                 name i i
7300           | FileIn name ->
7301               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7302                 name i i
7303           | FileOut name ->
7304               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7305                 name i i
7306           | StringList name | DeviceList name ->
7307               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7308               pr "  if (%s == NULL) return -1;\n" name;
7309           | Bool name ->
7310               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7311           | Int name ->
7312               let range =
7313                 let min = "(-(2LL<<30))"
7314                 and max = "((2LL<<30)-1)"
7315                 and comment =
7316                   "The Int type in the generator is a signed 31 bit int." in
7317                 Some (min, max, comment) in
7318               parse_integer "xstrtoll" "long long" "int" range name i
7319           | Int64 name ->
7320               parse_integer "xstrtoll" "long long" "int64_t" None name i
7321       ) (snd style);
7322
7323       (* Call C API function. *)
7324       let fn =
7325         try find_map (function FishAction n -> Some n | _ -> None) flags
7326         with Not_found -> sprintf "guestfs_%s" name in
7327       pr "  r = %s " fn;
7328       generate_c_call_args ~handle:"g" style;
7329       pr ";\n";
7330
7331       List.iter (
7332         function
7333         | Device name | String name
7334         | OptString name | FileIn name | FileOut name | Bool name
7335         | Int name | Int64 name -> ()
7336         | Pathname name | Dev_or_Path name ->
7337             pr "  free (%s);\n" name
7338         | StringList name | DeviceList name ->
7339             pr "  free_strings (%s);\n" name
7340       ) (snd style);
7341
7342       (* Check return value for errors and display command results. *)
7343       (match fst style with
7344        | RErr -> pr "  return r;\n"
7345        | RInt _ ->
7346            pr "  if (r == -1) return -1;\n";
7347            pr "  printf (\"%%d\\n\", r);\n";
7348            pr "  return 0;\n"
7349        | RInt64 _ ->
7350            pr "  if (r == -1) return -1;\n";
7351            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7352            pr "  return 0;\n"
7353        | RBool _ ->
7354            pr "  if (r == -1) return -1;\n";
7355            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7356            pr "  return 0;\n"
7357        | RConstString _ ->
7358            pr "  if (r == NULL) return -1;\n";
7359            pr "  printf (\"%%s\\n\", r);\n";
7360            pr "  return 0;\n"
7361        | RConstOptString _ ->
7362            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7363            pr "  return 0;\n"
7364        | RString _ ->
7365            pr "  if (r == NULL) return -1;\n";
7366            pr "  printf (\"%%s\\n\", r);\n";
7367            pr "  free (r);\n";
7368            pr "  return 0;\n"
7369        | RStringList _ ->
7370            pr "  if (r == NULL) return -1;\n";
7371            pr "  print_strings (r);\n";
7372            pr "  free_strings (r);\n";
7373            pr "  return 0;\n"
7374        | RStruct (_, typ) ->
7375            pr "  if (r == NULL) return -1;\n";
7376            pr "  print_%s (r);\n" typ;
7377            pr "  guestfs_free_%s (r);\n" typ;
7378            pr "  return 0;\n"
7379        | RStructList (_, typ) ->
7380            pr "  if (r == NULL) return -1;\n";
7381            pr "  print_%s_list (r);\n" typ;
7382            pr "  guestfs_free_%s_list (r);\n" typ;
7383            pr "  return 0;\n"
7384        | RHashtable _ ->
7385            pr "  if (r == NULL) return -1;\n";
7386            pr "  print_table (r);\n";
7387            pr "  free_strings (r);\n";
7388            pr "  return 0;\n"
7389        | RBufferOut _ ->
7390            pr "  if (r == NULL) return -1;\n";
7391            pr "  if (full_write (1, r, size) != size) {\n";
7392            pr "    perror (\"write\");\n";
7393            pr "    free (r);\n";
7394            pr "    return -1;\n";
7395            pr "  }\n";
7396            pr "  free (r);\n";
7397            pr "  return 0;\n"
7398       );
7399       pr "}\n";
7400       pr "\n"
7401   ) all_functions;
7402
7403   (* run_action function *)
7404   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7405   pr "{\n";
7406   List.iter (
7407     fun (name, _, _, flags, _, _, _) ->
7408       let name2 = replace_char name '_' '-' in
7409       let alias =
7410         try find_map (function FishAlias n -> Some n | _ -> None) flags
7411         with Not_found -> name in
7412       pr "  if (";
7413       pr "STRCASEEQ (cmd, \"%s\")" name;
7414       if name <> name2 then
7415         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7416       if name <> alias then
7417         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7418       pr ")\n";
7419       pr "    return run_%s (cmd, argc, argv);\n" name;
7420       pr "  else\n";
7421   ) all_functions;
7422   pr "    {\n";
7423   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7424   pr "      if (command_num == 1)\n";
7425   pr "        extended_help_message ();\n";
7426   pr "      return -1;\n";
7427   pr "    }\n";
7428   pr "  return 0;\n";
7429   pr "}\n";
7430   pr "\n"
7431
7432 (* Readline completion for guestfish. *)
7433 and generate_fish_completion () =
7434   generate_header CStyle GPLv2plus;
7435
7436   let all_functions =
7437     List.filter (
7438       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7439     ) all_functions in
7440
7441   pr "\
7442 #include <config.h>
7443
7444 #include <stdio.h>
7445 #include <stdlib.h>
7446 #include <string.h>
7447
7448 #ifdef HAVE_LIBREADLINE
7449 #include <readline/readline.h>
7450 #endif
7451
7452 #include \"fish.h\"
7453
7454 #ifdef HAVE_LIBREADLINE
7455
7456 static const char *const commands[] = {
7457   BUILTIN_COMMANDS_FOR_COMPLETION,
7458 ";
7459
7460   (* Get the commands, including the aliases.  They don't need to be
7461    * sorted - the generator() function just does a dumb linear search.
7462    *)
7463   let commands =
7464     List.map (
7465       fun (name, _, _, flags, _, _, _) ->
7466         let name2 = replace_char name '_' '-' in
7467         let alias =
7468           try find_map (function FishAlias n -> Some n | _ -> None) flags
7469           with Not_found -> name in
7470
7471         if name <> alias then [name2; alias] else [name2]
7472     ) all_functions in
7473   let commands = List.flatten commands in
7474
7475   List.iter (pr "  \"%s\",\n") commands;
7476
7477   pr "  NULL
7478 };
7479
7480 static char *
7481 generator (const char *text, int state)
7482 {
7483   static int index, len;
7484   const char *name;
7485
7486   if (!state) {
7487     index = 0;
7488     len = strlen (text);
7489   }
7490
7491   rl_attempted_completion_over = 1;
7492
7493   while ((name = commands[index]) != NULL) {
7494     index++;
7495     if (STRCASEEQLEN (name, text, len))
7496       return strdup (name);
7497   }
7498
7499   return NULL;
7500 }
7501
7502 #endif /* HAVE_LIBREADLINE */
7503
7504 #ifdef HAVE_RL_COMPLETION_MATCHES
7505 #define RL_COMPLETION_MATCHES rl_completion_matches
7506 #else
7507 #ifdef HAVE_COMPLETION_MATCHES
7508 #define RL_COMPLETION_MATCHES completion_matches
7509 #endif
7510 #endif /* else just fail if we don't have either symbol */
7511
7512 char **
7513 do_completion (const char *text, int start, int end)
7514 {
7515   char **matches = NULL;
7516
7517 #ifdef HAVE_LIBREADLINE
7518   rl_completion_append_character = ' ';
7519
7520   if (start == 0)
7521     matches = RL_COMPLETION_MATCHES (text, generator);
7522   else if (complete_dest_paths)
7523     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7524 #endif
7525
7526   return matches;
7527 }
7528 ";
7529
7530 (* Generate the POD documentation for guestfish. *)
7531 and generate_fish_actions_pod () =
7532   let all_functions_sorted =
7533     List.filter (
7534       fun (_, _, _, flags, _, _, _) ->
7535         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7536     ) all_functions_sorted in
7537
7538   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7539
7540   List.iter (
7541     fun (name, style, _, flags, _, _, longdesc) ->
7542       let longdesc =
7543         Str.global_substitute rex (
7544           fun s ->
7545             let sub =
7546               try Str.matched_group 1 s
7547               with Not_found ->
7548                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7549             "C<" ^ replace_char sub '_' '-' ^ ">"
7550         ) longdesc in
7551       let name = replace_char name '_' '-' in
7552       let alias =
7553         try find_map (function FishAlias n -> Some n | _ -> None) flags
7554         with Not_found -> name in
7555
7556       pr "=head2 %s" name;
7557       if name <> alias then
7558         pr " | %s" alias;
7559       pr "\n";
7560       pr "\n";
7561       pr " %s" name;
7562       List.iter (
7563         function
7564         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7565         | OptString n -> pr " %s" n
7566         | StringList n | DeviceList n -> pr " '%s ...'" n
7567         | Bool _ -> pr " true|false"
7568         | Int n -> pr " %s" n
7569         | Int64 n -> pr " %s" n
7570         | FileIn n | FileOut n -> pr " (%s|-)" n
7571       ) (snd style);
7572       pr "\n";
7573       pr "\n";
7574       pr "%s\n\n" longdesc;
7575
7576       if List.exists (function FileIn _ | FileOut _ -> true
7577                       | _ -> false) (snd style) then
7578         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7579
7580       if List.mem ProtocolLimitWarning flags then
7581         pr "%s\n\n" protocol_limit_warning;
7582
7583       if List.mem DangerWillRobinson flags then
7584         pr "%s\n\n" danger_will_robinson;
7585
7586       match deprecation_notice flags with
7587       | None -> ()
7588       | Some txt -> pr "%s\n\n" txt
7589   ) all_functions_sorted
7590
7591 (* Generate a C function prototype. *)
7592 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7593     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7594     ?(prefix = "")
7595     ?handle name style =
7596   if extern then pr "extern ";
7597   if static then pr "static ";
7598   (match fst style with
7599    | RErr -> pr "int "
7600    | RInt _ -> pr "int "
7601    | RInt64 _ -> pr "int64_t "
7602    | RBool _ -> pr "int "
7603    | RConstString _ | RConstOptString _ -> pr "const char *"
7604    | RString _ | RBufferOut _ -> pr "char *"
7605    | RStringList _ | RHashtable _ -> pr "char **"
7606    | RStruct (_, typ) ->
7607        if not in_daemon then pr "struct guestfs_%s *" typ
7608        else pr "guestfs_int_%s *" typ
7609    | RStructList (_, typ) ->
7610        if not in_daemon then pr "struct guestfs_%s_list *" typ
7611        else pr "guestfs_int_%s_list *" typ
7612   );
7613   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7614   pr "%s%s (" prefix name;
7615   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7616     pr "void"
7617   else (
7618     let comma = ref false in
7619     (match handle with
7620      | None -> ()
7621      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7622     );
7623     let next () =
7624       if !comma then (
7625         if single_line then pr ", " else pr ",\n\t\t"
7626       );
7627       comma := true
7628     in
7629     List.iter (
7630       function
7631       | Pathname n
7632       | Device n | Dev_or_Path n
7633       | String n
7634       | OptString n ->
7635           next ();
7636           pr "const char *%s" n
7637       | StringList n | DeviceList n ->
7638           next ();
7639           pr "char *const *%s" n
7640       | Bool n -> next (); pr "int %s" n
7641       | Int n -> next (); pr "int %s" n
7642       | Int64 n -> next (); pr "int64_t %s" n
7643       | FileIn n
7644       | FileOut n ->
7645           if not in_daemon then (next (); pr "const char *%s" n)
7646     ) (snd style);
7647     if is_RBufferOut then (next (); pr "size_t *size_r");
7648   );
7649   pr ")";
7650   if semicolon then pr ";";
7651   if newline then pr "\n"
7652
7653 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7654 and generate_c_call_args ?handle ?(decl = false) style =
7655   pr "(";
7656   let comma = ref false in
7657   let next () =
7658     if !comma then pr ", ";
7659     comma := true
7660   in
7661   (match handle with
7662    | None -> ()
7663    | Some handle -> pr "%s" handle; comma := true
7664   );
7665   List.iter (
7666     fun arg ->
7667       next ();
7668       pr "%s" (name_of_argt arg)
7669   ) (snd style);
7670   (* For RBufferOut calls, add implicit &size parameter. *)
7671   if not decl then (
7672     match fst style with
7673     | RBufferOut _ ->
7674         next ();
7675         pr "&size"
7676     | _ -> ()
7677   );
7678   pr ")"
7679
7680 (* Generate the OCaml bindings interface. *)
7681 and generate_ocaml_mli () =
7682   generate_header OCamlStyle LGPLv2plus;
7683
7684   pr "\
7685 (** For API documentation you should refer to the C API
7686     in the guestfs(3) manual page.  The OCaml API uses almost
7687     exactly the same calls. *)
7688
7689 type t
7690 (** A [guestfs_h] handle. *)
7691
7692 exception Error of string
7693 (** This exception is raised when there is an error. *)
7694
7695 exception Handle_closed of string
7696 (** This exception is raised if you use a {!Guestfs.t} handle
7697     after calling {!close} on it.  The string is the name of
7698     the function. *)
7699
7700 val create : unit -> t
7701 (** Create a {!Guestfs.t} handle. *)
7702
7703 val close : t -> unit
7704 (** Close the {!Guestfs.t} handle and free up all resources used
7705     by it immediately.
7706
7707     Handles are closed by the garbage collector when they become
7708     unreferenced, but callers can call this in order to provide
7709     predictable cleanup. *)
7710
7711 ";
7712   generate_ocaml_structure_decls ();
7713
7714   (* The actions. *)
7715   List.iter (
7716     fun (name, style, _, _, _, shortdesc, _) ->
7717       generate_ocaml_prototype name style;
7718       pr "(** %s *)\n" shortdesc;
7719       pr "\n"
7720   ) all_functions_sorted
7721
7722 (* Generate the OCaml bindings implementation. *)
7723 and generate_ocaml_ml () =
7724   generate_header OCamlStyle LGPLv2plus;
7725
7726   pr "\
7727 type t
7728
7729 exception Error of string
7730 exception Handle_closed of string
7731
7732 external create : unit -> t = \"ocaml_guestfs_create\"
7733 external close : t -> unit = \"ocaml_guestfs_close\"
7734
7735 (* Give the exceptions names, so they can be raised from the C code. *)
7736 let () =
7737   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7738   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7739
7740 ";
7741
7742   generate_ocaml_structure_decls ();
7743
7744   (* The actions. *)
7745   List.iter (
7746     fun (name, style, _, _, _, shortdesc, _) ->
7747       generate_ocaml_prototype ~is_external:true name style;
7748   ) all_functions_sorted
7749
7750 (* Generate the OCaml bindings C implementation. *)
7751 and generate_ocaml_c () =
7752   generate_header CStyle LGPLv2plus;
7753
7754   pr "\
7755 #include <stdio.h>
7756 #include <stdlib.h>
7757 #include <string.h>
7758
7759 #include <caml/config.h>
7760 #include <caml/alloc.h>
7761 #include <caml/callback.h>
7762 #include <caml/fail.h>
7763 #include <caml/memory.h>
7764 #include <caml/mlvalues.h>
7765 #include <caml/signals.h>
7766
7767 #include <guestfs.h>
7768
7769 #include \"guestfs_c.h\"
7770
7771 /* Copy a hashtable of string pairs into an assoc-list.  We return
7772  * the list in reverse order, but hashtables aren't supposed to be
7773  * ordered anyway.
7774  */
7775 static CAMLprim value
7776 copy_table (char * const * argv)
7777 {
7778   CAMLparam0 ();
7779   CAMLlocal5 (rv, pairv, kv, vv, cons);
7780   int i;
7781
7782   rv = Val_int (0);
7783   for (i = 0; argv[i] != NULL; i += 2) {
7784     kv = caml_copy_string (argv[i]);
7785     vv = caml_copy_string (argv[i+1]);
7786     pairv = caml_alloc (2, 0);
7787     Store_field (pairv, 0, kv);
7788     Store_field (pairv, 1, vv);
7789     cons = caml_alloc (2, 0);
7790     Store_field (cons, 1, rv);
7791     rv = cons;
7792     Store_field (cons, 0, pairv);
7793   }
7794
7795   CAMLreturn (rv);
7796 }
7797
7798 ";
7799
7800   (* Struct copy functions. *)
7801
7802   let emit_ocaml_copy_list_function typ =
7803     pr "static CAMLprim value\n";
7804     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7805     pr "{\n";
7806     pr "  CAMLparam0 ();\n";
7807     pr "  CAMLlocal2 (rv, v);\n";
7808     pr "  unsigned int i;\n";
7809     pr "\n";
7810     pr "  if (%ss->len == 0)\n" typ;
7811     pr "    CAMLreturn (Atom (0));\n";
7812     pr "  else {\n";
7813     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7814     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7815     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7816     pr "      caml_modify (&Field (rv, i), v);\n";
7817     pr "    }\n";
7818     pr "    CAMLreturn (rv);\n";
7819     pr "  }\n";
7820     pr "}\n";
7821     pr "\n";
7822   in
7823
7824   List.iter (
7825     fun (typ, cols) ->
7826       let has_optpercent_col =
7827         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7828
7829       pr "static CAMLprim value\n";
7830       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7831       pr "{\n";
7832       pr "  CAMLparam0 ();\n";
7833       if has_optpercent_col then
7834         pr "  CAMLlocal3 (rv, v, v2);\n"
7835       else
7836         pr "  CAMLlocal2 (rv, v);\n";
7837       pr "\n";
7838       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7839       iteri (
7840         fun i col ->
7841           (match col with
7842            | name, FString ->
7843                pr "  v = caml_copy_string (%s->%s);\n" typ name
7844            | name, FBuffer ->
7845                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7846                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7847                  typ name typ name
7848            | name, FUUID ->
7849                pr "  v = caml_alloc_string (32);\n";
7850                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7851            | name, (FBytes|FInt64|FUInt64) ->
7852                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7853            | name, (FInt32|FUInt32) ->
7854                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7855            | name, FOptPercent ->
7856                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7857                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7858                pr "    v = caml_alloc (1, 0);\n";
7859                pr "    Store_field (v, 0, v2);\n";
7860                pr "  } else /* None */\n";
7861                pr "    v = Val_int (0);\n";
7862            | name, FChar ->
7863                pr "  v = Val_int (%s->%s);\n" typ name
7864           );
7865           pr "  Store_field (rv, %d, v);\n" i
7866       ) cols;
7867       pr "  CAMLreturn (rv);\n";
7868       pr "}\n";
7869       pr "\n";
7870   ) structs;
7871
7872   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7873   List.iter (
7874     function
7875     | typ, (RStructListOnly | RStructAndList) ->
7876         (* generate the function for typ *)
7877         emit_ocaml_copy_list_function typ
7878     | typ, _ -> () (* empty *)
7879   ) (rstructs_used_by all_functions);
7880
7881   (* The wrappers. *)
7882   List.iter (
7883     fun (name, style, _, _, _, _, _) ->
7884       pr "/* Automatically generated wrapper for function\n";
7885       pr " * ";
7886       generate_ocaml_prototype name style;
7887       pr " */\n";
7888       pr "\n";
7889
7890       let params =
7891         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7892
7893       let needs_extra_vs =
7894         match fst style with RConstOptString _ -> true | _ -> false in
7895
7896       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7897       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7898       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7899       pr "\n";
7900
7901       pr "CAMLprim value\n";
7902       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7903       List.iter (pr ", value %s") (List.tl params);
7904       pr ")\n";
7905       pr "{\n";
7906
7907       (match params with
7908        | [p1; p2; p3; p4; p5] ->
7909            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7910        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7911            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7912            pr "  CAMLxparam%d (%s);\n"
7913              (List.length rest) (String.concat ", " rest)
7914        | ps ->
7915            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7916       );
7917       if not needs_extra_vs then
7918         pr "  CAMLlocal1 (rv);\n"
7919       else
7920         pr "  CAMLlocal3 (rv, v, v2);\n";
7921       pr "\n";
7922
7923       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7924       pr "  if (g == NULL)\n";
7925       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7926       pr "\n";
7927
7928       List.iter (
7929         function
7930         | Pathname n
7931         | Device n | Dev_or_Path n
7932         | String n
7933         | FileIn n
7934         | FileOut n ->
7935             pr "  const char *%s = String_val (%sv);\n" n n
7936         | OptString n ->
7937             pr "  const char *%s =\n" n;
7938             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7939               n n
7940         | StringList n | DeviceList n ->
7941             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7942         | Bool n ->
7943             pr "  int %s = Bool_val (%sv);\n" n n
7944         | Int n ->
7945             pr "  int %s = Int_val (%sv);\n" n n
7946         | Int64 n ->
7947             pr "  int64_t %s = Int64_val (%sv);\n" n n
7948       ) (snd style);
7949       let error_code =
7950         match fst style with
7951         | RErr -> pr "  int r;\n"; "-1"
7952         | RInt _ -> pr "  int r;\n"; "-1"
7953         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7954         | RBool _ -> pr "  int r;\n"; "-1"
7955         | RConstString _ | RConstOptString _ ->
7956             pr "  const char *r;\n"; "NULL"
7957         | RString _ -> pr "  char *r;\n"; "NULL"
7958         | RStringList _ ->
7959             pr "  int i;\n";
7960             pr "  char **r;\n";
7961             "NULL"
7962         | RStruct (_, typ) ->
7963             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7964         | RStructList (_, typ) ->
7965             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7966         | RHashtable _ ->
7967             pr "  int i;\n";
7968             pr "  char **r;\n";
7969             "NULL"
7970         | RBufferOut _ ->
7971             pr "  char *r;\n";
7972             pr "  size_t size;\n";
7973             "NULL" in
7974       pr "\n";
7975
7976       pr "  caml_enter_blocking_section ();\n";
7977       pr "  r = guestfs_%s " name;
7978       generate_c_call_args ~handle:"g" style;
7979       pr ";\n";
7980       pr "  caml_leave_blocking_section ();\n";
7981
7982       List.iter (
7983         function
7984         | StringList n | DeviceList n ->
7985             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7986         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7987         | Bool _ | Int _ | Int64 _
7988         | FileIn _ | FileOut _ -> ()
7989       ) (snd style);
7990
7991       pr "  if (r == %s)\n" error_code;
7992       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7993       pr "\n";
7994
7995       (match fst style with
7996        | RErr -> pr "  rv = Val_unit;\n"
7997        | RInt _ -> pr "  rv = Val_int (r);\n"
7998        | RInt64 _ ->
7999            pr "  rv = caml_copy_int64 (r);\n"
8000        | RBool _ -> pr "  rv = Val_bool (r);\n"
8001        | RConstString _ ->
8002            pr "  rv = caml_copy_string (r);\n"
8003        | RConstOptString _ ->
8004            pr "  if (r) { /* Some string */\n";
8005            pr "    v = caml_alloc (1, 0);\n";
8006            pr "    v2 = caml_copy_string (r);\n";
8007            pr "    Store_field (v, 0, v2);\n";
8008            pr "  } else /* None */\n";
8009            pr "    v = Val_int (0);\n";
8010        | RString _ ->
8011            pr "  rv = caml_copy_string (r);\n";
8012            pr "  free (r);\n"
8013        | RStringList _ ->
8014            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8015            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8016            pr "  free (r);\n"
8017        | RStruct (_, typ) ->
8018            pr "  rv = copy_%s (r);\n" typ;
8019            pr "  guestfs_free_%s (r);\n" typ;
8020        | RStructList (_, typ) ->
8021            pr "  rv = copy_%s_list (r);\n" typ;
8022            pr "  guestfs_free_%s_list (r);\n" typ;
8023        | RHashtable _ ->
8024            pr "  rv = copy_table (r);\n";
8025            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8026            pr "  free (r);\n";
8027        | RBufferOut _ ->
8028            pr "  rv = caml_alloc_string (size);\n";
8029            pr "  memcpy (String_val (rv), r, size);\n";
8030       );
8031
8032       pr "  CAMLreturn (rv);\n";
8033       pr "}\n";
8034       pr "\n";
8035
8036       if List.length params > 5 then (
8037         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8038         pr "CAMLprim value ";
8039         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8040         pr "CAMLprim value\n";
8041         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8042         pr "{\n";
8043         pr "  return ocaml_guestfs_%s (argv[0]" name;
8044         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8045         pr ");\n";
8046         pr "}\n";
8047         pr "\n"
8048       )
8049   ) all_functions_sorted
8050
8051 and generate_ocaml_structure_decls () =
8052   List.iter (
8053     fun (typ, cols) ->
8054       pr "type %s = {\n" typ;
8055       List.iter (
8056         function
8057         | name, FString -> pr "  %s : string;\n" name
8058         | name, FBuffer -> pr "  %s : string;\n" name
8059         | name, FUUID -> pr "  %s : string;\n" name
8060         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8061         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8062         | name, FChar -> pr "  %s : char;\n" name
8063         | name, FOptPercent -> pr "  %s : float option;\n" name
8064       ) cols;
8065       pr "}\n";
8066       pr "\n"
8067   ) structs
8068
8069 and generate_ocaml_prototype ?(is_external = false) name style =
8070   if is_external then pr "external " else pr "val ";
8071   pr "%s : t -> " name;
8072   List.iter (
8073     function
8074     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8075     | OptString _ -> pr "string option -> "
8076     | StringList _ | DeviceList _ -> pr "string array -> "
8077     | Bool _ -> pr "bool -> "
8078     | Int _ -> pr "int -> "
8079     | Int64 _ -> pr "int64 -> "
8080   ) (snd style);
8081   (match fst style with
8082    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8083    | RInt _ -> pr "int"
8084    | RInt64 _ -> pr "int64"
8085    | RBool _ -> pr "bool"
8086    | RConstString _ -> pr "string"
8087    | RConstOptString _ -> pr "string option"
8088    | RString _ | RBufferOut _ -> pr "string"
8089    | RStringList _ -> pr "string array"
8090    | RStruct (_, typ) -> pr "%s" typ
8091    | RStructList (_, typ) -> pr "%s array" typ
8092    | RHashtable _ -> pr "(string * string) list"
8093   );
8094   if is_external then (
8095     pr " = ";
8096     if List.length (snd style) + 1 > 5 then
8097       pr "\"ocaml_guestfs_%s_byte\" " name;
8098     pr "\"ocaml_guestfs_%s\"" name
8099   );
8100   pr "\n"
8101
8102 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8103 and generate_perl_xs () =
8104   generate_header CStyle LGPLv2plus;
8105
8106   pr "\
8107 #include \"EXTERN.h\"
8108 #include \"perl.h\"
8109 #include \"XSUB.h\"
8110
8111 #include <guestfs.h>
8112
8113 #ifndef PRId64
8114 #define PRId64 \"lld\"
8115 #endif
8116
8117 static SV *
8118 my_newSVll(long long val) {
8119 #ifdef USE_64_BIT_ALL
8120   return newSViv(val);
8121 #else
8122   char buf[100];
8123   int len;
8124   len = snprintf(buf, 100, \"%%\" PRId64, val);
8125   return newSVpv(buf, len);
8126 #endif
8127 }
8128
8129 #ifndef PRIu64
8130 #define PRIu64 \"llu\"
8131 #endif
8132
8133 static SV *
8134 my_newSVull(unsigned long long val) {
8135 #ifdef USE_64_BIT_ALL
8136   return newSVuv(val);
8137 #else
8138   char buf[100];
8139   int len;
8140   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8141   return newSVpv(buf, len);
8142 #endif
8143 }
8144
8145 /* http://www.perlmonks.org/?node_id=680842 */
8146 static char **
8147 XS_unpack_charPtrPtr (SV *arg) {
8148   char **ret;
8149   AV *av;
8150   I32 i;
8151
8152   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8153     croak (\"array reference expected\");
8154
8155   av = (AV *)SvRV (arg);
8156   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8157   if (!ret)
8158     croak (\"malloc failed\");
8159
8160   for (i = 0; i <= av_len (av); i++) {
8161     SV **elem = av_fetch (av, i, 0);
8162
8163     if (!elem || !*elem)
8164       croak (\"missing element in list\");
8165
8166     ret[i] = SvPV_nolen (*elem);
8167   }
8168
8169   ret[i] = NULL;
8170
8171   return ret;
8172 }
8173
8174 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8175
8176 PROTOTYPES: ENABLE
8177
8178 guestfs_h *
8179 _create ()
8180    CODE:
8181       RETVAL = guestfs_create ();
8182       if (!RETVAL)
8183         croak (\"could not create guestfs handle\");
8184       guestfs_set_error_handler (RETVAL, NULL, NULL);
8185  OUTPUT:
8186       RETVAL
8187
8188 void
8189 DESTROY (g)
8190       guestfs_h *g;
8191  PPCODE:
8192       guestfs_close (g);
8193
8194 ";
8195
8196   List.iter (
8197     fun (name, style, _, _, _, _, _) ->
8198       (match fst style with
8199        | RErr -> pr "void\n"
8200        | RInt _ -> pr "SV *\n"
8201        | RInt64 _ -> pr "SV *\n"
8202        | RBool _ -> pr "SV *\n"
8203        | RConstString _ -> pr "SV *\n"
8204        | RConstOptString _ -> pr "SV *\n"
8205        | RString _ -> pr "SV *\n"
8206        | RBufferOut _ -> pr "SV *\n"
8207        | RStringList _
8208        | RStruct _ | RStructList _
8209        | RHashtable _ ->
8210            pr "void\n" (* all lists returned implictly on the stack *)
8211       );
8212       (* Call and arguments. *)
8213       pr "%s " name;
8214       generate_c_call_args ~handle:"g" ~decl:true style;
8215       pr "\n";
8216       pr "      guestfs_h *g;\n";
8217       iteri (
8218         fun i ->
8219           function
8220           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8221               pr "      char *%s;\n" n
8222           | OptString n ->
8223               (* http://www.perlmonks.org/?node_id=554277
8224                * Note that the implicit handle argument means we have
8225                * to add 1 to the ST(x) operator.
8226                *)
8227               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8228           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8229           | Bool n -> pr "      int %s;\n" n
8230           | Int n -> pr "      int %s;\n" n
8231           | Int64 n -> pr "      int64_t %s;\n" n
8232       ) (snd style);
8233
8234       let do_cleanups () =
8235         List.iter (
8236           function
8237           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8238           | Bool _ | Int _ | Int64 _
8239           | FileIn _ | FileOut _ -> ()
8240           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8241         ) (snd style)
8242       in
8243
8244       (* Code. *)
8245       (match fst style with
8246        | RErr ->
8247            pr "PREINIT:\n";
8248            pr "      int r;\n";
8249            pr " PPCODE:\n";
8250            pr "      r = guestfs_%s " name;
8251            generate_c_call_args ~handle:"g" style;
8252            pr ";\n";
8253            do_cleanups ();
8254            pr "      if (r == -1)\n";
8255            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8256        | RInt n
8257        | RBool n ->
8258            pr "PREINIT:\n";
8259            pr "      int %s;\n" n;
8260            pr "   CODE:\n";
8261            pr "      %s = guestfs_%s " n name;
8262            generate_c_call_args ~handle:"g" style;
8263            pr ";\n";
8264            do_cleanups ();
8265            pr "      if (%s == -1)\n" n;
8266            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8267            pr "      RETVAL = newSViv (%s);\n" n;
8268            pr " OUTPUT:\n";
8269            pr "      RETVAL\n"
8270        | RInt64 n ->
8271            pr "PREINIT:\n";
8272            pr "      int64_t %s;\n" n;
8273            pr "   CODE:\n";
8274            pr "      %s = guestfs_%s " n name;
8275            generate_c_call_args ~handle:"g" style;
8276            pr ";\n";
8277            do_cleanups ();
8278            pr "      if (%s == -1)\n" n;
8279            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8280            pr "      RETVAL = my_newSVll (%s);\n" n;
8281            pr " OUTPUT:\n";
8282            pr "      RETVAL\n"
8283        | RConstString n ->
8284            pr "PREINIT:\n";
8285            pr "      const char *%s;\n" n;
8286            pr "   CODE:\n";
8287            pr "      %s = guestfs_%s " n name;
8288            generate_c_call_args ~handle:"g" style;
8289            pr ";\n";
8290            do_cleanups ();
8291            pr "      if (%s == NULL)\n" n;
8292            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8293            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8294            pr " OUTPUT:\n";
8295            pr "      RETVAL\n"
8296        | RConstOptString n ->
8297            pr "PREINIT:\n";
8298            pr "      const char *%s;\n" n;
8299            pr "   CODE:\n";
8300            pr "      %s = guestfs_%s " n name;
8301            generate_c_call_args ~handle:"g" style;
8302            pr ";\n";
8303            do_cleanups ();
8304            pr "      if (%s == NULL)\n" n;
8305            pr "        RETVAL = &PL_sv_undef;\n";
8306            pr "      else\n";
8307            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8308            pr " OUTPUT:\n";
8309            pr "      RETVAL\n"
8310        | RString n ->
8311            pr "PREINIT:\n";
8312            pr "      char *%s;\n" n;
8313            pr "   CODE:\n";
8314            pr "      %s = guestfs_%s " n name;
8315            generate_c_call_args ~handle:"g" style;
8316            pr ";\n";
8317            do_cleanups ();
8318            pr "      if (%s == NULL)\n" n;
8319            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8320            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8321            pr "      free (%s);\n" n;
8322            pr " OUTPUT:\n";
8323            pr "      RETVAL\n"
8324        | RStringList n | RHashtable n ->
8325            pr "PREINIT:\n";
8326            pr "      char **%s;\n" n;
8327            pr "      int i, n;\n";
8328            pr " PPCODE:\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 "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8336            pr "      EXTEND (SP, n);\n";
8337            pr "      for (i = 0; i < n; ++i) {\n";
8338            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8339            pr "        free (%s[i]);\n" n;
8340            pr "      }\n";
8341            pr "      free (%s);\n" n;
8342        | RStruct (n, typ) ->
8343            let cols = cols_of_struct typ in
8344            generate_perl_struct_code typ cols name style n do_cleanups
8345        | RStructList (n, typ) ->
8346            let cols = cols_of_struct typ in
8347            generate_perl_struct_list_code typ cols name style n do_cleanups
8348        | RBufferOut n ->
8349            pr "PREINIT:\n";
8350            pr "      char *%s;\n" n;
8351            pr "      size_t size;\n";
8352            pr "   CODE:\n";
8353            pr "      %s = guestfs_%s " n name;
8354            generate_c_call_args ~handle:"g" style;
8355            pr ";\n";
8356            do_cleanups ();
8357            pr "      if (%s == NULL)\n" n;
8358            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8359            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8360            pr "      free (%s);\n" n;
8361            pr " OUTPUT:\n";
8362            pr "      RETVAL\n"
8363       );
8364
8365       pr "\n"
8366   ) all_functions
8367
8368 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8369   pr "PREINIT:\n";
8370   pr "      struct guestfs_%s_list *%s;\n" typ n;
8371   pr "      int i;\n";
8372   pr "      HV *hv;\n";
8373   pr " PPCODE:\n";
8374   pr "      %s = guestfs_%s " n name;
8375   generate_c_call_args ~handle:"g" style;
8376   pr ";\n";
8377   do_cleanups ();
8378   pr "      if (%s == NULL)\n" n;
8379   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8380   pr "      EXTEND (SP, %s->len);\n" n;
8381   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8382   pr "        hv = newHV ();\n";
8383   List.iter (
8384     function
8385     | name, FString ->
8386         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8387           name (String.length name) n name
8388     | name, FUUID ->
8389         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8390           name (String.length name) n name
8391     | name, FBuffer ->
8392         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8393           name (String.length name) n name n name
8394     | name, (FBytes|FUInt64) ->
8395         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8396           name (String.length name) n name
8397     | name, FInt64 ->
8398         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8399           name (String.length name) n name
8400     | name, (FInt32|FUInt32) ->
8401         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8402           name (String.length name) n name
8403     | name, FChar ->
8404         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8405           name (String.length name) n name
8406     | name, FOptPercent ->
8407         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8408           name (String.length name) n name
8409   ) cols;
8410   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8411   pr "      }\n";
8412   pr "      guestfs_free_%s_list (%s);\n" typ n
8413
8414 and generate_perl_struct_code typ cols name style n do_cleanups =
8415   pr "PREINIT:\n";
8416   pr "      struct guestfs_%s *%s;\n" typ n;
8417   pr " PPCODE:\n";
8418   pr "      %s = guestfs_%s " n name;
8419   generate_c_call_args ~handle:"g" style;
8420   pr ";\n";
8421   do_cleanups ();
8422   pr "      if (%s == NULL)\n" n;
8423   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8424   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8425   List.iter (
8426     fun ((name, _) as col) ->
8427       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8428
8429       match col with
8430       | name, FString ->
8431           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8432             n name
8433       | name, FBuffer ->
8434           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8435             n name n name
8436       | name, FUUID ->
8437           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8438             n name
8439       | name, (FBytes|FUInt64) ->
8440           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8441             n name
8442       | name, FInt64 ->
8443           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8444             n name
8445       | name, (FInt32|FUInt32) ->
8446           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8447             n name
8448       | name, FChar ->
8449           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8450             n name
8451       | name, FOptPercent ->
8452           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8453             n name
8454   ) cols;
8455   pr "      free (%s);\n" n
8456
8457 (* Generate Sys/Guestfs.pm. *)
8458 and generate_perl_pm () =
8459   generate_header HashStyle LGPLv2plus;
8460
8461   pr "\
8462 =pod
8463
8464 =head1 NAME
8465
8466 Sys::Guestfs - Perl bindings for libguestfs
8467
8468 =head1 SYNOPSIS
8469
8470  use Sys::Guestfs;
8471
8472  my $h = Sys::Guestfs->new ();
8473  $h->add_drive ('guest.img');
8474  $h->launch ();
8475  $h->mount ('/dev/sda1', '/');
8476  $h->touch ('/hello');
8477  $h->sync ();
8478
8479 =head1 DESCRIPTION
8480
8481 The C<Sys::Guestfs> module provides a Perl XS binding to the
8482 libguestfs API for examining and modifying virtual machine
8483 disk images.
8484
8485 Amongst the things this is good for: making batch configuration
8486 changes to guests, getting disk used/free statistics (see also:
8487 virt-df), migrating between virtualization systems (see also:
8488 virt-p2v), performing partial backups, performing partial guest
8489 clones, cloning guests and changing registry/UUID/hostname info, and
8490 much else besides.
8491
8492 Libguestfs uses Linux kernel and qemu code, and can access any type of
8493 guest filesystem that Linux and qemu can, including but not limited
8494 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8495 schemes, qcow, qcow2, vmdk.
8496
8497 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8498 LVs, what filesystem is in each LV, etc.).  It can also run commands
8499 in the context of the guest.  Also you can access filesystems over
8500 FUSE.
8501
8502 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8503 functions for using libguestfs from Perl, including integration
8504 with libvirt.
8505
8506 =head1 ERRORS
8507
8508 All errors turn into calls to C<croak> (see L<Carp(3)>).
8509
8510 =head1 METHODS
8511
8512 =over 4
8513
8514 =cut
8515
8516 package Sys::Guestfs;
8517
8518 use strict;
8519 use warnings;
8520
8521 require XSLoader;
8522 XSLoader::load ('Sys::Guestfs');
8523
8524 =item $h = Sys::Guestfs->new ();
8525
8526 Create a new guestfs handle.
8527
8528 =cut
8529
8530 sub new {
8531   my $proto = shift;
8532   my $class = ref ($proto) || $proto;
8533
8534   my $self = Sys::Guestfs::_create ();
8535   bless $self, $class;
8536   return $self;
8537 }
8538
8539 ";
8540
8541   (* Actions.  We only need to print documentation for these as
8542    * they are pulled in from the XS code automatically.
8543    *)
8544   List.iter (
8545     fun (name, style, _, flags, _, _, longdesc) ->
8546       if not (List.mem NotInDocs flags) then (
8547         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8548         pr "=item ";
8549         generate_perl_prototype name style;
8550         pr "\n\n";
8551         pr "%s\n\n" longdesc;
8552         if List.mem ProtocolLimitWarning flags then
8553           pr "%s\n\n" protocol_limit_warning;
8554         if List.mem DangerWillRobinson flags then
8555           pr "%s\n\n" danger_will_robinson;
8556         match deprecation_notice flags with
8557         | None -> ()
8558         | Some txt -> pr "%s\n\n" txt
8559       )
8560   ) all_functions_sorted;
8561
8562   (* End of file. *)
8563   pr "\
8564 =cut
8565
8566 1;
8567
8568 =back
8569
8570 =head1 COPYRIGHT
8571
8572 Copyright (C) %s Red Hat Inc.
8573
8574 =head1 LICENSE
8575
8576 Please see the file COPYING.LIB for the full license.
8577
8578 =head1 SEE ALSO
8579
8580 L<guestfs(3)>,
8581 L<guestfish(1)>,
8582 L<http://libguestfs.org>,
8583 L<Sys::Guestfs::Lib(3)>.
8584
8585 =cut
8586 " copyright_years
8587
8588 and generate_perl_prototype name style =
8589   (match fst style with
8590    | RErr -> ()
8591    | RBool n
8592    | RInt n
8593    | RInt64 n
8594    | RConstString n
8595    | RConstOptString n
8596    | RString n
8597    | RBufferOut n -> pr "$%s = " n
8598    | RStruct (n,_)
8599    | RHashtable n -> pr "%%%s = " n
8600    | RStringList n
8601    | RStructList (n,_) -> pr "@%s = " n
8602   );
8603   pr "$h->%s (" name;
8604   let comma = ref false in
8605   List.iter (
8606     fun arg ->
8607       if !comma then pr ", ";
8608       comma := true;
8609       match arg with
8610       | Pathname n | Device n | Dev_or_Path n | String n
8611       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8612           pr "$%s" n
8613       | StringList n | DeviceList n ->
8614           pr "\\@%s" n
8615   ) (snd style);
8616   pr ");"
8617
8618 (* Generate Python C module. *)
8619 and generate_python_c () =
8620   generate_header CStyle LGPLv2plus;
8621
8622   pr "\
8623 #include <Python.h>
8624
8625 #include <stdio.h>
8626 #include <stdlib.h>
8627 #include <assert.h>
8628
8629 #include \"guestfs.h\"
8630
8631 typedef struct {
8632   PyObject_HEAD
8633   guestfs_h *g;
8634 } Pyguestfs_Object;
8635
8636 static guestfs_h *
8637 get_handle (PyObject *obj)
8638 {
8639   assert (obj);
8640   assert (obj != Py_None);
8641   return ((Pyguestfs_Object *) obj)->g;
8642 }
8643
8644 static PyObject *
8645 put_handle (guestfs_h *g)
8646 {
8647   assert (g);
8648   return
8649     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8650 }
8651
8652 /* This list should be freed (but not the strings) after use. */
8653 static char **
8654 get_string_list (PyObject *obj)
8655 {
8656   int i, len;
8657   char **r;
8658
8659   assert (obj);
8660
8661   if (!PyList_Check (obj)) {
8662     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8663     return NULL;
8664   }
8665
8666   len = PyList_Size (obj);
8667   r = malloc (sizeof (char *) * (len+1));
8668   if (r == NULL) {
8669     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8670     return NULL;
8671   }
8672
8673   for (i = 0; i < len; ++i)
8674     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8675   r[len] = NULL;
8676
8677   return r;
8678 }
8679
8680 static PyObject *
8681 put_string_list (char * const * const argv)
8682 {
8683   PyObject *list;
8684   int argc, i;
8685
8686   for (argc = 0; argv[argc] != NULL; ++argc)
8687     ;
8688
8689   list = PyList_New (argc);
8690   for (i = 0; i < argc; ++i)
8691     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8692
8693   return list;
8694 }
8695
8696 static PyObject *
8697 put_table (char * const * const argv)
8698 {
8699   PyObject *list, *item;
8700   int argc, i;
8701
8702   for (argc = 0; argv[argc] != NULL; ++argc)
8703     ;
8704
8705   list = PyList_New (argc >> 1);
8706   for (i = 0; i < argc; i += 2) {
8707     item = PyTuple_New (2);
8708     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8709     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8710     PyList_SetItem (list, i >> 1, item);
8711   }
8712
8713   return list;
8714 }
8715
8716 static void
8717 free_strings (char **argv)
8718 {
8719   int argc;
8720
8721   for (argc = 0; argv[argc] != NULL; ++argc)
8722     free (argv[argc]);
8723   free (argv);
8724 }
8725
8726 static PyObject *
8727 py_guestfs_create (PyObject *self, PyObject *args)
8728 {
8729   guestfs_h *g;
8730
8731   g = guestfs_create ();
8732   if (g == NULL) {
8733     PyErr_SetString (PyExc_RuntimeError,
8734                      \"guestfs.create: failed to allocate handle\");
8735     return NULL;
8736   }
8737   guestfs_set_error_handler (g, NULL, NULL);
8738   return put_handle (g);
8739 }
8740
8741 static PyObject *
8742 py_guestfs_close (PyObject *self, PyObject *args)
8743 {
8744   PyObject *py_g;
8745   guestfs_h *g;
8746
8747   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8748     return NULL;
8749   g = get_handle (py_g);
8750
8751   guestfs_close (g);
8752
8753   Py_INCREF (Py_None);
8754   return Py_None;
8755 }
8756
8757 ";
8758
8759   let emit_put_list_function typ =
8760     pr "static PyObject *\n";
8761     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8762     pr "{\n";
8763     pr "  PyObject *list;\n";
8764     pr "  int i;\n";
8765     pr "\n";
8766     pr "  list = PyList_New (%ss->len);\n" typ;
8767     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8768     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8769     pr "  return list;\n";
8770     pr "};\n";
8771     pr "\n"
8772   in
8773
8774   (* Structures, turned into Python dictionaries. *)
8775   List.iter (
8776     fun (typ, cols) ->
8777       pr "static PyObject *\n";
8778       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8779       pr "{\n";
8780       pr "  PyObject *dict;\n";
8781       pr "\n";
8782       pr "  dict = PyDict_New ();\n";
8783       List.iter (
8784         function
8785         | name, FString ->
8786             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8787             pr "                        PyString_FromString (%s->%s));\n"
8788               typ name
8789         | name, FBuffer ->
8790             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8791             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8792               typ name typ name
8793         | name, FUUID ->
8794             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8795             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8796               typ name
8797         | name, (FBytes|FUInt64) ->
8798             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8799             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8800               typ name
8801         | name, FInt64 ->
8802             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8803             pr "                        PyLong_FromLongLong (%s->%s));\n"
8804               typ name
8805         | name, FUInt32 ->
8806             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8807             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8808               typ name
8809         | name, FInt32 ->
8810             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8811             pr "                        PyLong_FromLong (%s->%s));\n"
8812               typ name
8813         | name, FOptPercent ->
8814             pr "  if (%s->%s >= 0)\n" typ name;
8815             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8816             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8817               typ name;
8818             pr "  else {\n";
8819             pr "    Py_INCREF (Py_None);\n";
8820             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8821             pr "  }\n"
8822         | name, FChar ->
8823             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8824             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8825       ) cols;
8826       pr "  return dict;\n";
8827       pr "};\n";
8828       pr "\n";
8829
8830   ) structs;
8831
8832   (* Emit a put_TYPE_list function definition only if that function is used. *)
8833   List.iter (
8834     function
8835     | typ, (RStructListOnly | RStructAndList) ->
8836         (* generate the function for typ *)
8837         emit_put_list_function typ
8838     | typ, _ -> () (* empty *)
8839   ) (rstructs_used_by all_functions);
8840
8841   (* Python wrapper functions. *)
8842   List.iter (
8843     fun (name, style, _, _, _, _, _) ->
8844       pr "static PyObject *\n";
8845       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8846       pr "{\n";
8847
8848       pr "  PyObject *py_g;\n";
8849       pr "  guestfs_h *g;\n";
8850       pr "  PyObject *py_r;\n";
8851
8852       let error_code =
8853         match fst style with
8854         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8855         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8856         | RConstString _ | RConstOptString _ ->
8857             pr "  const char *r;\n"; "NULL"
8858         | RString _ -> pr "  char *r;\n"; "NULL"
8859         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8860         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8861         | RStructList (_, typ) ->
8862             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8863         | RBufferOut _ ->
8864             pr "  char *r;\n";
8865             pr "  size_t size;\n";
8866             "NULL" in
8867
8868       List.iter (
8869         function
8870         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8871             pr "  const char *%s;\n" n
8872         | OptString n -> pr "  const char *%s;\n" n
8873         | StringList n | DeviceList n ->
8874             pr "  PyObject *py_%s;\n" n;
8875             pr "  char **%s;\n" n
8876         | Bool n -> pr "  int %s;\n" n
8877         | Int n -> pr "  int %s;\n" n
8878         | Int64 n -> pr "  long long %s;\n" n
8879       ) (snd style);
8880
8881       pr "\n";
8882
8883       (* Convert the parameters. *)
8884       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8885       List.iter (
8886         function
8887         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8888         | OptString _ -> pr "z"
8889         | StringList _ | DeviceList _ -> pr "O"
8890         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8891         | Int _ -> pr "i"
8892         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8893                              * emulate C's int/long/long long in Python?
8894                              *)
8895       ) (snd style);
8896       pr ":guestfs_%s\",\n" name;
8897       pr "                         &py_g";
8898       List.iter (
8899         function
8900         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8901         | OptString n -> pr ", &%s" n
8902         | StringList n | DeviceList n -> pr ", &py_%s" n
8903         | Bool n -> pr ", &%s" n
8904         | Int n -> pr ", &%s" n
8905         | Int64 n -> pr ", &%s" n
8906       ) (snd style);
8907
8908       pr "))\n";
8909       pr "    return NULL;\n";
8910
8911       pr "  g = get_handle (py_g);\n";
8912       List.iter (
8913         function
8914         | Pathname _ | Device _ | Dev_or_Path _ | String _
8915         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8916         | StringList n | DeviceList n ->
8917             pr "  %s = get_string_list (py_%s);\n" n n;
8918             pr "  if (!%s) return NULL;\n" n
8919       ) (snd style);
8920
8921       pr "\n";
8922
8923       pr "  r = guestfs_%s " name;
8924       generate_c_call_args ~handle:"g" style;
8925       pr ";\n";
8926
8927       List.iter (
8928         function
8929         | Pathname _ | Device _ | Dev_or_Path _ | String _
8930         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8931         | StringList n | DeviceList n ->
8932             pr "  free (%s);\n" n
8933       ) (snd style);
8934
8935       pr "  if (r == %s) {\n" error_code;
8936       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8937       pr "    return NULL;\n";
8938       pr "  }\n";
8939       pr "\n";
8940
8941       (match fst style with
8942        | RErr ->
8943            pr "  Py_INCREF (Py_None);\n";
8944            pr "  py_r = Py_None;\n"
8945        | RInt _
8946        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8947        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8948        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8949        | RConstOptString _ ->
8950            pr "  if (r)\n";
8951            pr "    py_r = PyString_FromString (r);\n";
8952            pr "  else {\n";
8953            pr "    Py_INCREF (Py_None);\n";
8954            pr "    py_r = Py_None;\n";
8955            pr "  }\n"
8956        | RString _ ->
8957            pr "  py_r = PyString_FromString (r);\n";
8958            pr "  free (r);\n"
8959        | RStringList _ ->
8960            pr "  py_r = put_string_list (r);\n";
8961            pr "  free_strings (r);\n"
8962        | RStruct (_, typ) ->
8963            pr "  py_r = put_%s (r);\n" typ;
8964            pr "  guestfs_free_%s (r);\n" typ
8965        | RStructList (_, typ) ->
8966            pr "  py_r = put_%s_list (r);\n" typ;
8967            pr "  guestfs_free_%s_list (r);\n" typ
8968        | RHashtable n ->
8969            pr "  py_r = put_table (r);\n";
8970            pr "  free_strings (r);\n"
8971        | RBufferOut _ ->
8972            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8973            pr "  free (r);\n"
8974       );
8975
8976       pr "  return py_r;\n";
8977       pr "}\n";
8978       pr "\n"
8979   ) all_functions;
8980
8981   (* Table of functions. *)
8982   pr "static PyMethodDef methods[] = {\n";
8983   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8984   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8985   List.iter (
8986     fun (name, _, _, _, _, _, _) ->
8987       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8988         name name
8989   ) all_functions;
8990   pr "  { NULL, NULL, 0, NULL }\n";
8991   pr "};\n";
8992   pr "\n";
8993
8994   (* Init function. *)
8995   pr "\
8996 void
8997 initlibguestfsmod (void)
8998 {
8999   static int initialized = 0;
9000
9001   if (initialized) return;
9002   Py_InitModule ((char *) \"libguestfsmod\", methods);
9003   initialized = 1;
9004 }
9005 "
9006
9007 (* Generate Python module. *)
9008 and generate_python_py () =
9009   generate_header HashStyle LGPLv2plus;
9010
9011   pr "\
9012 u\"\"\"Python bindings for libguestfs
9013
9014 import guestfs
9015 g = guestfs.GuestFS ()
9016 g.add_drive (\"guest.img\")
9017 g.launch ()
9018 parts = g.list_partitions ()
9019
9020 The guestfs module provides a Python binding to the libguestfs API
9021 for examining and modifying virtual machine disk images.
9022
9023 Amongst the things this is good for: making batch configuration
9024 changes to guests, getting disk used/free statistics (see also:
9025 virt-df), migrating between virtualization systems (see also:
9026 virt-p2v), performing partial backups, performing partial guest
9027 clones, cloning guests and changing registry/UUID/hostname info, and
9028 much else besides.
9029
9030 Libguestfs uses Linux kernel and qemu code, and can access any type of
9031 guest filesystem that Linux and qemu can, including but not limited
9032 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9033 schemes, qcow, qcow2, vmdk.
9034
9035 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9036 LVs, what filesystem is in each LV, etc.).  It can also run commands
9037 in the context of the guest.  Also you can access filesystems over
9038 FUSE.
9039
9040 Errors which happen while using the API are turned into Python
9041 RuntimeError exceptions.
9042
9043 To create a guestfs handle you usually have to perform the following
9044 sequence of calls:
9045
9046 # Create the handle, call add_drive at least once, and possibly
9047 # several times if the guest has multiple block devices:
9048 g = guestfs.GuestFS ()
9049 g.add_drive (\"guest.img\")
9050
9051 # Launch the qemu subprocess and wait for it to become ready:
9052 g.launch ()
9053
9054 # Now you can issue commands, for example:
9055 logvols = g.lvs ()
9056
9057 \"\"\"
9058
9059 import libguestfsmod
9060
9061 class GuestFS:
9062     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9063
9064     def __init__ (self):
9065         \"\"\"Create a new libguestfs handle.\"\"\"
9066         self._o = libguestfsmod.create ()
9067
9068     def __del__ (self):
9069         libguestfsmod.close (self._o)
9070
9071 ";
9072
9073   List.iter (
9074     fun (name, style, _, flags, _, _, longdesc) ->
9075       pr "    def %s " name;
9076       generate_py_call_args ~handle:"self" (snd style);
9077       pr ":\n";
9078
9079       if not (List.mem NotInDocs flags) then (
9080         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9081         let doc =
9082           match fst style with
9083           | RErr | RInt _ | RInt64 _ | RBool _
9084           | RConstOptString _ | RConstString _
9085           | RString _ | RBufferOut _ -> doc
9086           | RStringList _ ->
9087               doc ^ "\n\nThis function returns a list of strings."
9088           | RStruct (_, typ) ->
9089               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9090           | RStructList (_, typ) ->
9091               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9092           | RHashtable _ ->
9093               doc ^ "\n\nThis function returns a dictionary." in
9094         let doc =
9095           if List.mem ProtocolLimitWarning flags then
9096             doc ^ "\n\n" ^ protocol_limit_warning
9097           else doc in
9098         let doc =
9099           if List.mem DangerWillRobinson flags then
9100             doc ^ "\n\n" ^ danger_will_robinson
9101           else doc in
9102         let doc =
9103           match deprecation_notice flags with
9104           | None -> doc
9105           | Some txt -> doc ^ "\n\n" ^ txt in
9106         let doc = pod2text ~width:60 name doc in
9107         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9108         let doc = String.concat "\n        " doc in
9109         pr "        u\"\"\"%s\"\"\"\n" doc;
9110       );
9111       pr "        return libguestfsmod.%s " name;
9112       generate_py_call_args ~handle:"self._o" (snd style);
9113       pr "\n";
9114       pr "\n";
9115   ) all_functions
9116
9117 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9118 and generate_py_call_args ~handle args =
9119   pr "(%s" handle;
9120   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9121   pr ")"
9122
9123 (* Useful if you need the longdesc POD text as plain text.  Returns a
9124  * list of lines.
9125  *
9126  * Because this is very slow (the slowest part of autogeneration),
9127  * we memoize the results.
9128  *)
9129 and pod2text ~width name longdesc =
9130   let key = width, name, longdesc in
9131   try Hashtbl.find pod2text_memo key
9132   with Not_found ->
9133     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9134     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9135     close_out chan;
9136     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9137     let chan = open_process_in cmd in
9138     let lines = ref [] in
9139     let rec loop i =
9140       let line = input_line chan in
9141       if i = 1 then             (* discard the first line of output *)
9142         loop (i+1)
9143       else (
9144         let line = triml line in
9145         lines := line :: !lines;
9146         loop (i+1)
9147       ) in
9148     let lines = try loop 1 with End_of_file -> List.rev !lines in
9149     unlink filename;
9150     (match close_process_in chan with
9151      | WEXITED 0 -> ()
9152      | WEXITED i ->
9153          failwithf "pod2text: process exited with non-zero status (%d)" i
9154      | WSIGNALED i | WSTOPPED i ->
9155          failwithf "pod2text: process signalled or stopped by signal %d" i
9156     );
9157     Hashtbl.add pod2text_memo key lines;
9158     pod2text_memo_updated ();
9159     lines
9160
9161 (* Generate ruby bindings. *)
9162 and generate_ruby_c () =
9163   generate_header CStyle LGPLv2plus;
9164
9165   pr "\
9166 #include <stdio.h>
9167 #include <stdlib.h>
9168
9169 #include <ruby.h>
9170
9171 #include \"guestfs.h\"
9172
9173 #include \"extconf.h\"
9174
9175 /* For Ruby < 1.9 */
9176 #ifndef RARRAY_LEN
9177 #define RARRAY_LEN(r) (RARRAY((r))->len)
9178 #endif
9179
9180 static VALUE m_guestfs;                 /* guestfs module */
9181 static VALUE c_guestfs;                 /* guestfs_h handle */
9182 static VALUE e_Error;                   /* used for all errors */
9183
9184 static void ruby_guestfs_free (void *p)
9185 {
9186   if (!p) return;
9187   guestfs_close ((guestfs_h *) p);
9188 }
9189
9190 static VALUE ruby_guestfs_create (VALUE m)
9191 {
9192   guestfs_h *g;
9193
9194   g = guestfs_create ();
9195   if (!g)
9196     rb_raise (e_Error, \"failed to create guestfs handle\");
9197
9198   /* Don't print error messages to stderr by default. */
9199   guestfs_set_error_handler (g, NULL, NULL);
9200
9201   /* Wrap it, and make sure the close function is called when the
9202    * handle goes away.
9203    */
9204   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9205 }
9206
9207 static VALUE ruby_guestfs_close (VALUE gv)
9208 {
9209   guestfs_h *g;
9210   Data_Get_Struct (gv, guestfs_h, g);
9211
9212   ruby_guestfs_free (g);
9213   DATA_PTR (gv) = NULL;
9214
9215   return Qnil;
9216 }
9217
9218 ";
9219
9220   List.iter (
9221     fun (name, style, _, _, _, _, _) ->
9222       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9223       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9224       pr ")\n";
9225       pr "{\n";
9226       pr "  guestfs_h *g;\n";
9227       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9228       pr "  if (!g)\n";
9229       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9230         name;
9231       pr "\n";
9232
9233       List.iter (
9234         function
9235         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9236             pr "  Check_Type (%sv, T_STRING);\n" n;
9237             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9238             pr "  if (!%s)\n" n;
9239             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9240             pr "              \"%s\", \"%s\");\n" n name
9241         | OptString n ->
9242             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9243         | StringList n | DeviceList n ->
9244             pr "  char **%s;\n" n;
9245             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9246             pr "  {\n";
9247             pr "    int i, len;\n";
9248             pr "    len = RARRAY_LEN (%sv);\n" n;
9249             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9250               n;
9251             pr "    for (i = 0; i < len; ++i) {\n";
9252             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9253             pr "      %s[i] = StringValueCStr (v);\n" n;
9254             pr "    }\n";
9255             pr "    %s[len] = NULL;\n" n;
9256             pr "  }\n";
9257         | Bool n ->
9258             pr "  int %s = RTEST (%sv);\n" n n
9259         | Int n ->
9260             pr "  int %s = NUM2INT (%sv);\n" n n
9261         | Int64 n ->
9262             pr "  long long %s = NUM2LL (%sv);\n" n n
9263       ) (snd style);
9264       pr "\n";
9265
9266       let error_code =
9267         match fst style with
9268         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9269         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9270         | RConstString _ | RConstOptString _ ->
9271             pr "  const char *r;\n"; "NULL"
9272         | RString _ -> pr "  char *r;\n"; "NULL"
9273         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9274         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9275         | RStructList (_, typ) ->
9276             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9277         | RBufferOut _ ->
9278             pr "  char *r;\n";
9279             pr "  size_t size;\n";
9280             "NULL" in
9281       pr "\n";
9282
9283       pr "  r = guestfs_%s " name;
9284       generate_c_call_args ~handle:"g" style;
9285       pr ";\n";
9286
9287       List.iter (
9288         function
9289         | Pathname _ | Device _ | Dev_or_Path _ | String _
9290         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9291         | StringList n | DeviceList n ->
9292             pr "  free (%s);\n" n
9293       ) (snd style);
9294
9295       pr "  if (r == %s)\n" error_code;
9296       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9297       pr "\n";
9298
9299       (match fst style with
9300        | RErr ->
9301            pr "  return Qnil;\n"
9302        | RInt _ | RBool _ ->
9303            pr "  return INT2NUM (r);\n"
9304        | RInt64 _ ->
9305            pr "  return ULL2NUM (r);\n"
9306        | RConstString _ ->
9307            pr "  return rb_str_new2 (r);\n";
9308        | RConstOptString _ ->
9309            pr "  if (r)\n";
9310            pr "    return rb_str_new2 (r);\n";
9311            pr "  else\n";
9312            pr "    return Qnil;\n";
9313        | RString _ ->
9314            pr "  VALUE rv = rb_str_new2 (r);\n";
9315            pr "  free (r);\n";
9316            pr "  return rv;\n";
9317        | RStringList _ ->
9318            pr "  int i, len = 0;\n";
9319            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9320            pr "  VALUE rv = rb_ary_new2 (len);\n";
9321            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9322            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9323            pr "    free (r[i]);\n";
9324            pr "  }\n";
9325            pr "  free (r);\n";
9326            pr "  return rv;\n"
9327        | RStruct (_, typ) ->
9328            let cols = cols_of_struct typ in
9329            generate_ruby_struct_code typ cols
9330        | RStructList (_, typ) ->
9331            let cols = cols_of_struct typ in
9332            generate_ruby_struct_list_code typ cols
9333        | RHashtable _ ->
9334            pr "  VALUE rv = rb_hash_new ();\n";
9335            pr "  int i;\n";
9336            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9337            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9338            pr "    free (r[i]);\n";
9339            pr "    free (r[i+1]);\n";
9340            pr "  }\n";
9341            pr "  free (r);\n";
9342            pr "  return rv;\n"
9343        | RBufferOut _ ->
9344            pr "  VALUE rv = rb_str_new (r, size);\n";
9345            pr "  free (r);\n";
9346            pr "  return rv;\n";
9347       );
9348
9349       pr "}\n";
9350       pr "\n"
9351   ) all_functions;
9352
9353   pr "\
9354 /* Initialize the module. */
9355 void Init__guestfs ()
9356 {
9357   m_guestfs = rb_define_module (\"Guestfs\");
9358   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9359   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9360
9361   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9362   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9363
9364 ";
9365   (* Define the rest of the methods. *)
9366   List.iter (
9367     fun (name, style, _, _, _, _, _) ->
9368       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9369       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9370   ) all_functions;
9371
9372   pr "}\n"
9373
9374 (* Ruby code to return a struct. *)
9375 and generate_ruby_struct_code typ cols =
9376   pr "  VALUE rv = rb_hash_new ();\n";
9377   List.iter (
9378     function
9379     | name, FString ->
9380         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9381     | name, FBuffer ->
9382         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9383     | name, FUUID ->
9384         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9385     | name, (FBytes|FUInt64) ->
9386         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9387     | name, FInt64 ->
9388         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9389     | name, FUInt32 ->
9390         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9391     | name, FInt32 ->
9392         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9393     | name, FOptPercent ->
9394         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9395     | name, FChar -> (* XXX wrong? *)
9396         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9397   ) cols;
9398   pr "  guestfs_free_%s (r);\n" typ;
9399   pr "  return rv;\n"
9400
9401 (* Ruby code to return a struct list. *)
9402 and generate_ruby_struct_list_code typ cols =
9403   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9404   pr "  int i;\n";
9405   pr "  for (i = 0; i < r->len; ++i) {\n";
9406   pr "    VALUE hv = rb_hash_new ();\n";
9407   List.iter (
9408     function
9409     | name, FString ->
9410         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9411     | name, FBuffer ->
9412         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
9413     | name, FUUID ->
9414         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9415     | name, (FBytes|FUInt64) ->
9416         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9417     | name, FInt64 ->
9418         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9419     | name, FUInt32 ->
9420         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9421     | name, FInt32 ->
9422         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9423     | name, FOptPercent ->
9424         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9425     | name, FChar -> (* XXX wrong? *)
9426         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9427   ) cols;
9428   pr "    rb_ary_push (rv, hv);\n";
9429   pr "  }\n";
9430   pr "  guestfs_free_%s_list (r);\n" typ;
9431   pr "  return rv;\n"
9432
9433 (* Generate Java bindings GuestFS.java file. *)
9434 and generate_java_java () =
9435   generate_header CStyle LGPLv2plus;
9436
9437   pr "\
9438 package com.redhat.et.libguestfs;
9439
9440 import java.util.HashMap;
9441 import com.redhat.et.libguestfs.LibGuestFSException;
9442 import com.redhat.et.libguestfs.PV;
9443 import com.redhat.et.libguestfs.VG;
9444 import com.redhat.et.libguestfs.LV;
9445 import com.redhat.et.libguestfs.Stat;
9446 import com.redhat.et.libguestfs.StatVFS;
9447 import com.redhat.et.libguestfs.IntBool;
9448 import com.redhat.et.libguestfs.Dirent;
9449
9450 /**
9451  * The GuestFS object is a libguestfs handle.
9452  *
9453  * @author rjones
9454  */
9455 public class GuestFS {
9456   // Load the native code.
9457   static {
9458     System.loadLibrary (\"guestfs_jni\");
9459   }
9460
9461   /**
9462    * The native guestfs_h pointer.
9463    */
9464   long g;
9465
9466   /**
9467    * Create a libguestfs handle.
9468    *
9469    * @throws LibGuestFSException
9470    */
9471   public GuestFS () throws LibGuestFSException
9472   {
9473     g = _create ();
9474   }
9475   private native long _create () throws LibGuestFSException;
9476
9477   /**
9478    * Close a libguestfs handle.
9479    *
9480    * You can also leave handles to be collected by the garbage
9481    * collector, but this method ensures that the resources used
9482    * by the handle are freed up immediately.  If you call any
9483    * other methods after closing the handle, you will get an
9484    * exception.
9485    *
9486    * @throws LibGuestFSException
9487    */
9488   public void close () throws LibGuestFSException
9489   {
9490     if (g != 0)
9491       _close (g);
9492     g = 0;
9493   }
9494   private native void _close (long g) throws LibGuestFSException;
9495
9496   public void finalize () throws LibGuestFSException
9497   {
9498     close ();
9499   }
9500
9501 ";
9502
9503   List.iter (
9504     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9505       if not (List.mem NotInDocs flags); then (
9506         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9507         let doc =
9508           if List.mem ProtocolLimitWarning flags then
9509             doc ^ "\n\n" ^ protocol_limit_warning
9510           else doc in
9511         let doc =
9512           if List.mem DangerWillRobinson flags then
9513             doc ^ "\n\n" ^ danger_will_robinson
9514           else doc in
9515         let doc =
9516           match deprecation_notice flags with
9517           | None -> doc
9518           | Some txt -> doc ^ "\n\n" ^ txt in
9519         let doc = pod2text ~width:60 name doc in
9520         let doc = List.map (            (* RHBZ#501883 *)
9521           function
9522           | "" -> "<p>"
9523           | nonempty -> nonempty
9524         ) doc in
9525         let doc = String.concat "\n   * " doc in
9526
9527         pr "  /**\n";
9528         pr "   * %s\n" shortdesc;
9529         pr "   * <p>\n";
9530         pr "   * %s\n" doc;
9531         pr "   * @throws LibGuestFSException\n";
9532         pr "   */\n";
9533         pr "  ";
9534       );
9535       generate_java_prototype ~public:true ~semicolon:false name style;
9536       pr "\n";
9537       pr "  {\n";
9538       pr "    if (g == 0)\n";
9539       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9540         name;
9541       pr "    ";
9542       if fst style <> RErr then pr "return ";
9543       pr "_%s " name;
9544       generate_java_call_args ~handle:"g" (snd style);
9545       pr ";\n";
9546       pr "  }\n";
9547       pr "  ";
9548       generate_java_prototype ~privat:true ~native:true name style;
9549       pr "\n";
9550       pr "\n";
9551   ) all_functions;
9552
9553   pr "}\n"
9554
9555 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9556 and generate_java_call_args ~handle args =
9557   pr "(%s" handle;
9558   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9559   pr ")"
9560
9561 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9562     ?(semicolon=true) name style =
9563   if privat then pr "private ";
9564   if public then pr "public ";
9565   if native then pr "native ";
9566
9567   (* return type *)
9568   (match fst style with
9569    | RErr -> pr "void ";
9570    | RInt _ -> pr "int ";
9571    | RInt64 _ -> pr "long ";
9572    | RBool _ -> pr "boolean ";
9573    | RConstString _ | RConstOptString _ | RString _
9574    | RBufferOut _ -> pr "String ";
9575    | RStringList _ -> pr "String[] ";
9576    | RStruct (_, typ) ->
9577        let name = java_name_of_struct typ in
9578        pr "%s " name;
9579    | RStructList (_, typ) ->
9580        let name = java_name_of_struct typ in
9581        pr "%s[] " name;
9582    | RHashtable _ -> pr "HashMap<String,String> ";
9583   );
9584
9585   if native then pr "_%s " name else pr "%s " name;
9586   pr "(";
9587   let needs_comma = ref false in
9588   if native then (
9589     pr "long g";
9590     needs_comma := true
9591   );
9592
9593   (* args *)
9594   List.iter (
9595     fun arg ->
9596       if !needs_comma then pr ", ";
9597       needs_comma := true;
9598
9599       match arg with
9600       | Pathname n
9601       | Device n | Dev_or_Path n
9602       | String n
9603       | OptString n
9604       | FileIn n
9605       | FileOut n ->
9606           pr "String %s" n
9607       | StringList n | DeviceList n ->
9608           pr "String[] %s" n
9609       | Bool n ->
9610           pr "boolean %s" n
9611       | Int n ->
9612           pr "int %s" n
9613       | Int64 n ->
9614           pr "long %s" n
9615   ) (snd style);
9616
9617   pr ")\n";
9618   pr "    throws LibGuestFSException";
9619   if semicolon then pr ";"
9620
9621 and generate_java_struct jtyp cols () =
9622   generate_header CStyle LGPLv2plus;
9623
9624   pr "\
9625 package com.redhat.et.libguestfs;
9626
9627 /**
9628  * Libguestfs %s structure.
9629  *
9630  * @author rjones
9631  * @see GuestFS
9632  */
9633 public class %s {
9634 " jtyp jtyp;
9635
9636   List.iter (
9637     function
9638     | name, FString
9639     | name, FUUID
9640     | name, FBuffer -> pr "  public String %s;\n" name
9641     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9642     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9643     | name, FChar -> pr "  public char %s;\n" name
9644     | name, FOptPercent ->
9645         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9646         pr "  public float %s;\n" name
9647   ) cols;
9648
9649   pr "}\n"
9650
9651 and generate_java_c () =
9652   generate_header CStyle LGPLv2plus;
9653
9654   pr "\
9655 #include <stdio.h>
9656 #include <stdlib.h>
9657 #include <string.h>
9658
9659 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9660 #include \"guestfs.h\"
9661
9662 /* Note that this function returns.  The exception is not thrown
9663  * until after the wrapper function returns.
9664  */
9665 static void
9666 throw_exception (JNIEnv *env, const char *msg)
9667 {
9668   jclass cl;
9669   cl = (*env)->FindClass (env,
9670                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9671   (*env)->ThrowNew (env, cl, msg);
9672 }
9673
9674 JNIEXPORT jlong JNICALL
9675 Java_com_redhat_et_libguestfs_GuestFS__1create
9676   (JNIEnv *env, jobject obj)
9677 {
9678   guestfs_h *g;
9679
9680   g = guestfs_create ();
9681   if (g == NULL) {
9682     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9683     return 0;
9684   }
9685   guestfs_set_error_handler (g, NULL, NULL);
9686   return (jlong) (long) g;
9687 }
9688
9689 JNIEXPORT void JNICALL
9690 Java_com_redhat_et_libguestfs_GuestFS__1close
9691   (JNIEnv *env, jobject obj, jlong jg)
9692 {
9693   guestfs_h *g = (guestfs_h *) (long) jg;
9694   guestfs_close (g);
9695 }
9696
9697 ";
9698
9699   List.iter (
9700     fun (name, style, _, _, _, _, _) ->
9701       pr "JNIEXPORT ";
9702       (match fst style with
9703        | RErr -> pr "void ";
9704        | RInt _ -> pr "jint ";
9705        | RInt64 _ -> pr "jlong ";
9706        | RBool _ -> pr "jboolean ";
9707        | RConstString _ | RConstOptString _ | RString _
9708        | RBufferOut _ -> pr "jstring ";
9709        | RStruct _ | RHashtable _ ->
9710            pr "jobject ";
9711        | RStringList _ | RStructList _ ->
9712            pr "jobjectArray ";
9713       );
9714       pr "JNICALL\n";
9715       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9716       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9717       pr "\n";
9718       pr "  (JNIEnv *env, jobject obj, jlong jg";
9719       List.iter (
9720         function
9721         | Pathname n
9722         | Device n | Dev_or_Path n
9723         | String n
9724         | OptString n
9725         | FileIn n
9726         | FileOut n ->
9727             pr ", jstring j%s" n
9728         | StringList n | DeviceList n ->
9729             pr ", jobjectArray j%s" n
9730         | Bool n ->
9731             pr ", jboolean j%s" n
9732         | Int n ->
9733             pr ", jint j%s" n
9734         | Int64 n ->
9735             pr ", jlong j%s" n
9736       ) (snd style);
9737       pr ")\n";
9738       pr "{\n";
9739       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9740       let error_code, no_ret =
9741         match fst style with
9742         | RErr -> pr "  int r;\n"; "-1", ""
9743         | RBool _
9744         | RInt _ -> pr "  int r;\n"; "-1", "0"
9745         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9746         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9747         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9748         | RString _ ->
9749             pr "  jstring jr;\n";
9750             pr "  char *r;\n"; "NULL", "NULL"
9751         | RStringList _ ->
9752             pr "  jobjectArray jr;\n";
9753             pr "  int r_len;\n";
9754             pr "  jclass cl;\n";
9755             pr "  jstring jstr;\n";
9756             pr "  char **r;\n"; "NULL", "NULL"
9757         | RStruct (_, typ) ->
9758             pr "  jobject jr;\n";
9759             pr "  jclass cl;\n";
9760             pr "  jfieldID fl;\n";
9761             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9762         | RStructList (_, typ) ->
9763             pr "  jobjectArray jr;\n";
9764             pr "  jclass cl;\n";
9765             pr "  jfieldID fl;\n";
9766             pr "  jobject jfl;\n";
9767             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9768         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9769         | RBufferOut _ ->
9770             pr "  jstring jr;\n";
9771             pr "  char *r;\n";
9772             pr "  size_t size;\n";
9773             "NULL", "NULL" in
9774       List.iter (
9775         function
9776         | Pathname n
9777         | Device n | Dev_or_Path n
9778         | String n
9779         | OptString n
9780         | FileIn n
9781         | FileOut n ->
9782             pr "  const char *%s;\n" n
9783         | StringList n | DeviceList n ->
9784             pr "  int %s_len;\n" n;
9785             pr "  const char **%s;\n" n
9786         | Bool n
9787         | Int n ->
9788             pr "  int %s;\n" n
9789         | Int64 n ->
9790             pr "  int64_t %s;\n" n
9791       ) (snd style);
9792
9793       let needs_i =
9794         (match fst style with
9795          | RStringList _ | RStructList _ -> true
9796          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9797          | RConstOptString _
9798          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9799           List.exists (function
9800                        | StringList _ -> true
9801                        | DeviceList _ -> true
9802                        | _ -> false) (snd style) in
9803       if needs_i then
9804         pr "  int i;\n";
9805
9806       pr "\n";
9807
9808       (* Get the parameters. *)
9809       List.iter (
9810         function
9811         | Pathname n
9812         | Device n | Dev_or_Path n
9813         | String n
9814         | FileIn n
9815         | FileOut n ->
9816             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9817         | OptString n ->
9818             (* This is completely undocumented, but Java null becomes
9819              * a NULL parameter.
9820              *)
9821             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9822         | StringList n | DeviceList n ->
9823             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9824             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9825             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9826             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9827               n;
9828             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9829             pr "  }\n";
9830             pr "  %s[%s_len] = NULL;\n" n n;
9831         | Bool n
9832         | Int n
9833         | Int64 n ->
9834             pr "  %s = j%s;\n" n n
9835       ) (snd style);
9836
9837       (* Make the call. *)
9838       pr "  r = guestfs_%s " name;
9839       generate_c_call_args ~handle:"g" style;
9840       pr ";\n";
9841
9842       (* Release the parameters. *)
9843       List.iter (
9844         function
9845         | Pathname n
9846         | Device n | Dev_or_Path n
9847         | String n
9848         | FileIn n
9849         | FileOut n ->
9850             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9851         | OptString n ->
9852             pr "  if (j%s)\n" n;
9853             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9854         | StringList n | DeviceList n ->
9855             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9856             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9857               n;
9858             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9859             pr "  }\n";
9860             pr "  free (%s);\n" n
9861         | Bool n
9862         | Int n
9863         | Int64 n -> ()
9864       ) (snd style);
9865
9866       (* Check for errors. *)
9867       pr "  if (r == %s) {\n" error_code;
9868       pr "    throw_exception (env, guestfs_last_error (g));\n";
9869       pr "    return %s;\n" no_ret;
9870       pr "  }\n";
9871
9872       (* Return value. *)
9873       (match fst style with
9874        | RErr -> ()
9875        | RInt _ -> pr "  return (jint) r;\n"
9876        | RBool _ -> pr "  return (jboolean) r;\n"
9877        | RInt64 _ -> pr "  return (jlong) r;\n"
9878        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9879        | RConstOptString _ ->
9880            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9881        | RString _ ->
9882            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9883            pr "  free (r);\n";
9884            pr "  return jr;\n"
9885        | RStringList _ ->
9886            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9887            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9888            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9889            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9890            pr "  for (i = 0; i < r_len; ++i) {\n";
9891            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9892            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9893            pr "    free (r[i]);\n";
9894            pr "  }\n";
9895            pr "  free (r);\n";
9896            pr "  return jr;\n"
9897        | RStruct (_, typ) ->
9898            let jtyp = java_name_of_struct typ in
9899            let cols = cols_of_struct typ in
9900            generate_java_struct_return typ jtyp cols
9901        | RStructList (_, typ) ->
9902            let jtyp = java_name_of_struct typ in
9903            let cols = cols_of_struct typ in
9904            generate_java_struct_list_return typ jtyp cols
9905        | RHashtable _ ->
9906            (* XXX *)
9907            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9908            pr "  return NULL;\n"
9909        | RBufferOut _ ->
9910            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9911            pr "  free (r);\n";
9912            pr "  return jr;\n"
9913       );
9914
9915       pr "}\n";
9916       pr "\n"
9917   ) all_functions
9918
9919 and generate_java_struct_return typ jtyp cols =
9920   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9921   pr "  jr = (*env)->AllocObject (env, cl);\n";
9922   List.iter (
9923     function
9924     | name, FString ->
9925         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9926         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9927     | name, FUUID ->
9928         pr "  {\n";
9929         pr "    char s[33];\n";
9930         pr "    memcpy (s, r->%s, 32);\n" name;
9931         pr "    s[32] = 0;\n";
9932         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9933         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9934         pr "  }\n";
9935     | name, FBuffer ->
9936         pr "  {\n";
9937         pr "    int len = r->%s_len;\n" name;
9938         pr "    char s[len+1];\n";
9939         pr "    memcpy (s, r->%s, len);\n" name;
9940         pr "    s[len] = 0;\n";
9941         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9942         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9943         pr "  }\n";
9944     | name, (FBytes|FUInt64|FInt64) ->
9945         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9946         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9947     | name, (FUInt32|FInt32) ->
9948         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9949         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9950     | name, FOptPercent ->
9951         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9952         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9953     | name, FChar ->
9954         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9955         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9956   ) cols;
9957   pr "  free (r);\n";
9958   pr "  return jr;\n"
9959
9960 and generate_java_struct_list_return typ jtyp cols =
9961   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9962   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9963   pr "  for (i = 0; i < r->len; ++i) {\n";
9964   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9965   List.iter (
9966     function
9967     | name, FString ->
9968         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9969         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9970     | name, FUUID ->
9971         pr "    {\n";
9972         pr "      char s[33];\n";
9973         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9974         pr "      s[32] = 0;\n";
9975         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9976         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9977         pr "    }\n";
9978     | name, FBuffer ->
9979         pr "    {\n";
9980         pr "      int len = r->val[i].%s_len;\n" name;
9981         pr "      char s[len+1];\n";
9982         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9983         pr "      s[len] = 0;\n";
9984         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9985         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9986         pr "    }\n";
9987     | name, (FBytes|FUInt64|FInt64) ->
9988         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9989         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9990     | name, (FUInt32|FInt32) ->
9991         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9992         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9993     | name, FOptPercent ->
9994         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9995         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9996     | name, FChar ->
9997         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9998         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9999   ) cols;
10000   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10001   pr "  }\n";
10002   pr "  guestfs_free_%s_list (r);\n" typ;
10003   pr "  return jr;\n"
10004
10005 and generate_java_makefile_inc () =
10006   generate_header HashStyle GPLv2plus;
10007
10008   pr "java_built_sources = \\\n";
10009   List.iter (
10010     fun (typ, jtyp) ->
10011         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10012   ) java_structs;
10013   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10014
10015 and generate_haskell_hs () =
10016   generate_header HaskellStyle LGPLv2plus;
10017
10018   (* XXX We only know how to generate partial FFI for Haskell
10019    * at the moment.  Please help out!
10020    *)
10021   let can_generate style =
10022     match style with
10023     | RErr, _
10024     | RInt _, _
10025     | RInt64 _, _ -> true
10026     | RBool _, _
10027     | RConstString _, _
10028     | RConstOptString _, _
10029     | RString _, _
10030     | RStringList _, _
10031     | RStruct _, _
10032     | RStructList _, _
10033     | RHashtable _, _
10034     | RBufferOut _, _ -> false in
10035
10036   pr "\
10037 {-# INCLUDE <guestfs.h> #-}
10038 {-# LANGUAGE ForeignFunctionInterface #-}
10039
10040 module Guestfs (
10041   create";
10042
10043   (* List out the names of the actions we want to export. *)
10044   List.iter (
10045     fun (name, style, _, _, _, _, _) ->
10046       if can_generate style then pr ",\n  %s" name
10047   ) all_functions;
10048
10049   pr "
10050   ) where
10051
10052 -- Unfortunately some symbols duplicate ones already present
10053 -- in Prelude.  We don't know which, so we hard-code a list
10054 -- here.
10055 import Prelude hiding (truncate)
10056
10057 import Foreign
10058 import Foreign.C
10059 import Foreign.C.Types
10060 import IO
10061 import Control.Exception
10062 import Data.Typeable
10063
10064 data GuestfsS = GuestfsS            -- represents the opaque C struct
10065 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10066 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10067
10068 -- XXX define properly later XXX
10069 data PV = PV
10070 data VG = VG
10071 data LV = LV
10072 data IntBool = IntBool
10073 data Stat = Stat
10074 data StatVFS = StatVFS
10075 data Hashtable = Hashtable
10076
10077 foreign import ccall unsafe \"guestfs_create\" c_create
10078   :: IO GuestfsP
10079 foreign import ccall unsafe \"&guestfs_close\" c_close
10080   :: FunPtr (GuestfsP -> IO ())
10081 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10082   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10083
10084 create :: IO GuestfsH
10085 create = do
10086   p <- c_create
10087   c_set_error_handler p nullPtr nullPtr
10088   h <- newForeignPtr c_close p
10089   return h
10090
10091 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10092   :: GuestfsP -> IO CString
10093
10094 -- last_error :: GuestfsH -> IO (Maybe String)
10095 -- last_error h = do
10096 --   str <- withForeignPtr h (\\p -> c_last_error p)
10097 --   maybePeek peekCString str
10098
10099 last_error :: GuestfsH -> IO (String)
10100 last_error h = do
10101   str <- withForeignPtr h (\\p -> c_last_error p)
10102   if (str == nullPtr)
10103     then return \"no error\"
10104     else peekCString str
10105
10106 ";
10107
10108   (* Generate wrappers for each foreign function. *)
10109   List.iter (
10110     fun (name, style, _, _, _, _, _) ->
10111       if can_generate style then (
10112         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10113         pr "  :: ";
10114         generate_haskell_prototype ~handle:"GuestfsP" style;
10115         pr "\n";
10116         pr "\n";
10117         pr "%s :: " name;
10118         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10119         pr "\n";
10120         pr "%s %s = do\n" name
10121           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10122         pr "  r <- ";
10123         (* Convert pointer arguments using with* functions. *)
10124         List.iter (
10125           function
10126           | FileIn n
10127           | FileOut n
10128           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10129           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10130           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10131           | Bool _ | Int _ | Int64 _ -> ()
10132         ) (snd style);
10133         (* Convert integer arguments. *)
10134         let args =
10135           List.map (
10136             function
10137             | Bool n -> sprintf "(fromBool %s)" n
10138             | Int n -> sprintf "(fromIntegral %s)" n
10139             | Int64 n -> sprintf "(fromIntegral %s)" n
10140             | FileIn n | FileOut n
10141             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10142           ) (snd style) in
10143         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10144           (String.concat " " ("p" :: args));
10145         (match fst style with
10146          | RErr | RInt _ | RInt64 _ | RBool _ ->
10147              pr "  if (r == -1)\n";
10148              pr "    then do\n";
10149              pr "      err <- last_error h\n";
10150              pr "      fail err\n";
10151          | RConstString _ | RConstOptString _ | RString _
10152          | RStringList _ | RStruct _
10153          | RStructList _ | RHashtable _ | RBufferOut _ ->
10154              pr "  if (r == nullPtr)\n";
10155              pr "    then do\n";
10156              pr "      err <- last_error h\n";
10157              pr "      fail err\n";
10158         );
10159         (match fst style with
10160          | RErr ->
10161              pr "    else return ()\n"
10162          | RInt _ ->
10163              pr "    else return (fromIntegral r)\n"
10164          | RInt64 _ ->
10165              pr "    else return (fromIntegral r)\n"
10166          | RBool _ ->
10167              pr "    else return (toBool r)\n"
10168          | RConstString _
10169          | RConstOptString _
10170          | RString _
10171          | RStringList _
10172          | RStruct _
10173          | RStructList _
10174          | RHashtable _
10175          | RBufferOut _ ->
10176              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10177         );
10178         pr "\n";
10179       )
10180   ) all_functions
10181
10182 and generate_haskell_prototype ~handle ?(hs = false) style =
10183   pr "%s -> " handle;
10184   let string = if hs then "String" else "CString" in
10185   let int = if hs then "Int" else "CInt" in
10186   let bool = if hs then "Bool" else "CInt" in
10187   let int64 = if hs then "Integer" else "Int64" in
10188   List.iter (
10189     fun arg ->
10190       (match arg with
10191        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10192        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10193        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10194        | Bool _ -> pr "%s" bool
10195        | Int _ -> pr "%s" int
10196        | Int64 _ -> pr "%s" int
10197        | FileIn _ -> pr "%s" string
10198        | FileOut _ -> pr "%s" string
10199       );
10200       pr " -> ";
10201   ) (snd style);
10202   pr "IO (";
10203   (match fst style with
10204    | RErr -> if not hs then pr "CInt"
10205    | RInt _ -> pr "%s" int
10206    | RInt64 _ -> pr "%s" int64
10207    | RBool _ -> pr "%s" bool
10208    | RConstString _ -> pr "%s" string
10209    | RConstOptString _ -> pr "Maybe %s" string
10210    | RString _ -> pr "%s" string
10211    | RStringList _ -> pr "[%s]" string
10212    | RStruct (_, typ) ->
10213        let name = java_name_of_struct typ in
10214        pr "%s" name
10215    | RStructList (_, typ) ->
10216        let name = java_name_of_struct typ in
10217        pr "[%s]" name
10218    | RHashtable _ -> pr "Hashtable"
10219    | RBufferOut _ -> pr "%s" string
10220   );
10221   pr ")"
10222
10223 and generate_csharp () =
10224   generate_header CPlusPlusStyle LGPLv2plus;
10225
10226   (* XXX Make this configurable by the C# assembly users. *)
10227   let library = "libguestfs.so.0" in
10228
10229   pr "\
10230 // These C# bindings are highly experimental at present.
10231 //
10232 // Firstly they only work on Linux (ie. Mono).  In order to get them
10233 // to work on Windows (ie. .Net) you would need to port the library
10234 // itself to Windows first.
10235 //
10236 // The second issue is that some calls are known to be incorrect and
10237 // can cause Mono to segfault.  Particularly: calls which pass or
10238 // return string[], or return any structure value.  This is because
10239 // we haven't worked out the correct way to do this from C#.
10240 //
10241 // The third issue is that when compiling you get a lot of warnings.
10242 // We are not sure whether the warnings are important or not.
10243 //
10244 // Fourthly we do not routinely build or test these bindings as part
10245 // of the make && make check cycle, which means that regressions might
10246 // go unnoticed.
10247 //
10248 // Suggestions and patches are welcome.
10249
10250 // To compile:
10251 //
10252 // gmcs Libguestfs.cs
10253 // mono Libguestfs.exe
10254 //
10255 // (You'll probably want to add a Test class / static main function
10256 // otherwise this won't do anything useful).
10257
10258 using System;
10259 using System.IO;
10260 using System.Runtime.InteropServices;
10261 using System.Runtime.Serialization;
10262 using System.Collections;
10263
10264 namespace Guestfs
10265 {
10266   class Error : System.ApplicationException
10267   {
10268     public Error (string message) : base (message) {}
10269     protected Error (SerializationInfo info, StreamingContext context) {}
10270   }
10271
10272   class Guestfs
10273   {
10274     IntPtr _handle;
10275
10276     [DllImport (\"%s\")]
10277     static extern IntPtr guestfs_create ();
10278
10279     public Guestfs ()
10280     {
10281       _handle = guestfs_create ();
10282       if (_handle == IntPtr.Zero)
10283         throw new Error (\"could not create guestfs handle\");
10284     }
10285
10286     [DllImport (\"%s\")]
10287     static extern void guestfs_close (IntPtr h);
10288
10289     ~Guestfs ()
10290     {
10291       guestfs_close (_handle);
10292     }
10293
10294     [DllImport (\"%s\")]
10295     static extern string guestfs_last_error (IntPtr h);
10296
10297 " library library library;
10298
10299   (* Generate C# structure bindings.  We prefix struct names with
10300    * underscore because C# cannot have conflicting struct names and
10301    * method names (eg. "class stat" and "stat").
10302    *)
10303   List.iter (
10304     fun (typ, cols) ->
10305       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10306       pr "    public class _%s {\n" typ;
10307       List.iter (
10308         function
10309         | name, FChar -> pr "      char %s;\n" name
10310         | name, FString -> pr "      string %s;\n" name
10311         | name, FBuffer ->
10312             pr "      uint %s_len;\n" name;
10313             pr "      string %s;\n" name
10314         | name, FUUID ->
10315             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10316             pr "      string %s;\n" name
10317         | name, FUInt32 -> pr "      uint %s;\n" name
10318         | name, FInt32 -> pr "      int %s;\n" name
10319         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10320         | name, FInt64 -> pr "      long %s;\n" name
10321         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10322       ) cols;
10323       pr "    }\n";
10324       pr "\n"
10325   ) structs;
10326
10327   (* Generate C# function bindings. *)
10328   List.iter (
10329     fun (name, style, _, _, _, shortdesc, _) ->
10330       let rec csharp_return_type () =
10331         match fst style with
10332         | RErr -> "void"
10333         | RBool n -> "bool"
10334         | RInt n -> "int"
10335         | RInt64 n -> "long"
10336         | RConstString n
10337         | RConstOptString n
10338         | RString n
10339         | RBufferOut n -> "string"
10340         | RStruct (_,n) -> "_" ^ n
10341         | RHashtable n -> "Hashtable"
10342         | RStringList n -> "string[]"
10343         | RStructList (_,n) -> sprintf "_%s[]" n
10344
10345       and c_return_type () =
10346         match fst style with
10347         | RErr
10348         | RBool _
10349         | RInt _ -> "int"
10350         | RInt64 _ -> "long"
10351         | RConstString _
10352         | RConstOptString _
10353         | RString _
10354         | RBufferOut _ -> "string"
10355         | RStruct (_,n) -> "_" ^ n
10356         | RHashtable _
10357         | RStringList _ -> "string[]"
10358         | RStructList (_,n) -> sprintf "_%s[]" n
10359
10360       and c_error_comparison () =
10361         match fst style with
10362         | RErr
10363         | RBool _
10364         | RInt _
10365         | RInt64 _ -> "== -1"
10366         | RConstString _
10367         | RConstOptString _
10368         | RString _
10369         | RBufferOut _
10370         | RStruct (_,_)
10371         | RHashtable _
10372         | RStringList _
10373         | RStructList (_,_) -> "== null"
10374
10375       and generate_extern_prototype () =
10376         pr "    static extern %s guestfs_%s (IntPtr h"
10377           (c_return_type ()) name;
10378         List.iter (
10379           function
10380           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10381           | FileIn n | FileOut n ->
10382               pr ", [In] string %s" n
10383           | StringList n | DeviceList n ->
10384               pr ", [In] string[] %s" n
10385           | Bool n ->
10386               pr ", bool %s" n
10387           | Int n ->
10388               pr ", int %s" n
10389           | Int64 n ->
10390               pr ", long %s" n
10391         ) (snd style);
10392         pr ");\n"
10393
10394       and generate_public_prototype () =
10395         pr "    public %s %s (" (csharp_return_type ()) name;
10396         let comma = ref false in
10397         let next () =
10398           if !comma then pr ", ";
10399           comma := true
10400         in
10401         List.iter (
10402           function
10403           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10404           | FileIn n | FileOut n ->
10405               next (); pr "string %s" n
10406           | StringList n | DeviceList n ->
10407               next (); pr "string[] %s" n
10408           | Bool n ->
10409               next (); pr "bool %s" n
10410           | Int n ->
10411               next (); pr "int %s" n
10412           | Int64 n ->
10413               next (); pr "long %s" n
10414         ) (snd style);
10415         pr ")\n"
10416
10417       and generate_call () =
10418         pr "guestfs_%s (_handle" name;
10419         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10420         pr ");\n";
10421       in
10422
10423       pr "    [DllImport (\"%s\")]\n" library;
10424       generate_extern_prototype ();
10425       pr "\n";
10426       pr "    /// <summary>\n";
10427       pr "    /// %s\n" shortdesc;
10428       pr "    /// </summary>\n";
10429       generate_public_prototype ();
10430       pr "    {\n";
10431       pr "      %s r;\n" (c_return_type ());
10432       pr "      r = ";
10433       generate_call ();
10434       pr "      if (r %s)\n" (c_error_comparison ());
10435       pr "        throw new Error (guestfs_last_error (_handle));\n";
10436       (match fst style with
10437        | RErr -> ()
10438        | RBool _ ->
10439            pr "      return r != 0 ? true : false;\n"
10440        | RHashtable _ ->
10441            pr "      Hashtable rr = new Hashtable ();\n";
10442            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10443            pr "        rr.Add (r[i], r[i+1]);\n";
10444            pr "      return rr;\n"
10445        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10446        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10447        | RStructList _ ->
10448            pr "      return r;\n"
10449       );
10450       pr "    }\n";
10451       pr "\n";
10452   ) all_functions_sorted;
10453
10454   pr "  }
10455 }
10456 "
10457
10458 and generate_bindtests () =
10459   generate_header CStyle LGPLv2plus;
10460
10461   pr "\
10462 #include <stdio.h>
10463 #include <stdlib.h>
10464 #include <inttypes.h>
10465 #include <string.h>
10466
10467 #include \"guestfs.h\"
10468 #include \"guestfs-internal.h\"
10469 #include \"guestfs-internal-actions.h\"
10470 #include \"guestfs_protocol.h\"
10471
10472 #define error guestfs_error
10473 #define safe_calloc guestfs_safe_calloc
10474 #define safe_malloc guestfs_safe_malloc
10475
10476 static void
10477 print_strings (char *const *argv)
10478 {
10479   int argc;
10480
10481   printf (\"[\");
10482   for (argc = 0; argv[argc] != NULL; ++argc) {
10483     if (argc > 0) printf (\", \");
10484     printf (\"\\\"%%s\\\"\", argv[argc]);
10485   }
10486   printf (\"]\\n\");
10487 }
10488
10489 /* The test0 function prints its parameters to stdout. */
10490 ";
10491
10492   let test0, tests =
10493     match test_functions with
10494     | [] -> assert false
10495     | test0 :: tests -> test0, tests in
10496
10497   let () =
10498     let (name, style, _, _, _, _, _) = test0 in
10499     generate_prototype ~extern:false ~semicolon:false ~newline:true
10500       ~handle:"g" ~prefix:"guestfs__" name style;
10501     pr "{\n";
10502     List.iter (
10503       function
10504       | Pathname n
10505       | Device n | Dev_or_Path n
10506       | String n
10507       | FileIn n
10508       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10509       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10510       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10511       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10512       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10513       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10514     ) (snd style);
10515     pr "  /* Java changes stdout line buffering so we need this: */\n";
10516     pr "  fflush (stdout);\n";
10517     pr "  return 0;\n";
10518     pr "}\n";
10519     pr "\n" in
10520
10521   List.iter (
10522     fun (name, style, _, _, _, _, _) ->
10523       if String.sub name (String.length name - 3) 3 <> "err" then (
10524         pr "/* Test normal return. */\n";
10525         generate_prototype ~extern:false ~semicolon:false ~newline:true
10526           ~handle:"g" ~prefix:"guestfs__" name style;
10527         pr "{\n";
10528         (match fst style with
10529          | RErr ->
10530              pr "  return 0;\n"
10531          | RInt _ ->
10532              pr "  int r;\n";
10533              pr "  sscanf (val, \"%%d\", &r);\n";
10534              pr "  return r;\n"
10535          | RInt64 _ ->
10536              pr "  int64_t r;\n";
10537              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10538              pr "  return r;\n"
10539          | RBool _ ->
10540              pr "  return STREQ (val, \"true\");\n"
10541          | RConstString _
10542          | RConstOptString _ ->
10543              (* Can't return the input string here.  Return a static
10544               * string so we ensure we get a segfault if the caller
10545               * tries to free it.
10546               *)
10547              pr "  return \"static string\";\n"
10548          | RString _ ->
10549              pr "  return strdup (val);\n"
10550          | RStringList _ ->
10551              pr "  char **strs;\n";
10552              pr "  int n, i;\n";
10553              pr "  sscanf (val, \"%%d\", &n);\n";
10554              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10555              pr "  for (i = 0; i < n; ++i) {\n";
10556              pr "    strs[i] = safe_malloc (g, 16);\n";
10557              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10558              pr "  }\n";
10559              pr "  strs[n] = NULL;\n";
10560              pr "  return strs;\n"
10561          | RStruct (_, typ) ->
10562              pr "  struct guestfs_%s *r;\n" typ;
10563              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10564              pr "  return r;\n"
10565          | RStructList (_, typ) ->
10566              pr "  struct guestfs_%s_list *r;\n" typ;
10567              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10568              pr "  sscanf (val, \"%%d\", &r->len);\n";
10569              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10570              pr "  return r;\n"
10571          | RHashtable _ ->
10572              pr "  char **strs;\n";
10573              pr "  int n, i;\n";
10574              pr "  sscanf (val, \"%%d\", &n);\n";
10575              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10576              pr "  for (i = 0; i < n; ++i) {\n";
10577              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10578              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10579              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10580              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10581              pr "  }\n";
10582              pr "  strs[n*2] = NULL;\n";
10583              pr "  return strs;\n"
10584          | RBufferOut _ ->
10585              pr "  return strdup (val);\n"
10586         );
10587         pr "}\n";
10588         pr "\n"
10589       ) else (
10590         pr "/* Test error return. */\n";
10591         generate_prototype ~extern:false ~semicolon:false ~newline:true
10592           ~handle:"g" ~prefix:"guestfs__" name style;
10593         pr "{\n";
10594         pr "  error (g, \"error\");\n";
10595         (match fst style with
10596          | RErr | RInt _ | RInt64 _ | RBool _ ->
10597              pr "  return -1;\n"
10598          | RConstString _ | RConstOptString _
10599          | RString _ | RStringList _ | RStruct _
10600          | RStructList _
10601          | RHashtable _
10602          | RBufferOut _ ->
10603              pr "  return NULL;\n"
10604         );
10605         pr "}\n";
10606         pr "\n"
10607       )
10608   ) tests
10609
10610 and generate_ocaml_bindtests () =
10611   generate_header OCamlStyle GPLv2plus;
10612
10613   pr "\
10614 let () =
10615   let g = Guestfs.create () in
10616 ";
10617
10618   let mkargs args =
10619     String.concat " " (
10620       List.map (
10621         function
10622         | CallString s -> "\"" ^ s ^ "\""
10623         | CallOptString None -> "None"
10624         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10625         | CallStringList xs ->
10626             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10627         | CallInt i when i >= 0 -> string_of_int i
10628         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10629         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10630         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10631         | CallBool b -> string_of_bool b
10632       ) args
10633     )
10634   in
10635
10636   generate_lang_bindtests (
10637     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10638   );
10639
10640   pr "print_endline \"EOF\"\n"
10641
10642 and generate_perl_bindtests () =
10643   pr "#!/usr/bin/perl -w\n";
10644   generate_header HashStyle GPLv2plus;
10645
10646   pr "\
10647 use strict;
10648
10649 use Sys::Guestfs;
10650
10651 my $g = Sys::Guestfs->new ();
10652 ";
10653
10654   let mkargs args =
10655     String.concat ", " (
10656       List.map (
10657         function
10658         | CallString s -> "\"" ^ s ^ "\""
10659         | CallOptString None -> "undef"
10660         | CallOptString (Some s) -> sprintf "\"%s\"" s
10661         | CallStringList xs ->
10662             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10663         | CallInt i -> string_of_int i
10664         | CallInt64 i -> Int64.to_string i
10665         | CallBool b -> if b then "1" else "0"
10666       ) args
10667     )
10668   in
10669
10670   generate_lang_bindtests (
10671     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10672   );
10673
10674   pr "print \"EOF\\n\"\n"
10675
10676 and generate_python_bindtests () =
10677   generate_header HashStyle GPLv2plus;
10678
10679   pr "\
10680 import guestfs
10681
10682 g = guestfs.GuestFS ()
10683 ";
10684
10685   let mkargs args =
10686     String.concat ", " (
10687       List.map (
10688         function
10689         | CallString s -> "\"" ^ s ^ "\""
10690         | CallOptString None -> "None"
10691         | CallOptString (Some s) -> sprintf "\"%s\"" s
10692         | CallStringList xs ->
10693             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10694         | CallInt i -> string_of_int i
10695         | CallInt64 i -> Int64.to_string i
10696         | CallBool b -> if b then "1" else "0"
10697       ) args
10698     )
10699   in
10700
10701   generate_lang_bindtests (
10702     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10703   );
10704
10705   pr "print \"EOF\"\n"
10706
10707 and generate_ruby_bindtests () =
10708   generate_header HashStyle GPLv2plus;
10709
10710   pr "\
10711 require 'guestfs'
10712
10713 g = Guestfs::create()
10714 ";
10715
10716   let mkargs args =
10717     String.concat ", " (
10718       List.map (
10719         function
10720         | CallString s -> "\"" ^ s ^ "\""
10721         | CallOptString None -> "nil"
10722         | CallOptString (Some s) -> sprintf "\"%s\"" s
10723         | CallStringList xs ->
10724             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10725         | CallInt i -> string_of_int i
10726         | CallInt64 i -> Int64.to_string i
10727         | CallBool b -> string_of_bool b
10728       ) args
10729     )
10730   in
10731
10732   generate_lang_bindtests (
10733     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10734   );
10735
10736   pr "print \"EOF\\n\"\n"
10737
10738 and generate_java_bindtests () =
10739   generate_header CStyle GPLv2plus;
10740
10741   pr "\
10742 import com.redhat.et.libguestfs.*;
10743
10744 public class Bindtests {
10745     public static void main (String[] argv)
10746     {
10747         try {
10748             GuestFS g = new GuestFS ();
10749 ";
10750
10751   let mkargs args =
10752     String.concat ", " (
10753       List.map (
10754         function
10755         | CallString s -> "\"" ^ s ^ "\""
10756         | CallOptString None -> "null"
10757         | CallOptString (Some s) -> sprintf "\"%s\"" s
10758         | CallStringList xs ->
10759             "new String[]{" ^
10760               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10761         | CallInt i -> string_of_int i
10762         | CallInt64 i -> Int64.to_string i
10763         | CallBool b -> string_of_bool b
10764       ) args
10765     )
10766   in
10767
10768   generate_lang_bindtests (
10769     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10770   );
10771
10772   pr "
10773             System.out.println (\"EOF\");
10774         }
10775         catch (Exception exn) {
10776             System.err.println (exn);
10777             System.exit (1);
10778         }
10779     }
10780 }
10781 "
10782
10783 and generate_haskell_bindtests () =
10784   generate_header HaskellStyle GPLv2plus;
10785
10786   pr "\
10787 module Bindtests where
10788 import qualified Guestfs
10789
10790 main = do
10791   g <- Guestfs.create
10792 ";
10793
10794   let mkargs args =
10795     String.concat " " (
10796       List.map (
10797         function
10798         | CallString s -> "\"" ^ s ^ "\""
10799         | CallOptString None -> "Nothing"
10800         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10801         | CallStringList xs ->
10802             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10803         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10804         | CallInt i -> string_of_int i
10805         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10806         | CallInt64 i -> Int64.to_string i
10807         | CallBool true -> "True"
10808         | CallBool false -> "False"
10809       ) args
10810     )
10811   in
10812
10813   generate_lang_bindtests (
10814     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10815   );
10816
10817   pr "  putStrLn \"EOF\"\n"
10818
10819 (* Language-independent bindings tests - we do it this way to
10820  * ensure there is parity in testing bindings across all languages.
10821  *)
10822 and generate_lang_bindtests call =
10823   call "test0" [CallString "abc"; CallOptString (Some "def");
10824                 CallStringList []; CallBool false;
10825                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10826   call "test0" [CallString "abc"; CallOptString None;
10827                 CallStringList []; CallBool false;
10828                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10829   call "test0" [CallString ""; CallOptString (Some "def");
10830                 CallStringList []; CallBool false;
10831                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10832   call "test0" [CallString ""; CallOptString (Some "");
10833                 CallStringList []; CallBool false;
10834                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10835   call "test0" [CallString "abc"; CallOptString (Some "def");
10836                 CallStringList ["1"]; CallBool false;
10837                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10838   call "test0" [CallString "abc"; CallOptString (Some "def");
10839                 CallStringList ["1"; "2"]; CallBool false;
10840                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10841   call "test0" [CallString "abc"; CallOptString (Some "def");
10842                 CallStringList ["1"]; CallBool true;
10843                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10844   call "test0" [CallString "abc"; CallOptString (Some "def");
10845                 CallStringList ["1"]; CallBool false;
10846                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10847   call "test0" [CallString "abc"; CallOptString (Some "def");
10848                 CallStringList ["1"]; CallBool false;
10849                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10850   call "test0" [CallString "abc"; CallOptString (Some "def");
10851                 CallStringList ["1"]; CallBool false;
10852                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10853   call "test0" [CallString "abc"; CallOptString (Some "def");
10854                 CallStringList ["1"]; CallBool false;
10855                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10856   call "test0" [CallString "abc"; CallOptString (Some "def");
10857                 CallStringList ["1"]; CallBool false;
10858                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10859   call "test0" [CallString "abc"; CallOptString (Some "def");
10860                 CallStringList ["1"]; CallBool false;
10861                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10862
10863 (* XXX Add here tests of the return and error functions. *)
10864
10865 (* Code to generator bindings for virt-inspector.  Currently only
10866  * implemented for OCaml code (for virt-p2v 2.0).
10867  *)
10868 let rng_input = "inspector/virt-inspector.rng"
10869
10870 (* Read the input file and parse it into internal structures.  This is
10871  * by no means a complete RELAX NG parser, but is just enough to be
10872  * able to parse the specific input file.
10873  *)
10874 type rng =
10875   | Element of string * rng list        (* <element name=name/> *)
10876   | Attribute of string * rng list        (* <attribute name=name/> *)
10877   | Interleave of rng list                (* <interleave/> *)
10878   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10879   | OneOrMore of rng                        (* <oneOrMore/> *)
10880   | Optional of rng                        (* <optional/> *)
10881   | Choice of string list                (* <choice><value/>*</choice> *)
10882   | Value of string                        (* <value>str</value> *)
10883   | Text                                (* <text/> *)
10884
10885 let rec string_of_rng = function
10886   | Element (name, xs) ->
10887       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10888   | Attribute (name, xs) ->
10889       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10890   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10891   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10892   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10893   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10894   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10895   | Value value -> "Value \"" ^ value ^ "\""
10896   | Text -> "Text"
10897
10898 and string_of_rng_list xs =
10899   String.concat ", " (List.map string_of_rng xs)
10900
10901 let rec parse_rng ?defines context = function
10902   | [] -> []
10903   | Xml.Element ("element", ["name", name], children) :: rest ->
10904       Element (name, parse_rng ?defines context children)
10905       :: parse_rng ?defines context rest
10906   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10907       Attribute (name, parse_rng ?defines context children)
10908       :: parse_rng ?defines context rest
10909   | Xml.Element ("interleave", [], children) :: rest ->
10910       Interleave (parse_rng ?defines context children)
10911       :: parse_rng ?defines context rest
10912   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10913       let rng = parse_rng ?defines context [child] in
10914       (match rng with
10915        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10916        | _ ->
10917            failwithf "%s: <zeroOrMore> contains more than one child element"
10918              context
10919       )
10920   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10921       let rng = parse_rng ?defines context [child] in
10922       (match rng with
10923        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10924        | _ ->
10925            failwithf "%s: <oneOrMore> contains more than one child element"
10926              context
10927       )
10928   | Xml.Element ("optional", [], [child]) :: rest ->
10929       let rng = parse_rng ?defines context [child] in
10930       (match rng with
10931        | [child] -> Optional child :: parse_rng ?defines context rest
10932        | _ ->
10933            failwithf "%s: <optional> contains more than one child element"
10934              context
10935       )
10936   | Xml.Element ("choice", [], children) :: rest ->
10937       let values = List.map (
10938         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10939         | _ ->
10940             failwithf "%s: can't handle anything except <value> in <choice>"
10941               context
10942       ) children in
10943       Choice values
10944       :: parse_rng ?defines context rest
10945   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10946       Value value :: parse_rng ?defines context rest
10947   | Xml.Element ("text", [], []) :: rest ->
10948       Text :: parse_rng ?defines context rest
10949   | Xml.Element ("ref", ["name", name], []) :: rest ->
10950       (* Look up the reference.  Because of limitations in this parser,
10951        * we can't handle arbitrarily nested <ref> yet.  You can only
10952        * use <ref> from inside <start>.
10953        *)
10954       (match defines with
10955        | None ->
10956            failwithf "%s: contains <ref>, but no refs are defined yet" context
10957        | Some map ->
10958            let rng = StringMap.find name map in
10959            rng @ parse_rng ?defines context rest
10960       )
10961   | x :: _ ->
10962       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10963
10964 let grammar =
10965   let xml = Xml.parse_file rng_input in
10966   match xml with
10967   | Xml.Element ("grammar", _,
10968                  Xml.Element ("start", _, gram) :: defines) ->
10969       (* The <define/> elements are referenced in the <start> section,
10970        * so build a map of those first.
10971        *)
10972       let defines = List.fold_left (
10973         fun map ->
10974           function Xml.Element ("define", ["name", name], defn) ->
10975             StringMap.add name defn map
10976           | _ ->
10977               failwithf "%s: expected <define name=name/>" rng_input
10978       ) StringMap.empty defines in
10979       let defines = StringMap.mapi parse_rng defines in
10980
10981       (* Parse the <start> clause, passing the defines. *)
10982       parse_rng ~defines "<start>" gram
10983   | _ ->
10984       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10985         rng_input
10986
10987 let name_of_field = function
10988   | Element (name, _) | Attribute (name, _)
10989   | ZeroOrMore (Element (name, _))
10990   | OneOrMore (Element (name, _))
10991   | Optional (Element (name, _)) -> name
10992   | Optional (Attribute (name, _)) -> name
10993   | Text -> (* an unnamed field in an element *)
10994       "data"
10995   | rng ->
10996       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10997
10998 (* At the moment this function only generates OCaml types.  However we
10999  * should parameterize it later so it can generate types/structs in a
11000  * variety of languages.
11001  *)
11002 let generate_types xs =
11003   (* A simple type is one that can be printed out directly, eg.
11004    * "string option".  A complex type is one which has a name and has
11005    * to be defined via another toplevel definition, eg. a struct.
11006    *
11007    * generate_type generates code for either simple or complex types.
11008    * In the simple case, it returns the string ("string option").  In
11009    * the complex case, it returns the name ("mountpoint").  In the
11010    * complex case it has to print out the definition before returning,
11011    * so it should only be called when we are at the beginning of a
11012    * new line (BOL context).
11013    *)
11014   let rec generate_type = function
11015     | Text ->                                (* string *)
11016         "string", true
11017     | Choice values ->                        (* [`val1|`val2|...] *)
11018         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11019     | ZeroOrMore rng ->                        (* <rng> list *)
11020         let t, is_simple = generate_type rng in
11021         t ^ " list (* 0 or more *)", is_simple
11022     | OneOrMore rng ->                        (* <rng> list *)
11023         let t, is_simple = generate_type rng in
11024         t ^ " list (* 1 or more *)", is_simple
11025                                         (* virt-inspector hack: bool *)
11026     | Optional (Attribute (name, [Value "1"])) ->
11027         "bool", true
11028     | Optional rng ->                        (* <rng> list *)
11029         let t, is_simple = generate_type rng in
11030         t ^ " option", is_simple
11031                                         (* type name = { fields ... } *)
11032     | Element (name, fields) when is_attrs_interleave fields ->
11033         generate_type_struct name (get_attrs_interleave fields)
11034     | Element (name, [field])                (* type name = field *)
11035     | Attribute (name, [field]) ->
11036         let t, is_simple = generate_type field in
11037         if is_simple then (t, true)
11038         else (
11039           pr "type %s = %s\n" name t;
11040           name, false
11041         )
11042     | Element (name, fields) ->              (* type name = { fields ... } *)
11043         generate_type_struct name fields
11044     | rng ->
11045         failwithf "generate_type failed at: %s" (string_of_rng rng)
11046
11047   and is_attrs_interleave = function
11048     | [Interleave _] -> true
11049     | Attribute _ :: fields -> is_attrs_interleave fields
11050     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11051     | _ -> false
11052
11053   and get_attrs_interleave = function
11054     | [Interleave fields] -> fields
11055     | ((Attribute _) as field) :: fields
11056     | ((Optional (Attribute _)) as field) :: fields ->
11057         field :: get_attrs_interleave fields
11058     | _ -> assert false
11059
11060   and generate_types xs =
11061     List.iter (fun x -> ignore (generate_type x)) xs
11062
11063   and generate_type_struct name fields =
11064     (* Calculate the types of the fields first.  We have to do this
11065      * before printing anything so we are still in BOL context.
11066      *)
11067     let types = List.map fst (List.map generate_type fields) in
11068
11069     (* Special case of a struct containing just a string and another
11070      * field.  Turn it into an assoc list.
11071      *)
11072     match types with
11073     | ["string"; other] ->
11074         let fname1, fname2 =
11075           match fields with
11076           | [f1; f2] -> name_of_field f1, name_of_field f2
11077           | _ -> assert false in
11078         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11079         name, false
11080
11081     | types ->
11082         pr "type %s = {\n" name;
11083         List.iter (
11084           fun (field, ftype) ->
11085             let fname = name_of_field field in
11086             pr "  %s_%s : %s;\n" name fname ftype
11087         ) (List.combine fields types);
11088         pr "}\n";
11089         (* Return the name of this type, and
11090          * false because it's not a simple type.
11091          *)
11092         name, false
11093   in
11094
11095   generate_types xs
11096
11097 let generate_parsers xs =
11098   (* As for generate_type above, generate_parser makes a parser for
11099    * some type, and returns the name of the parser it has generated.
11100    * Because it (may) need to print something, it should always be
11101    * called in BOL context.
11102    *)
11103   let rec generate_parser = function
11104     | Text ->                                (* string *)
11105         "string_child_or_empty"
11106     | Choice values ->                        (* [`val1|`val2|...] *)
11107         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11108           (String.concat "|"
11109              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11110     | ZeroOrMore rng ->                        (* <rng> list *)
11111         let pa = generate_parser rng in
11112         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11113     | OneOrMore rng ->                        (* <rng> list *)
11114         let pa = generate_parser rng in
11115         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11116                                         (* virt-inspector hack: bool *)
11117     | Optional (Attribute (name, [Value "1"])) ->
11118         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11119     | Optional rng ->                        (* <rng> list *)
11120         let pa = generate_parser rng in
11121         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11122                                         (* type name = { fields ... } *)
11123     | Element (name, fields) when is_attrs_interleave fields ->
11124         generate_parser_struct name (get_attrs_interleave fields)
11125     | Element (name, [field]) ->        (* type name = field *)
11126         let pa = generate_parser field in
11127         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11128         pr "let %s =\n" parser_name;
11129         pr "  %s\n" pa;
11130         pr "let parse_%s = %s\n" name parser_name;
11131         parser_name
11132     | Attribute (name, [field]) ->
11133         let pa = generate_parser field in
11134         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11135         pr "let %s =\n" parser_name;
11136         pr "  %s\n" pa;
11137         pr "let parse_%s = %s\n" name parser_name;
11138         parser_name
11139     | Element (name, fields) ->              (* type name = { fields ... } *)
11140         generate_parser_struct name ([], fields)
11141     | rng ->
11142         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11143
11144   and is_attrs_interleave = function
11145     | [Interleave _] -> true
11146     | Attribute _ :: fields -> is_attrs_interleave fields
11147     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11148     | _ -> false
11149
11150   and get_attrs_interleave = function
11151     | [Interleave fields] -> [], fields
11152     | ((Attribute _) as field) :: fields
11153     | ((Optional (Attribute _)) as field) :: fields ->
11154         let attrs, interleaves = get_attrs_interleave fields in
11155         (field :: attrs), interleaves
11156     | _ -> assert false
11157
11158   and generate_parsers xs =
11159     List.iter (fun x -> ignore (generate_parser x)) xs
11160
11161   and generate_parser_struct name (attrs, interleaves) =
11162     (* Generate parsers for the fields first.  We have to do this
11163      * before printing anything so we are still in BOL context.
11164      *)
11165     let fields = attrs @ interleaves in
11166     let pas = List.map generate_parser fields in
11167
11168     (* Generate an intermediate tuple from all the fields first.
11169      * If the type is just a string + another field, then we will
11170      * return this directly, otherwise it is turned into a record.
11171      *
11172      * RELAX NG note: This code treats <interleave> and plain lists of
11173      * fields the same.  In other words, it doesn't bother enforcing
11174      * any ordering of fields in the XML.
11175      *)
11176     pr "let parse_%s x =\n" name;
11177     pr "  let t = (\n    ";
11178     let comma = ref false in
11179     List.iter (
11180       fun x ->
11181         if !comma then pr ",\n    ";
11182         comma := true;
11183         match x with
11184         | Optional (Attribute (fname, [field])), pa ->
11185             pr "%s x" pa
11186         | Optional (Element (fname, [field])), pa ->
11187             pr "%s (optional_child %S x)" pa fname
11188         | Attribute (fname, [Text]), _ ->
11189             pr "attribute %S x" fname
11190         | (ZeroOrMore _ | OneOrMore _), pa ->
11191             pr "%s x" pa
11192         | Text, pa ->
11193             pr "%s x" pa
11194         | (field, pa) ->
11195             let fname = name_of_field field in
11196             pr "%s (child %S x)" pa fname
11197     ) (List.combine fields pas);
11198     pr "\n  ) in\n";
11199
11200     (match fields with
11201      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11202          pr "  t\n"
11203
11204      | _ ->
11205          pr "  (Obj.magic t : %s)\n" name
11206 (*
11207          List.iter (
11208            function
11209            | (Optional (Attribute (fname, [field])), pa) ->
11210                pr "  %s_%s =\n" name fname;
11211                pr "    %s x;\n" pa
11212            | (Optional (Element (fname, [field])), pa) ->
11213                pr "  %s_%s =\n" name fname;
11214                pr "    (let x = optional_child %S x in\n" fname;
11215                pr "     %s x);\n" pa
11216            | (field, pa) ->
11217                let fname = name_of_field field in
11218                pr "  %s_%s =\n" name fname;
11219                pr "    (let x = child %S x in\n" fname;
11220                pr "     %s x);\n" pa
11221          ) (List.combine fields pas);
11222          pr "}\n"
11223 *)
11224     );
11225     sprintf "parse_%s" name
11226   in
11227
11228   generate_parsers xs
11229
11230 (* Generate ocaml/guestfs_inspector.mli. *)
11231 let generate_ocaml_inspector_mli () =
11232   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11233
11234   pr "\
11235 (** This is an OCaml language binding to the external [virt-inspector]
11236     program.
11237
11238     For more information, please read the man page [virt-inspector(1)].
11239 *)
11240
11241 ";
11242
11243   generate_types grammar;
11244   pr "(** The nested information returned from the {!inspect} function. *)\n";
11245   pr "\n";
11246
11247   pr "\
11248 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11249 (** To inspect a libvirt domain called [name], pass a singleton
11250     list: [inspect [name]].  When using libvirt only, you may
11251     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11252
11253     To inspect a disk image or images, pass a list of the filenames
11254     of the disk images: [inspect filenames]
11255
11256     This function inspects the given guest or disk images and
11257     returns a list of operating system(s) found and a large amount
11258     of information about them.  In the vast majority of cases,
11259     a virtual machine only contains a single operating system.
11260
11261     If the optional [~xml] parameter is given, then this function
11262     skips running the external virt-inspector program and just
11263     parses the given XML directly (which is expected to be XML
11264     produced from a previous run of virt-inspector).  The list of
11265     names and connect URI are ignored in this case.
11266
11267     This function can throw a wide variety of exceptions, for example
11268     if the external virt-inspector program cannot be found, or if
11269     it doesn't generate valid XML.
11270 *)
11271 "
11272
11273 (* Generate ocaml/guestfs_inspector.ml. *)
11274 let generate_ocaml_inspector_ml () =
11275   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11276
11277   pr "open Unix\n";
11278   pr "\n";
11279
11280   generate_types grammar;
11281   pr "\n";
11282
11283   pr "\
11284 (* Misc functions which are used by the parser code below. *)
11285 let first_child = function
11286   | Xml.Element (_, _, c::_) -> c
11287   | Xml.Element (name, _, []) ->
11288       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11289   | Xml.PCData str ->
11290       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11291
11292 let string_child_or_empty = function
11293   | Xml.Element (_, _, [Xml.PCData s]) -> s
11294   | Xml.Element (_, _, []) -> \"\"
11295   | Xml.Element (x, _, _) ->
11296       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11297                 x ^ \" instead\")
11298   | Xml.PCData str ->
11299       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11300
11301 let optional_child name xml =
11302   let children = Xml.children xml in
11303   try
11304     Some (List.find (function
11305                      | Xml.Element (n, _, _) when n = name -> true
11306                      | _ -> false) children)
11307   with
11308     Not_found -> None
11309
11310 let child name xml =
11311   match optional_child name xml with
11312   | Some c -> c
11313   | None ->
11314       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11315
11316 let attribute name xml =
11317   try Xml.attrib xml name
11318   with Xml.No_attribute _ ->
11319     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11320
11321 ";
11322
11323   generate_parsers grammar;
11324   pr "\n";
11325
11326   pr "\
11327 (* Run external virt-inspector, then use parser to parse the XML. *)
11328 let inspect ?connect ?xml names =
11329   let xml =
11330     match xml with
11331     | None ->
11332         if names = [] then invalid_arg \"inspect: no names given\";
11333         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11334           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11335           names in
11336         let cmd = List.map Filename.quote cmd in
11337         let cmd = String.concat \" \" cmd in
11338         let chan = open_process_in cmd in
11339         let xml = Xml.parse_in chan in
11340         (match close_process_in chan with
11341          | WEXITED 0 -> ()
11342          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11343          | WSIGNALED i | WSTOPPED i ->
11344              failwith (\"external virt-inspector command died or stopped on sig \" ^
11345                        string_of_int i)
11346         );
11347         xml
11348     | Some doc ->
11349         Xml.parse_string doc in
11350   parse_operatingsystems xml
11351 "
11352
11353 (* This is used to generate the src/MAX_PROC_NR file which
11354  * contains the maximum procedure number, a surrogate for the
11355  * ABI version number.  See src/Makefile.am for the details.
11356  *)
11357 and generate_max_proc_nr () =
11358   let proc_nrs = List.map (
11359     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11360   ) daemon_functions in
11361
11362   let max_proc_nr = List.fold_left max 0 proc_nrs in
11363
11364   pr "%d\n" max_proc_nr
11365
11366 let output_to filename k =
11367   let filename_new = filename ^ ".new" in
11368   chan := open_out filename_new;
11369   k ();
11370   close_out !chan;
11371   chan := Pervasives.stdout;
11372
11373   (* Is the new file different from the current file? *)
11374   if Sys.file_exists filename && files_equal filename filename_new then
11375     unlink filename_new                 (* same, so skip it *)
11376   else (
11377     (* different, overwrite old one *)
11378     (try chmod filename 0o644 with Unix_error _ -> ());
11379     rename filename_new filename;
11380     chmod filename 0o444;
11381     printf "written %s\n%!" filename;
11382   )
11383
11384 let perror msg = function
11385   | Unix_error (err, _, _) ->
11386       eprintf "%s: %s\n" msg (error_message err)
11387   | exn ->
11388       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11389
11390 (* Main program. *)
11391 let () =
11392   let lock_fd =
11393     try openfile "HACKING" [O_RDWR] 0
11394     with
11395     | Unix_error (ENOENT, _, _) ->
11396         eprintf "\
11397 You are probably running this from the wrong directory.
11398 Run it from the top source directory using the command
11399   src/generator.ml
11400 ";
11401         exit 1
11402     | exn ->
11403         perror "open: HACKING" exn;
11404         exit 1 in
11405
11406   (* Acquire a lock so parallel builds won't try to run the generator
11407    * twice at the same time.  Subsequent builds will wait for the first
11408    * one to finish.  Note the lock is released implicitly when the
11409    * program exits.
11410    *)
11411   (try lockf lock_fd F_LOCK 1
11412    with exn ->
11413      perror "lock: HACKING" exn;
11414      exit 1);
11415
11416   check_functions ();
11417
11418   output_to "src/guestfs_protocol.x" generate_xdr;
11419   output_to "src/guestfs-structs.h" generate_structs_h;
11420   output_to "src/guestfs-actions.h" generate_actions_h;
11421   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11422   output_to "src/guestfs-actions.c" generate_client_actions;
11423   output_to "src/guestfs-bindtests.c" generate_bindtests;
11424   output_to "src/guestfs-structs.pod" generate_structs_pod;
11425   output_to "src/guestfs-actions.pod" generate_actions_pod;
11426   output_to "src/guestfs-availability.pod" generate_availability_pod;
11427   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11428   output_to "src/libguestfs.syms" generate_linker_script;
11429   output_to "daemon/actions.h" generate_daemon_actions_h;
11430   output_to "daemon/stubs.c" generate_daemon_actions;
11431   output_to "daemon/names.c" generate_daemon_names;
11432   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11433   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11434   output_to "capitests/tests.c" generate_tests;
11435   output_to "fish/cmds.c" generate_fish_cmds;
11436   output_to "fish/completion.c" generate_fish_completion;
11437   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11438   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11439   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11440   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11441   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11442   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11443   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11444   output_to "perl/Guestfs.xs" generate_perl_xs;
11445   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11446   output_to "perl/bindtests.pl" generate_perl_bindtests;
11447   output_to "python/guestfs-py.c" generate_python_c;
11448   output_to "python/guestfs.py" generate_python_py;
11449   output_to "python/bindtests.py" generate_python_bindtests;
11450   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11451   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11452   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11453
11454   List.iter (
11455     fun (typ, jtyp) ->
11456       let cols = cols_of_struct typ in
11457       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11458       output_to filename (generate_java_struct jtyp cols);
11459   ) java_structs;
11460
11461   output_to "java/Makefile.inc" generate_java_makefile_inc;
11462   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11463   output_to "java/Bindtests.java" generate_java_bindtests;
11464   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11465   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11466   output_to "csharp/Libguestfs.cs" generate_csharp;
11467
11468   (* Always generate this file last, and unconditionally.  It's used
11469    * by the Makefile to know when we must re-run the generator.
11470    *)
11471   let chan = open_out "src/stamp-generator" in
11472   fprintf chan "1\n";
11473   close_out chan;
11474
11475   printf "generated %d lines of code\n" !lines