c01e265b39ce96c16caafc49a252b0799d0421e0
[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   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<val>.
1254
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL.  Due to an oversight in the libguestfs API
1257 you cannot do that with this call.  Instead you must use the
1258 C<guestfs_aug_clear> call.");
1259
1260   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "insert a sibling Augeas node",
1263    "\
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1266 flag C<before>).
1267
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1271
1272   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273    [], (* XXX Augeas code needs tests. *)
1274    "remove an Augeas path",
1275    "\
1276 Remove C<path> and all of its children.
1277
1278 On success this returns the number of entries which were removed.");
1279
1280   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "move Augeas node",
1283    "\
1284 Move the node C<src> to C<dest>.  C<src> must match exactly
1285 one node.  C<dest> is overwritten if it exists.");
1286
1287   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "return Augeas nodes which match augpath",
1290    "\
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1294
1295   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "write all pending Augeas changes to disk",
1298    "\
1299 This writes all pending changes to disk.
1300
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1303
1304   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "load files into the tree",
1307    "\
1308 Load files into the tree.
1309
1310 See C<aug_load> in the Augeas documentation for the full gory
1311 details.");
1312
1313   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "list Augeas nodes under augpath",
1316    "\
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1319
1320   ("rm", (RErr, [Pathname "path"]), 29, [],
1321    [InitBasicFS, Always, TestRun
1322       [["touch"; "/new"];
1323        ["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["rm"; "/new"]];
1326     InitBasicFS, Always, TestLastFail
1327       [["mkdir"; "/new"];
1328        ["rm"; "/new"]]],
1329    "remove a file",
1330    "\
1331 Remove the single file C<path>.");
1332
1333   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334    [InitBasicFS, Always, TestRun
1335       [["mkdir"; "/new"];
1336        ["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["rmdir"; "/new"]];
1339     InitBasicFS, Always, TestLastFail
1340       [["touch"; "/new"];
1341        ["rmdir"; "/new"]]],
1342    "remove a directory",
1343    "\
1344 Remove the single directory C<path>.");
1345
1346   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347    [InitBasicFS, Always, TestOutputFalse
1348       [["mkdir"; "/new"];
1349        ["mkdir"; "/new/foo"];
1350        ["touch"; "/new/foo/bar"];
1351        ["rm_rf"; "/new"];
1352        ["exists"; "/new"]]],
1353    "remove a file or directory recursively",
1354    "\
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory.  This is like the C<rm -rf> shell
1357 command.");
1358
1359   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360    [InitBasicFS, Always, TestOutputTrue
1361       [["mkdir"; "/new"];
1362        ["is_dir"; "/new"]];
1363     InitBasicFS, Always, TestLastFail
1364       [["mkdir"; "/new/foo/bar"]]],
1365    "create a directory",
1366    "\
1367 Create a directory named C<path>.");
1368
1369   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370    [InitBasicFS, Always, TestOutputTrue
1371       [["mkdir_p"; "/new/foo/bar"];
1372        ["is_dir"; "/new/foo/bar"]];
1373     InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new"]];
1379     (* Regression tests for RHBZ#503133: *)
1380     InitBasicFS, Always, TestRun
1381       [["mkdir"; "/new"];
1382        ["mkdir_p"; "/new"]];
1383     InitBasicFS, Always, TestLastFail
1384       [["touch"; "/new"];
1385        ["mkdir_p"; "/new"]]],
1386    "create a directory and parents",
1387    "\
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary.  This is like the C<mkdir -p> shell command.");
1390
1391   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392    [], (* XXX Need stat command to test *)
1393    "change file mode",
1394    "\
1395 Change the mode (permissions) of C<path> to C<mode>.  Only
1396 numeric modes are supported.
1397
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1401
1402 The mode actually set is affected by the umask.");
1403
1404   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405    [], (* XXX Need stat command to test *)
1406    "change file owner and group",
1407    "\
1408 Change the file owner to C<owner> and group to C<group>.
1409
1410 Only numeric uid and gid are supported.  If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1413
1414   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415    [InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/empty"]]);
1417     InitISOFS, Always, TestOutputTrue (
1418       [["exists"; "/directory"]])],
1419    "test if file or directory exists",
1420    "\
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1423
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1425
1426   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427    [InitISOFS, Always, TestOutputTrue (
1428       [["is_file"; "/known-1"]]);
1429     InitISOFS, Always, TestOutputFalse (
1430       [["is_file"; "/directory"]])],
1431    "test if file exists",
1432    "\
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name.  Note that it returns false for
1435 other objects like directories.
1436
1437 See also C<guestfs_stat>.");
1438
1439   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440    [InitISOFS, Always, TestOutputFalse (
1441       [["is_dir"; "/known-3"]]);
1442     InitISOFS, Always, TestOutputTrue (
1443       [["is_dir"; "/directory"]])],
1444    "test if file exists",
1445    "\
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name.  Note that it returns false for
1448 other objects like files.
1449
1450 See also C<guestfs_stat>.");
1451
1452   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453    [InitEmpty, Always, TestOutputListOfDevices (
1454       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455        ["pvcreate"; "/dev/sda1"];
1456        ["pvcreate"; "/dev/sda2"];
1457        ["pvcreate"; "/dev/sda3"];
1458        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459    "create an LVM physical volume",
1460    "\
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1463 as C</dev/sda1>.");
1464
1465   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466    [InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468        ["pvcreate"; "/dev/sda1"];
1469        ["pvcreate"; "/dev/sda2"];
1470        ["pvcreate"; "/dev/sda3"];
1471        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472        ["vgcreate"; "VG2"; "/dev/sda3"];
1473        ["vgs"]], ["VG1"; "VG2"])],
1474    "create an LVM volume group",
1475    "\
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1478
1479   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480    [InitEmpty, Always, TestOutputList (
1481       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482        ["pvcreate"; "/dev/sda1"];
1483        ["pvcreate"; "/dev/sda2"];
1484        ["pvcreate"; "/dev/sda3"];
1485        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486        ["vgcreate"; "VG2"; "/dev/sda3"];
1487        ["lvcreate"; "LV1"; "VG1"; "50"];
1488        ["lvcreate"; "LV2"; "VG1"; "50"];
1489        ["lvcreate"; "LV3"; "VG2"; "50"];
1490        ["lvcreate"; "LV4"; "VG2"; "50"];
1491        ["lvcreate"; "LV5"; "VG2"; "50"];
1492        ["lvs"]],
1493       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495    "create an LVM logical volume",
1496    "\
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1499
1500   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501    [InitEmpty, Always, TestOutput (
1502       [["part_disk"; "/dev/sda"; "mbr"];
1503        ["mkfs"; "ext2"; "/dev/sda1"];
1504        ["mount_options"; ""; "/dev/sda1"; "/"];
1505        ["write_file"; "/new"; "new file contents"; "0"];
1506        ["cat"; "/new"]], "new file contents")],
1507    "make a filesystem",
1508    "\
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume).  The filesystem type is C<fstype>, for
1511 example C<ext3>.");
1512
1513   ("sfdisk", (RErr, [Device "device";
1514                      Int "cyls"; Int "heads"; Int "sectors";
1515                      StringList "lines"]), 43, [DangerWillRobinson],
1516    [],
1517    "create partitions on a block device",
1518    "\
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1521
1522 C<device> should be a block device, for example C</dev/sda>.
1523
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted.  Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1531
1532 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1533 information refer to the L<sfdisk(8)> manpage.
1534
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1538
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1541
1542   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543    [InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; "new file contents"; "0"];
1545        ["cat"; "/new"]], "new file contents");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548        ["cat"; "/new"]], "\nnew file contents\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n\n"; "0"];
1551        ["cat"; "/new"]], "\n\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["write_file"; "/new"; ""; "0"];
1554        ["cat"; "/new"]], "");
1555     InitBasicFS, Always, TestOutput (
1556       [["write_file"; "/new"; "\n\n\n"; "0"];
1557        ["cat"; "/new"]], "\n\n\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["write_file"; "/new"; "\n"; "0"];
1560        ["cat"; "/new"]], "\n")],
1561    "create a file",
1562    "\
1563 This call creates a file called C<path>.  The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1566
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1570
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version.  In the meantime
1574 use C<guestfs_upload>.");
1575
1576   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577    [InitEmpty, Always, TestOutputListOfDevices (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["mounts"]], ["/dev/sda1"]);
1582     InitEmpty, Always, TestOutputList (
1583       [["part_disk"; "/dev/sda"; "mbr"];
1584        ["mkfs"; "ext2"; "/dev/sda1"];
1585        ["mount_options"; ""; "/dev/sda1"; "/"];
1586        ["umount"; "/"];
1587        ["mounts"]], [])],
1588    "unmount a filesystem",
1589    "\
1590 This unmounts the given filesystem.  The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1593
1594   ("mounts", (RStringList "devices", []), 46, [],
1595    [InitBasicFS, Always, TestOutputListOfDevices (
1596       [["mounts"]], ["/dev/sda1"])],
1597    "show mounted filesystems",
1598    "\
1599 This returns the list of currently mounted filesystems.  It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1601
1602 Some internal mounts are not shown.
1603
1604 See also: C<guestfs_mountpoints>");
1605
1606   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607    [InitBasicFS, Always, TestOutputList (
1608       [["umount_all"];
1609        ["mounts"]], []);
1610     (* check that umount_all can unmount nested mounts correctly: *)
1611     InitEmpty, Always, TestOutputList (
1612       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613        ["mkfs"; "ext2"; "/dev/sda1"];
1614        ["mkfs"; "ext2"; "/dev/sda2"];
1615        ["mkfs"; "ext2"; "/dev/sda3"];
1616        ["mount_options"; ""; "/dev/sda1"; "/"];
1617        ["mkdir"; "/mp1"];
1618        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619        ["mkdir"; "/mp1/mp2"];
1620        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621        ["mkdir"; "/mp1/mp2/mp3"];
1622        ["umount_all"];
1623        ["mounts"]], [])],
1624    "unmount all filesystems",
1625    "\
1626 This unmounts all mounted filesystems.
1627
1628 Some internal mounts are not unmounted by this call.");
1629
1630   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1631    [],
1632    "remove all LVM LVs, VGs and PVs",
1633    "\
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1636
1637   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638    [InitISOFS, Always, TestOutput (
1639       [["file"; "/empty"]], "empty");
1640     InitISOFS, Always, TestOutput (
1641       [["file"; "/known-1"]], "ASCII text");
1642     InitISOFS, Always, TestLastFail (
1643       [["file"; "/notexists"]])],
1644    "determine file type",
1645    "\
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file.  This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1649
1650 This call will also transparently look inside various types
1651 of compressed file.
1652
1653 The exact command which runs is C<file -zbsL path>.  Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1656
1657   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658    [InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 1"]], "Result1");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 2"]], "Result2\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 3"]], "\nResult3");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 4"]], "\nResult4\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 5"]], "\nResult5\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 7"]], "");
1686     InitBasicFS, Always, TestOutput (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command 8"]], "\n");
1690     InitBasicFS, Always, TestOutput (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command"; "/test-command 9"]], "\n\n");
1694     InitBasicFS, Always, TestOutput (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698     InitBasicFS, Always, TestOutput (
1699       [["upload"; "test-command"; "/test-command"];
1700        ["chmod"; "0o755"; "/test-command"];
1701        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702     InitBasicFS, Always, TestLastFail (
1703       [["upload"; "test-command"; "/test-command"];
1704        ["chmod"; "0o755"; "/test-command"];
1705        ["command"; "/test-command"]])],
1706    "run a command from the guest filesystem",
1707    "\
1708 This call runs a command from the guest filesystem.  The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1712
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters.  The list must be
1716 non-empty (ie. must contain a program name).  Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1719
1720 The return value is anything printed to I<stdout> by
1721 the command.
1722
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message.  The error message
1725 string is the content of I<stderr> from the command.
1726
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>.  If you require a program from
1729 another location, you should provide the full path in the
1730 first parameter.
1731
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places.  It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1736 locations.");
1737
1738   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739    [InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 1"]], ["Result1"]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 2"]], ["Result2"]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 7"]], []);
1767     InitBasicFS, Always, TestOutputList (
1768       [["upload"; "test-command"; "/test-command"];
1769        ["chmod"; "0o755"; "/test-command"];
1770        ["command_lines"; "/test-command 8"]], [""]);
1771     InitBasicFS, Always, TestOutputList (
1772       [["upload"; "test-command"; "/test-command"];
1773        ["chmod"; "0o755"; "/test-command"];
1774        ["command_lines"; "/test-command 9"]], ["";""]);
1775     InitBasicFS, Always, TestOutputList (
1776       [["upload"; "test-command"; "/test-command"];
1777        ["chmod"; "0o755"; "/test-command"];
1778        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779     InitBasicFS, Always, TestOutputList (
1780       [["upload"; "test-command"; "/test-command"];
1781        ["chmod"; "0o755"; "/test-command"];
1782        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783    "run a command, returning lines",
1784    "\
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1787
1788 See also: C<guestfs_sh_lines>");
1789
1790   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as the C<stat(2)> system call.");
1798
1799   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800    [InitISOFS, Always, TestOutputStruct (
1801       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802    "get file information for a symbolic link",
1803    "\
1804 Returns file information for the given C<path>.
1805
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1808 refers to.
1809
1810 This is the same as the C<lstat(2)> system call.");
1811
1812   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813    [InitISOFS, Always, TestOutputStruct (
1814       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815    "get file system statistics",
1816    "\
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1820
1821 This is the same as the C<statvfs(2)> system call.");
1822
1823   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1824    [], (* XXX test *)
1825    "get ext2/ext3/ext4 superblock details",
1826    "\
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1829
1830 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1831 manpage for more details.  The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1834
1835   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "set block device to read-only",
1840    "\
1841 Sets the block device named C<device> to read-only.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846    [InitEmpty, Always, TestOutputFalse (
1847       [["blockdev_setrw"; "/dev/sda"];
1848        ["blockdev_getro"; "/dev/sda"]])],
1849    "set block device to read-write",
1850    "\
1851 Sets the block device named C<device> to read-write.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856    [InitEmpty, Always, TestOutputTrue (
1857       [["blockdev_setro"; "/dev/sda"];
1858        ["blockdev_getro"; "/dev/sda"]])],
1859    "is block device set to read-only",
1860    "\
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1863
1864 This uses the L<blockdev(8)> command.");
1865
1866   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867    [InitEmpty, Always, TestOutputInt (
1868       [["blockdev_getss"; "/dev/sda"]], 512)],
1869    "get sectorsize of block device",
1870    "\
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1873
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 for that).
1876
1877 This uses the L<blockdev(8)> command.");
1878
1879   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880    [InitEmpty, Always, TestOutputInt (
1881       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882    "get blocksize of block device",
1883    "\
1884 This returns the block size of a device.
1885
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1892    [], (* XXX test *)
1893    "set blocksize of block device",
1894    "\
1895 This sets the block size of a device.
1896
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905    "get total size of device in 512-byte sectors",
1906    "\
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1909
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917    [InitEmpty, Always, TestOutputInt (
1918       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919    "get total size of device in bytes",
1920    "\
1921 This returns the size of the device in bytes.
1922
1923 See also C<guestfs_blockdev_getsz>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928    [InitEmpty, Always, TestRun
1929       [["blockdev_flushbufs"; "/dev/sda"]]],
1930    "flush device buffers",
1931    "\
1932 This tells the kernel to flush internal buffers associated
1933 with C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938    [InitEmpty, Always, TestRun
1939       [["blockdev_rereadpt"; "/dev/sda"]]],
1940    "reread partition table",
1941    "\
1942 Reread the partition table on C<device>.
1943
1944 This uses the L<blockdev(8)> command.");
1945
1946   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947    [InitBasicFS, Always, TestOutput (
1948       (* Pick a file from cwd which isn't likely to change. *)
1949       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950        ["checksum"; "md5"; "/COPYING.LIB"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "upload a file from the local machine",
1953    "\
1954 Upload local file C<filename> to C<remotefilename> on the
1955 filesystem.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_download>.");
1960
1961   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962    [InitBasicFS, Always, TestOutput (
1963       (* Pick a file from cwd which isn't likely to change. *)
1964       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966        ["upload"; "testdownload.tmp"; "/upload"];
1967        ["checksum"; "md5"; "/upload"]],
1968       Digest.to_hex (Digest.file "COPYING.LIB"))],
1969    "download a file to the local machine",
1970    "\
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1973
1974 C<filename> can also be a named pipe.
1975
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1977
1978   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979    [InitISOFS, Always, TestOutput (
1980       [["checksum"; "crc"; "/known-3"]], "2891671662");
1981     InitISOFS, Always, TestLastFail (
1982       [["checksum"; "crc"; "/notexists"]]);
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987     InitISOFS, Always, TestOutput (
1988       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989     InitISOFS, Always, TestOutput (
1990       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991     InitISOFS, Always, TestOutput (
1992       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993     InitISOFS, Always, TestOutput (
1994       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1995     (* Test for RHBZ#579608, absolute symbolic links. *)
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1998    "compute MD5, SHAx or CRC checksum of file",
1999    "\
2000 This call computes the MD5, SHAx or CRC checksum of the
2001 file named C<path>.
2002
2003 The type of checksum to compute is given by the C<csumtype>
2004 parameter which must have one of the following values:
2005
2006 =over 4
2007
2008 =item C<crc>
2009
2010 Compute the cyclic redundancy check (CRC) specified by POSIX
2011 for the C<cksum> command.
2012
2013 =item C<md5>
2014
2015 Compute the MD5 hash (using the C<md5sum> program).
2016
2017 =item C<sha1>
2018
2019 Compute the SHA1 hash (using the C<sha1sum> program).
2020
2021 =item C<sha224>
2022
2023 Compute the SHA224 hash (using the C<sha224sum> program).
2024
2025 =item C<sha256>
2026
2027 Compute the SHA256 hash (using the C<sha256sum> program).
2028
2029 =item C<sha384>
2030
2031 Compute the SHA384 hash (using the C<sha384sum> program).
2032
2033 =item C<sha512>
2034
2035 Compute the SHA512 hash (using the C<sha512sum> program).
2036
2037 =back
2038
2039 The checksum is returned as a printable string.
2040
2041 To get the checksum for a device, use C<guestfs_checksum_device>.
2042
2043 To get the checksums for many files, use C<guestfs_checksums_out>.");
2044
2045   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2046    [InitBasicFS, Always, TestOutput (
2047       [["tar_in"; "../images/helloworld.tar"; "/"];
2048        ["cat"; "/hello"]], "hello\n")],
2049    "unpack tarfile to directory",
2050    "\
2051 This command uploads and unpacks local file C<tarfile> (an
2052 I<uncompressed> tar file) into C<directory>.
2053
2054 To upload a compressed tarball, use C<guestfs_tgz_in>
2055 or C<guestfs_txz_in>.");
2056
2057   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2058    [],
2059    "pack directory into tarfile",
2060    "\
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarfile>.
2063
2064 To download a compressed tarball, use C<guestfs_tgz_out>
2065 or C<guestfs_txz_out>.");
2066
2067   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2068    [InitBasicFS, Always, TestOutput (
2069       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2070        ["cat"; "/hello"]], "hello\n")],
2071    "unpack compressed tarball to directory",
2072    "\
2073 This command uploads and unpacks local file C<tarball> (a
2074 I<gzip compressed> tar file) into C<directory>.
2075
2076 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2077
2078   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2079    [],
2080    "pack directory into compressed tarball",
2081    "\
2082 This command packs the contents of C<directory> and downloads
2083 it to local file C<tarball>.
2084
2085 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2086
2087   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2088    [InitBasicFS, Always, TestLastFail (
2089       [["umount"; "/"];
2090        ["mount_ro"; "/dev/sda1"; "/"];
2091        ["touch"; "/new"]]);
2092     InitBasicFS, Always, TestOutput (
2093       [["write_file"; "/new"; "data"; "0"];
2094        ["umount"; "/"];
2095        ["mount_ro"; "/dev/sda1"; "/"];
2096        ["cat"; "/new"]], "data")],
2097    "mount a guest disk, read-only",
2098    "\
2099 This is the same as the C<guestfs_mount> command, but it
2100 mounts the filesystem with the read-only (I<-o ro>) flag.");
2101
2102   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2103    [],
2104    "mount a guest disk with mount options",
2105    "\
2106 This is the same as the C<guestfs_mount> command, but it
2107 allows you to set the mount options as for the
2108 L<mount(8)> I<-o> flag.
2109
2110 If the C<options> parameter is an empty string, then
2111 no options are passed (all options default to whatever
2112 the filesystem uses).");
2113
2114   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2115    [],
2116    "mount a guest disk with mount options and vfstype",
2117    "\
2118 This is the same as the C<guestfs_mount> command, but it
2119 allows you to set both the mount options and the vfstype
2120 as for the L<mount(8)> I<-o> and I<-t> flags.");
2121
2122   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2123    [],
2124    "debugging and internals",
2125    "\
2126 The C<guestfs_debug> command exposes some internals of
2127 C<guestfsd> (the guestfs daemon) that runs inside the
2128 qemu subprocess.
2129
2130 There is no comprehensive help for this command.  You have
2131 to look at the file C<daemon/debug.c> in the libguestfs source
2132 to find out what you can do.");
2133
2134   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2135    [InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG/LV1"];
2142        ["lvs"]], ["/dev/VG/LV2"]);
2143     InitEmpty, Always, TestOutputList (
2144       [["part_disk"; "/dev/sda"; "mbr"];
2145        ["pvcreate"; "/dev/sda1"];
2146        ["vgcreate"; "VG"; "/dev/sda1"];
2147        ["lvcreate"; "LV1"; "VG"; "50"];
2148        ["lvcreate"; "LV2"; "VG"; "50"];
2149        ["lvremove"; "/dev/VG"];
2150        ["lvs"]], []);
2151     InitEmpty, Always, TestOutputList (
2152       [["part_disk"; "/dev/sda"; "mbr"];
2153        ["pvcreate"; "/dev/sda1"];
2154        ["vgcreate"; "VG"; "/dev/sda1"];
2155        ["lvcreate"; "LV1"; "VG"; "50"];
2156        ["lvcreate"; "LV2"; "VG"; "50"];
2157        ["lvremove"; "/dev/VG"];
2158        ["vgs"]], ["VG"])],
2159    "remove an LVM logical volume",
2160    "\
2161 Remove an LVM logical volume C<device>, where C<device> is
2162 the path to the LV, such as C</dev/VG/LV>.
2163
2164 You can also remove all LVs in a volume group by specifying
2165 the VG name, C</dev/VG>.");
2166
2167   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2168    [InitEmpty, Always, TestOutputList (
2169       [["part_disk"; "/dev/sda"; "mbr"];
2170        ["pvcreate"; "/dev/sda1"];
2171        ["vgcreate"; "VG"; "/dev/sda1"];
2172        ["lvcreate"; "LV1"; "VG"; "50"];
2173        ["lvcreate"; "LV2"; "VG"; "50"];
2174        ["vgremove"; "VG"];
2175        ["lvs"]], []);
2176     InitEmpty, Always, TestOutputList (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["vgs"]], [])],
2184    "remove an LVM volume group",
2185    "\
2186 Remove an LVM volume group C<vgname>, (for example C<VG>).
2187
2188 This also forcibly removes all logical volumes in the volume
2189 group (if any).");
2190
2191   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2192    [InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["lvs"]], []);
2201     InitEmpty, Always, TestOutputListOfDevices (
2202       [["part_disk"; "/dev/sda"; "mbr"];
2203        ["pvcreate"; "/dev/sda1"];
2204        ["vgcreate"; "VG"; "/dev/sda1"];
2205        ["lvcreate"; "LV1"; "VG"; "50"];
2206        ["lvcreate"; "LV2"; "VG"; "50"];
2207        ["vgremove"; "VG"];
2208        ["pvremove"; "/dev/sda1"];
2209        ["vgs"]], []);
2210     InitEmpty, Always, TestOutputListOfDevices (
2211       [["part_disk"; "/dev/sda"; "mbr"];
2212        ["pvcreate"; "/dev/sda1"];
2213        ["vgcreate"; "VG"; "/dev/sda1"];
2214        ["lvcreate"; "LV1"; "VG"; "50"];
2215        ["lvcreate"; "LV2"; "VG"; "50"];
2216        ["vgremove"; "VG"];
2217        ["pvremove"; "/dev/sda1"];
2218        ["pvs"]], [])],
2219    "remove an LVM physical volume",
2220    "\
2221 This wipes a physical volume C<device> so that LVM will no longer
2222 recognise it.
2223
2224 The implementation uses the C<pvremove> command which refuses to
2225 wipe physical volumes that contain any volume groups, so you have
2226 to remove those first.");
2227
2228   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2229    [InitBasicFS, Always, TestOutput (
2230       [["set_e2label"; "/dev/sda1"; "testlabel"];
2231        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2232    "set the ext2/3/4 filesystem label",
2233    "\
2234 This sets the ext2/3/4 filesystem label of the filesystem on
2235 C<device> to C<label>.  Filesystem labels are limited to
2236 16 characters.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2239 to return the existing label on a filesystem.");
2240
2241   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2242    [],
2243    "get the ext2/3/4 filesystem label",
2244    "\
2245 This returns the ext2/3/4 filesystem label of the filesystem on
2246 C<device>.");
2247
2248   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2249    (let uuid = uuidgen () in
2250     [InitBasicFS, Always, TestOutput (
2251        [["set_e2uuid"; "/dev/sda1"; uuid];
2252         ["get_e2uuid"; "/dev/sda1"]], uuid);
2253      InitBasicFS, Always, TestOutput (
2254        [["set_e2uuid"; "/dev/sda1"; "clear"];
2255         ["get_e2uuid"; "/dev/sda1"]], "");
2256      (* We can't predict what UUIDs will be, so just check the commands run. *)
2257      InitBasicFS, Always, TestRun (
2258        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2259      InitBasicFS, Always, TestRun (
2260        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2261    "set the ext2/3/4 filesystem UUID",
2262    "\
2263 This sets the ext2/3/4 filesystem UUID of the filesystem on
2264 C<device> to C<uuid>.  The format of the UUID and alternatives
2265 such as C<clear>, C<random> and C<time> are described in the
2266 L<tune2fs(8)> manpage.
2267
2268 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2269 to return the existing UUID of a filesystem.");
2270
2271   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2272    [],
2273    "get the ext2/3/4 filesystem UUID",
2274    "\
2275 This returns the ext2/3/4 filesystem UUID of the filesystem on
2276 C<device>.");
2277
2278   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2279    [InitBasicFS, Always, TestOutputInt (
2280       [["umount"; "/dev/sda1"];
2281        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2282     InitBasicFS, Always, TestOutputInt (
2283       [["umount"; "/dev/sda1"];
2284        ["zero"; "/dev/sda1"];
2285        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2286    "run the filesystem checker",
2287    "\
2288 This runs the filesystem checker (fsck) on C<device> which
2289 should have filesystem type C<fstype>.
2290
2291 The returned integer is the status.  See L<fsck(8)> for the
2292 list of status codes from C<fsck>.
2293
2294 Notes:
2295
2296 =over 4
2297
2298 =item *
2299
2300 Multiple status codes can be summed together.
2301
2302 =item *
2303
2304 A non-zero return code can mean \"success\", for example if
2305 errors have been corrected on the filesystem.
2306
2307 =item *
2308
2309 Checking or repairing NTFS volumes is not supported
2310 (by linux-ntfs).
2311
2312 =back
2313
2314 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2315
2316   ("zero", (RErr, [Device "device"]), 85, [],
2317    [InitBasicFS, Always, TestOutput (
2318       [["umount"; "/dev/sda1"];
2319        ["zero"; "/dev/sda1"];
2320        ["file"; "/dev/sda1"]], "data")],
2321    "write zeroes to the device",
2322    "\
2323 This command writes zeroes over the first few blocks of C<device>.
2324
2325 How many blocks are zeroed isn't specified (but it's I<not> enough
2326 to securely wipe the device).  It should be sufficient to remove
2327 any partition tables, filesystem superblocks and so on.
2328
2329 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2330
2331   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2332    (* Test disabled because grub-install incompatible with virtio-blk driver.
2333     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2334     *)
2335    [InitBasicFS, Disabled, TestOutputTrue (
2336       [["grub_install"; "/"; "/dev/sda1"];
2337        ["is_dir"; "/boot"]])],
2338    "install GRUB",
2339    "\
2340 This command installs GRUB (the Grand Unified Bootloader) on
2341 C<device>, with the root directory being C<root>.");
2342
2343   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2344    [InitBasicFS, Always, TestOutput (
2345       [["write_file"; "/old"; "file content"; "0"];
2346        ["cp"; "/old"; "/new"];
2347        ["cat"; "/new"]], "file content");
2348     InitBasicFS, Always, TestOutputTrue (
2349       [["write_file"; "/old"; "file content"; "0"];
2350        ["cp"; "/old"; "/new"];
2351        ["is_file"; "/old"]]);
2352     InitBasicFS, Always, TestOutput (
2353       [["write_file"; "/old"; "file content"; "0"];
2354        ["mkdir"; "/dir"];
2355        ["cp"; "/old"; "/dir/new"];
2356        ["cat"; "/dir/new"]], "file content")],
2357    "copy a file",
2358    "\
2359 This copies a file from C<src> to C<dest> where C<dest> is
2360 either a destination filename or destination directory.");
2361
2362   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2363    [InitBasicFS, Always, TestOutput (
2364       [["mkdir"; "/olddir"];
2365        ["mkdir"; "/newdir"];
2366        ["write_file"; "/olddir/file"; "file content"; "0"];
2367        ["cp_a"; "/olddir"; "/newdir"];
2368        ["cat"; "/newdir/olddir/file"]], "file content")],
2369    "copy a file or directory recursively",
2370    "\
2371 This copies a file or directory from C<src> to C<dest>
2372 recursively using the C<cp -a> command.");
2373
2374   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2375    [InitBasicFS, Always, TestOutput (
2376       [["write_file"; "/old"; "file content"; "0"];
2377        ["mv"; "/old"; "/new"];
2378        ["cat"; "/new"]], "file content");
2379     InitBasicFS, Always, TestOutputFalse (
2380       [["write_file"; "/old"; "file content"; "0"];
2381        ["mv"; "/old"; "/new"];
2382        ["is_file"; "/old"]])],
2383    "move a file",
2384    "\
2385 This moves a file from C<src> to C<dest> where C<dest> is
2386 either a destination filename or destination directory.");
2387
2388   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2389    [InitEmpty, Always, TestRun (
2390       [["drop_caches"; "3"]])],
2391    "drop kernel page cache, dentries and inodes",
2392    "\
2393 This instructs the guest kernel to drop its page cache,
2394 and/or dentries and inode caches.  The parameter C<whattodrop>
2395 tells the kernel what precisely to drop, see
2396 L<http://linux-mm.org/Drop_Caches>
2397
2398 Setting C<whattodrop> to 3 should drop everything.
2399
2400 This automatically calls L<sync(2)> before the operation,
2401 so that the maximum guest memory is freed.");
2402
2403   ("dmesg", (RString "kmsgs", []), 91, [],
2404    [InitEmpty, Always, TestRun (
2405       [["dmesg"]])],
2406    "return kernel messages",
2407    "\
2408 This returns the kernel messages (C<dmesg> output) from
2409 the guest kernel.  This is sometimes useful for extended
2410 debugging of problems.
2411
2412 Another way to get the same information is to enable
2413 verbose messages with C<guestfs_set_verbose> or by setting
2414 the environment variable C<LIBGUESTFS_DEBUG=1> before
2415 running the program.");
2416
2417   ("ping_daemon", (RErr, []), 92, [],
2418    [InitEmpty, Always, TestRun (
2419       [["ping_daemon"]])],
2420    "ping the guest daemon",
2421    "\
2422 This is a test probe into the guestfs daemon running inside
2423 the qemu subprocess.  Calling this function checks that the
2424 daemon responds to the ping message, without affecting the daemon
2425 or attached block device(s) in any other way.");
2426
2427   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2428    [InitBasicFS, Always, TestOutputTrue (
2429       [["write_file"; "/file1"; "contents of a file"; "0"];
2430        ["cp"; "/file1"; "/file2"];
2431        ["equal"; "/file1"; "/file2"]]);
2432     InitBasicFS, Always, TestOutputFalse (
2433       [["write_file"; "/file1"; "contents of a file"; "0"];
2434        ["write_file"; "/file2"; "contents of another file"; "0"];
2435        ["equal"; "/file1"; "/file2"]]);
2436     InitBasicFS, Always, TestLastFail (
2437       [["equal"; "/file1"; "/file2"]])],
2438    "test if two files have equal contents",
2439    "\
2440 This compares the two files C<file1> and C<file2> and returns
2441 true if their content is exactly equal, or false otherwise.
2442
2443 The external L<cmp(1)> program is used for the comparison.");
2444
2445   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2446    [InitISOFS, Always, TestOutputList (
2447       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2448     InitISOFS, Always, TestOutputList (
2449       [["strings"; "/empty"]], []);
2450     (* Test for RHBZ#579608, absolute symbolic links. *)
2451     InitISOFS, Always, TestRun (
2452       [["strings"; "/abssymlink"]])],
2453    "print the printable strings in a file",
2454    "\
2455 This runs the L<strings(1)> command on a file and returns
2456 the list of printable strings found.");
2457
2458   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2459    [InitISOFS, Always, TestOutputList (
2460       [["strings_e"; "b"; "/known-5"]], []);
2461     InitBasicFS, Disabled, TestOutputList (
2462       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2463        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2464    "print the printable strings in a file",
2465    "\
2466 This is like the C<guestfs_strings> command, but allows you to
2467 specify the encoding.
2468
2469 See the L<strings(1)> manpage for the full list of encodings.
2470
2471 Commonly useful encodings are C<l> (lower case L) which will
2472 show strings inside Windows/x86 files.
2473
2474 The returned strings are transcoded to UTF-8.");
2475
2476   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2477    [InitISOFS, Always, TestOutput (
2478       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2479     (* Test for RHBZ#501888c2 regression which caused large hexdump
2480      * commands to segfault.
2481      *)
2482     InitISOFS, Always, TestRun (
2483       [["hexdump"; "/100krandom"]]);
2484     (* Test for RHBZ#579608, absolute symbolic links. *)
2485     InitISOFS, Always, TestRun (
2486       [["hexdump"; "/abssymlink"]])],
2487    "dump a file in hexadecimal",
2488    "\
2489 This runs C<hexdump -C> on the given C<path>.  The result is
2490 the human-readable, canonical hex dump of the file.");
2491
2492   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2493    [InitNone, Always, TestOutput (
2494       [["part_disk"; "/dev/sda"; "mbr"];
2495        ["mkfs"; "ext3"; "/dev/sda1"];
2496        ["mount_options"; ""; "/dev/sda1"; "/"];
2497        ["write_file"; "/new"; "test file"; "0"];
2498        ["umount"; "/dev/sda1"];
2499        ["zerofree"; "/dev/sda1"];
2500        ["mount_options"; ""; "/dev/sda1"; "/"];
2501        ["cat"; "/new"]], "test file")],
2502    "zero unused inodes and disk blocks on ext2/3 filesystem",
2503    "\
2504 This runs the I<zerofree> program on C<device>.  This program
2505 claims to zero unused inodes and disk blocks on an ext2/3
2506 filesystem, thus making it possible to compress the filesystem
2507 more effectively.
2508
2509 You should B<not> run this program if the filesystem is
2510 mounted.
2511
2512 It is possible that using this program can damage the filesystem
2513 or data on the filesystem.");
2514
2515   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2516    [],
2517    "resize an LVM physical volume",
2518    "\
2519 This resizes (expands or shrinks) an existing LVM physical
2520 volume to match the new size of the underlying device.");
2521
2522   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2523                        Int "cyls"; Int "heads"; Int "sectors";
2524                        String "line"]), 99, [DangerWillRobinson],
2525    [],
2526    "modify a single partition on a block device",
2527    "\
2528 This runs L<sfdisk(8)> option to modify just the single
2529 partition C<n> (note: C<n> counts from 1).
2530
2531 For other parameters, see C<guestfs_sfdisk>.  You should usually
2532 pass C<0> for the cyls/heads/sectors parameters.
2533
2534 See also: C<guestfs_part_add>");
2535
2536   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2537    [],
2538    "display the partition table",
2539    "\
2540 This displays the partition table on C<device>, in the
2541 human-readable output of the L<sfdisk(8)> command.  It is
2542 not intended to be parsed.
2543
2544 See also: C<guestfs_part_list>");
2545
2546   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2547    [],
2548    "display the kernel geometry",
2549    "\
2550 This displays the kernel's idea of the geometry of C<device>.
2551
2552 The result is in human-readable format, and not designed to
2553 be parsed.");
2554
2555   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2556    [],
2557    "display the disk geometry from the partition table",
2558    "\
2559 This displays the disk geometry of C<device> read from the
2560 partition table.  Especially in the case where the underlying
2561 block device has been resized, this can be different from the
2562 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2563
2564 The result is in human-readable format, and not designed to
2565 be parsed.");
2566
2567   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2568    [],
2569    "activate or deactivate all volume groups",
2570    "\
2571 This command activates or (if C<activate> is false) deactivates
2572 all logical volumes in all volume groups.
2573 If activated, then they are made known to the
2574 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2575 then those devices disappear.
2576
2577 This command is the same as running C<vgchange -a y|n>");
2578
2579   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2580    [],
2581    "activate or deactivate some volume groups",
2582    "\
2583 This command activates or (if C<activate> is false) deactivates
2584 all logical volumes in the listed volume groups C<volgroups>.
2585 If activated, then they are made known to the
2586 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2587 then those devices disappear.
2588
2589 This command is the same as running C<vgchange -a y|n volgroups...>
2590
2591 Note that if C<volgroups> is an empty list then B<all> volume groups
2592 are activated or deactivated.");
2593
2594   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2595    [InitNone, Always, TestOutput (
2596       [["part_disk"; "/dev/sda"; "mbr"];
2597        ["pvcreate"; "/dev/sda1"];
2598        ["vgcreate"; "VG"; "/dev/sda1"];
2599        ["lvcreate"; "LV"; "VG"; "10"];
2600        ["mkfs"; "ext2"; "/dev/VG/LV"];
2601        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2602        ["write_file"; "/new"; "test content"; "0"];
2603        ["umount"; "/"];
2604        ["lvresize"; "/dev/VG/LV"; "20"];
2605        ["e2fsck_f"; "/dev/VG/LV"];
2606        ["resize2fs"; "/dev/VG/LV"];
2607        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2608        ["cat"; "/new"]], "test content");
2609     InitNone, Always, TestRun (
2610       (* Make an LV smaller to test RHBZ#587484. *)
2611       [["part_disk"; "/dev/sda"; "mbr"];
2612        ["pvcreate"; "/dev/sda1"];
2613        ["vgcreate"; "VG"; "/dev/sda1"];
2614        ["lvcreate"; "LV"; "VG"; "20"];
2615        ["lvresize"; "/dev/VG/LV"; "10"]])],
2616    "resize an LVM logical volume",
2617    "\
2618 This resizes (expands or shrinks) an existing LVM logical
2619 volume to C<mbytes>.  When reducing, data in the reduced part
2620 is lost.");
2621
2622   ("resize2fs", (RErr, [Device "device"]), 106, [],
2623    [], (* lvresize tests this *)
2624    "resize an ext2/ext3 filesystem",
2625    "\
2626 This resizes an ext2 or ext3 filesystem to match the size of
2627 the underlying device.
2628
2629 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2630 on the C<device> before calling this command.  For unknown reasons
2631 C<resize2fs> sometimes gives an error about this and sometimes not.
2632 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2633 calling this function.");
2634
2635   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2636    [InitBasicFS, Always, TestOutputList (
2637       [["find"; "/"]], ["lost+found"]);
2638     InitBasicFS, Always, TestOutputList (
2639       [["touch"; "/a"];
2640        ["mkdir"; "/b"];
2641        ["touch"; "/b/c"];
2642        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2643     InitBasicFS, Always, TestOutputList (
2644       [["mkdir_p"; "/a/b/c"];
2645        ["touch"; "/a/b/c/d"];
2646        ["find"; "/a/b/"]], ["c"; "c/d"])],
2647    "find all files and directories",
2648    "\
2649 This command lists out all files and directories, recursively,
2650 starting at C<directory>.  It is essentially equivalent to
2651 running the shell command C<find directory -print> but some
2652 post-processing happens on the output, described below.
2653
2654 This returns a list of strings I<without any prefix>.  Thus
2655 if the directory structure was:
2656
2657  /tmp/a
2658  /tmp/b
2659  /tmp/c/d
2660
2661 then the returned list from C<guestfs_find> C</tmp> would be
2662 4 elements:
2663
2664  a
2665  b
2666  c
2667  c/d
2668
2669 If C<directory> is not a directory, then this command returns
2670 an error.
2671
2672 The returned list is sorted.
2673
2674 See also C<guestfs_find0>.");
2675
2676   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2677    [], (* lvresize tests this *)
2678    "check an ext2/ext3 filesystem",
2679    "\
2680 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2681 filesystem checker on C<device>, noninteractively (C<-p>),
2682 even if the filesystem appears to be clean (C<-f>).
2683
2684 This command is only needed because of C<guestfs_resize2fs>
2685 (q.v.).  Normally you should use C<guestfs_fsck>.");
2686
2687   ("sleep", (RErr, [Int "secs"]), 109, [],
2688    [InitNone, Always, TestRun (
2689       [["sleep"; "1"]])],
2690    "sleep for some seconds",
2691    "\
2692 Sleep for C<secs> seconds.");
2693
2694   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2695    [InitNone, Always, TestOutputInt (
2696       [["part_disk"; "/dev/sda"; "mbr"];
2697        ["mkfs"; "ntfs"; "/dev/sda1"];
2698        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2699     InitNone, Always, TestOutputInt (
2700       [["part_disk"; "/dev/sda"; "mbr"];
2701        ["mkfs"; "ext2"; "/dev/sda1"];
2702        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2703    "probe NTFS volume",
2704    "\
2705 This command runs the L<ntfs-3g.probe(8)> command which probes
2706 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2707 be mounted read-write, and some cannot be mounted at all).
2708
2709 C<rw> is a boolean flag.  Set it to true if you want to test
2710 if the volume can be mounted read-write.  Set it to false if
2711 you want to test if the volume can be mounted read-only.
2712
2713 The return value is an integer which C<0> if the operation
2714 would succeed, or some non-zero value documented in the
2715 L<ntfs-3g.probe(8)> manual page.");
2716
2717   ("sh", (RString "output", [String "command"]), 111, [],
2718    [], (* XXX needs tests *)
2719    "run a command via the shell",
2720    "\
2721 This call runs a command from the guest filesystem via the
2722 guest's C</bin/sh>.
2723
2724 This is like C<guestfs_command>, but passes the command to:
2725
2726  /bin/sh -c \"command\"
2727
2728 Depending on the guest's shell, this usually results in
2729 wildcards being expanded, shell expressions being interpolated
2730 and so on.
2731
2732 All the provisos about C<guestfs_command> apply to this call.");
2733
2734   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2735    [], (* XXX needs tests *)
2736    "run a command via the shell returning lines",
2737    "\
2738 This is the same as C<guestfs_sh>, but splits the result
2739 into a list of lines.
2740
2741 See also: C<guestfs_command_lines>");
2742
2743   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2744    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2745     * code in stubs.c, since all valid glob patterns must start with "/".
2746     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2747     *)
2748    [InitBasicFS, Always, TestOutputList (
2749       [["mkdir_p"; "/a/b/c"];
2750        ["touch"; "/a/b/c/d"];
2751        ["touch"; "/a/b/c/e"];
2752        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2753     InitBasicFS, Always, TestOutputList (
2754       [["mkdir_p"; "/a/b/c"];
2755        ["touch"; "/a/b/c/d"];
2756        ["touch"; "/a/b/c/e"];
2757        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2758     InitBasicFS, Always, TestOutputList (
2759       [["mkdir_p"; "/a/b/c"];
2760        ["touch"; "/a/b/c/d"];
2761        ["touch"; "/a/b/c/e"];
2762        ["glob_expand"; "/a/*/x/*"]], [])],
2763    "expand a wildcard path",
2764    "\
2765 This command searches for all the pathnames matching
2766 C<pattern> according to the wildcard expansion rules
2767 used by the shell.
2768
2769 If no paths match, then this returns an empty list
2770 (note: not an error).
2771
2772 It is just a wrapper around the C L<glob(3)> function
2773 with flags C<GLOB_MARK|GLOB_BRACE>.
2774 See that manual page for more details.");
2775
2776   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2777    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2778       [["scrub_device"; "/dev/sdc"]])],
2779    "scrub (securely wipe) a device",
2780    "\
2781 This command writes patterns over C<device> to make data retrieval
2782 more difficult.
2783
2784 It is an interface to the L<scrub(1)> program.  See that
2785 manual page for more details.");
2786
2787   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2788    [InitBasicFS, Always, TestRun (
2789       [["write_file"; "/file"; "content"; "0"];
2790        ["scrub_file"; "/file"]])],
2791    "scrub (securely wipe) a file",
2792    "\
2793 This command writes patterns over a file to make data retrieval
2794 more difficult.
2795
2796 The file is I<removed> after scrubbing.
2797
2798 It is an interface to the L<scrub(1)> program.  See that
2799 manual page for more details.");
2800
2801   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2802    [], (* XXX needs testing *)
2803    "scrub (securely wipe) free space",
2804    "\
2805 This command creates the directory C<dir> and then fills it
2806 with files until the filesystem is full, and scrubs the files
2807 as for C<guestfs_scrub_file>, and deletes them.
2808 The intention is to scrub any free space on the partition
2809 containing C<dir>.
2810
2811 It is an interface to the L<scrub(1)> program.  See that
2812 manual page for more details.");
2813
2814   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2815    [InitBasicFS, Always, TestRun (
2816       [["mkdir"; "/tmp"];
2817        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2818    "create a temporary directory",
2819    "\
2820 This command creates a temporary directory.  The
2821 C<template> parameter should be a full pathname for the
2822 temporary directory name with the final six characters being
2823 \"XXXXXX\".
2824
2825 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2826 the second one being suitable for Windows filesystems.
2827
2828 The name of the temporary directory that was created
2829 is returned.
2830
2831 The temporary directory is created with mode 0700
2832 and is owned by root.
2833
2834 The caller is responsible for deleting the temporary
2835 directory and its contents after use.
2836
2837 See also: L<mkdtemp(3)>");
2838
2839   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2840    [InitISOFS, Always, TestOutputInt (
2841       [["wc_l"; "/10klines"]], 10000);
2842     (* Test for RHBZ#579608, absolute symbolic links. *)
2843     InitISOFS, Always, TestOutputInt (
2844       [["wc_l"; "/abssymlink"]], 10000)],
2845    "count lines in a file",
2846    "\
2847 This command counts the lines in a file, using the
2848 C<wc -l> external command.");
2849
2850   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2851    [InitISOFS, Always, TestOutputInt (
2852       [["wc_w"; "/10klines"]], 10000)],
2853    "count words in a file",
2854    "\
2855 This command counts the words in a file, using the
2856 C<wc -w> external command.");
2857
2858   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2859    [InitISOFS, Always, TestOutputInt (
2860       [["wc_c"; "/100kallspaces"]], 102400)],
2861    "count characters in a file",
2862    "\
2863 This command counts the characters in a file, using the
2864 C<wc -c> external command.");
2865
2866   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2867    [InitISOFS, Always, TestOutputList (
2868       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2869     (* Test for RHBZ#579608, absolute symbolic links. *)
2870     InitISOFS, Always, TestOutputList (
2871       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2872    "return first 10 lines of a file",
2873    "\
2874 This command returns up to the first 10 lines of a file as
2875 a list of strings.");
2876
2877   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2878    [InitISOFS, Always, TestOutputList (
2879       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2880     InitISOFS, Always, TestOutputList (
2881       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2882     InitISOFS, Always, TestOutputList (
2883       [["head_n"; "0"; "/10klines"]], [])],
2884    "return first N lines of a file",
2885    "\
2886 If the parameter C<nrlines> is a positive number, this returns the first
2887 C<nrlines> lines of the file C<path>.
2888
2889 If the parameter C<nrlines> is a negative number, this returns lines
2890 from the file C<path>, excluding the last C<nrlines> lines.
2891
2892 If the parameter C<nrlines> is zero, this returns an empty list.");
2893
2894   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2895    [InitISOFS, Always, TestOutputList (
2896       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2897    "return last 10 lines of a file",
2898    "\
2899 This command returns up to the last 10 lines of a file as
2900 a list of strings.");
2901
2902   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2903    [InitISOFS, Always, TestOutputList (
2904       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2905     InitISOFS, Always, TestOutputList (
2906       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2907     InitISOFS, Always, TestOutputList (
2908       [["tail_n"; "0"; "/10klines"]], [])],
2909    "return last N lines of a file",
2910    "\
2911 If the parameter C<nrlines> is a positive number, this returns the last
2912 C<nrlines> lines of the file C<path>.
2913
2914 If the parameter C<nrlines> is a negative number, this returns lines
2915 from the file C<path>, starting with the C<-nrlines>th line.
2916
2917 If the parameter C<nrlines> is zero, this returns an empty list.");
2918
2919   ("df", (RString "output", []), 125, [],
2920    [], (* XXX Tricky to test because it depends on the exact format
2921         * of the 'df' command and other imponderables.
2922         *)
2923    "report file system disk space usage",
2924    "\
2925 This command runs the C<df> command to report disk space used.
2926
2927 This command is mostly useful for interactive sessions.  It
2928 is I<not> intended that you try to parse the output string.
2929 Use C<statvfs> from programs.");
2930
2931   ("df_h", (RString "output", []), 126, [],
2932    [], (* XXX Tricky to test because it depends on the exact format
2933         * of the 'df' command and other imponderables.
2934         *)
2935    "report file system disk space usage (human readable)",
2936    "\
2937 This command runs the C<df -h> command to report disk space used
2938 in human-readable format.
2939
2940 This command is mostly useful for interactive sessions.  It
2941 is I<not> intended that you try to parse the output string.
2942 Use C<statvfs> from programs.");
2943
2944   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2945    [InitISOFS, Always, TestOutputInt (
2946       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2947    "estimate file space usage",
2948    "\
2949 This command runs the C<du -s> command to estimate file space
2950 usage for C<path>.
2951
2952 C<path> can be a file or a directory.  If C<path> is a directory
2953 then the estimate includes the contents of the directory and all
2954 subdirectories (recursively).
2955
2956 The result is the estimated size in I<kilobytes>
2957 (ie. units of 1024 bytes).");
2958
2959   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2960    [InitISOFS, Always, TestOutputList (
2961       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2962    "list files in an initrd",
2963    "\
2964 This command lists out files contained in an initrd.
2965
2966 The files are listed without any initial C</> character.  The
2967 files are listed in the order they appear (not necessarily
2968 alphabetical).  Directory names are listed as separate items.
2969
2970 Old Linux kernels (2.4 and earlier) used a compressed ext2
2971 filesystem as initrd.  We I<only> support the newer initramfs
2972 format (compressed cpio files).");
2973
2974   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2975    [],
2976    "mount a file using the loop device",
2977    "\
2978 This command lets you mount C<file> (a filesystem image
2979 in a file) on a mount point.  It is entirely equivalent to
2980 the command C<mount -o loop file mountpoint>.");
2981
2982   ("mkswap", (RErr, [Device "device"]), 130, [],
2983    [InitEmpty, Always, TestRun (
2984       [["part_disk"; "/dev/sda"; "mbr"];
2985        ["mkswap"; "/dev/sda1"]])],
2986    "create a swap partition",
2987    "\
2988 Create a swap partition on C<device>.");
2989
2990   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2991    [InitEmpty, Always, TestRun (
2992       [["part_disk"; "/dev/sda"; "mbr"];
2993        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2994    "create a swap partition with a label",
2995    "\
2996 Create a swap partition on C<device> with label C<label>.
2997
2998 Note that you cannot attach a swap label to a block device
2999 (eg. C</dev/sda>), just to a partition.  This appears to be
3000 a limitation of the kernel or swap tools.");
3001
3002   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3003    (let uuid = uuidgen () in
3004     [InitEmpty, Always, TestRun (
3005        [["part_disk"; "/dev/sda"; "mbr"];
3006         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3007    "create a swap partition with an explicit UUID",
3008    "\
3009 Create a swap partition on C<device> with UUID C<uuid>.");
3010
3011   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3012    [InitBasicFS, Always, TestOutputStruct (
3013       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3014        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3015        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3016     InitBasicFS, Always, TestOutputStruct (
3017       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3018        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3019    "make block, character or FIFO devices",
3020    "\
3021 This call creates block or character special devices, or
3022 named pipes (FIFOs).
3023
3024 The C<mode> parameter should be the mode, using the standard
3025 constants.  C<devmajor> and C<devminor> are the
3026 device major and minor numbers, only used when creating block
3027 and character special devices.
3028
3029 Note that, just like L<mknod(2)>, the mode must be bitwise
3030 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3031 just creates a regular file).  These constants are
3032 available in the standard Linux header files, or you can use
3033 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3034 which are wrappers around this command which bitwise OR
3035 in the appropriate constant for you.
3036
3037 The mode actually set is affected by the umask.");
3038
3039   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3040    [InitBasicFS, Always, TestOutputStruct (
3041       [["mkfifo"; "0o777"; "/node"];
3042        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3043    "make FIFO (named pipe)",
3044    "\
3045 This call creates a FIFO (named pipe) called C<path> with
3046 mode C<mode>.  It is just a convenient wrapper around
3047 C<guestfs_mknod>.
3048
3049 The mode actually set is affected by the umask.");
3050
3051   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3052    [InitBasicFS, Always, TestOutputStruct (
3053       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3054        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3055    "make block device node",
3056    "\
3057 This call creates a block device node called C<path> with
3058 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3059 It is just a convenient wrapper around C<guestfs_mknod>.
3060
3061 The mode actually set is affected by the umask.");
3062
3063   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3064    [InitBasicFS, Always, TestOutputStruct (
3065       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3066        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3067    "make char device node",
3068    "\
3069 This call creates a char device node called C<path> with
3070 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3071 It is just a convenient wrapper around C<guestfs_mknod>.
3072
3073 The mode actually set is affected by the umask.");
3074
3075   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3076    [InitEmpty, Always, TestOutputInt (
3077       [["umask"; "0o22"]], 0o22)],
3078    "set file mode creation mask (umask)",
3079    "\
3080 This function sets the mask used for creating new files and
3081 device nodes to C<mask & 0777>.
3082
3083 Typical umask values would be C<022> which creates new files
3084 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3085 C<002> which creates new files with permissions like
3086 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3087
3088 The default umask is C<022>.  This is important because it
3089 means that directories and device nodes will be created with
3090 C<0644> or C<0755> mode even if you specify C<0777>.
3091
3092 See also C<guestfs_get_umask>,
3093 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3094
3095 This call returns the previous umask.");
3096
3097   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3098    [],
3099    "read directories entries",
3100    "\
3101 This returns the list of directory entries in directory C<dir>.
3102
3103 All entries in the directory are returned, including C<.> and
3104 C<..>.  The entries are I<not> sorted, but returned in the same
3105 order as the underlying filesystem.
3106
3107 Also this call returns basic file type information about each
3108 file.  The C<ftyp> field will contain one of the following characters:
3109
3110 =over 4
3111
3112 =item 'b'
3113
3114 Block special
3115
3116 =item 'c'
3117
3118 Char special
3119
3120 =item 'd'
3121
3122 Directory
3123
3124 =item 'f'
3125
3126 FIFO (named pipe)
3127
3128 =item 'l'
3129
3130 Symbolic link
3131
3132 =item 'r'
3133
3134 Regular file
3135
3136 =item 's'
3137
3138 Socket
3139
3140 =item 'u'
3141
3142 Unknown file type
3143
3144 =item '?'
3145
3146 The L<readdir(3)> returned a C<d_type> field with an
3147 unexpected value
3148
3149 =back
3150
3151 This function is primarily intended for use by programs.  To
3152 get a simple list of names, use C<guestfs_ls>.  To get a printable
3153 directory for human consumption, use C<guestfs_ll>.");
3154
3155   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3156    [],
3157    "create partitions on a block device",
3158    "\
3159 This is a simplified interface to the C<guestfs_sfdisk>
3160 command, where partition sizes are specified in megabytes
3161 only (rounded to the nearest cylinder) and you don't need
3162 to specify the cyls, heads and sectors parameters which
3163 were rarely if ever used anyway.
3164
3165 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3166 and C<guestfs_part_disk>");
3167
3168   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3169    [],
3170    "determine file type inside a compressed file",
3171    "\
3172 This command runs C<file> after first decompressing C<path>
3173 using C<method>.
3174
3175 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3176
3177 Since 1.0.63, use C<guestfs_file> instead which can now
3178 process compressed files.");
3179
3180   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3181    [],
3182    "list extended attributes of a file or directory",
3183    "\
3184 This call lists the extended attributes of the file or directory
3185 C<path>.
3186
3187 At the system call level, this is a combination of the
3188 L<listxattr(2)> and L<getxattr(2)> calls.
3189
3190 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3191
3192   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3193    [],
3194    "list extended attributes of a file or directory",
3195    "\
3196 This is the same as C<guestfs_getxattrs>, but if C<path>
3197 is a symbolic link, then it returns the extended attributes
3198 of the link itself.");
3199
3200   ("setxattr", (RErr, [String "xattr";
3201                        String "val"; Int "vallen"; (* will be BufferIn *)
3202                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3203    [],
3204    "set extended attribute of a file or directory",
3205    "\
3206 This call sets the extended attribute named C<xattr>
3207 of the file C<path> to the value C<val> (of length C<vallen>).
3208 The value is arbitrary 8 bit data.
3209
3210 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3211
3212   ("lsetxattr", (RErr, [String "xattr";
3213                         String "val"; Int "vallen"; (* will be BufferIn *)
3214                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3215    [],
3216    "set extended attribute of a file or directory",
3217    "\
3218 This is the same as C<guestfs_setxattr>, but if C<path>
3219 is a symbolic link, then it sets an extended attribute
3220 of the link itself.");
3221
3222   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3223    [],
3224    "remove extended attribute of a file or directory",
3225    "\
3226 This call removes the extended attribute named C<xattr>
3227 of the file C<path>.
3228
3229 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3230
3231   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3232    [],
3233    "remove extended attribute of a file or directory",
3234    "\
3235 This is the same as C<guestfs_removexattr>, but if C<path>
3236 is a symbolic link, then it removes an extended attribute
3237 of the link itself.");
3238
3239   ("mountpoints", (RHashtable "mps", []), 147, [],
3240    [],
3241    "show mountpoints",
3242    "\
3243 This call is similar to C<guestfs_mounts>.  That call returns
3244 a list of devices.  This one returns a hash table (map) of
3245 device name to directory where the device is mounted.");
3246
3247   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3248    (* This is a special case: while you would expect a parameter
3249     * of type "Pathname", that doesn't work, because it implies
3250     * NEED_ROOT in the generated calling code in stubs.c, and
3251     * this function cannot use NEED_ROOT.
3252     *)
3253    [],
3254    "create a mountpoint",
3255    "\
3256 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3257 specialized calls that can be used to create extra mountpoints
3258 before mounting the first filesystem.
3259
3260 These calls are I<only> necessary in some very limited circumstances,
3261 mainly the case where you want to mount a mix of unrelated and/or
3262 read-only filesystems together.
3263
3264 For example, live CDs often contain a \"Russian doll\" nest of
3265 filesystems, an ISO outer layer, with a squashfs image inside, with
3266 an ext2/3 image inside that.  You can unpack this as follows
3267 in guestfish:
3268
3269  add-ro Fedora-11-i686-Live.iso
3270  run
3271  mkmountpoint /cd
3272  mkmountpoint /squash
3273  mkmountpoint /ext3
3274  mount /dev/sda /cd
3275  mount-loop /cd/LiveOS/squashfs.img /squash
3276  mount-loop /squash/LiveOS/ext3fs.img /ext3
3277
3278 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3279
3280   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3281    [],
3282    "remove a mountpoint",
3283    "\
3284 This calls removes a mountpoint that was previously created
3285 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3286 for full details.");
3287
3288   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3289    [InitISOFS, Always, TestOutputBuffer (
3290       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3291     (* Test various near large, large and too large files (RHBZ#589039). *)
3292     InitBasicFS, Always, TestLastFail (
3293       [["touch"; "/a"];
3294        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3295        ["read_file"; "/a"]]);
3296     InitBasicFS, Always, TestLastFail (
3297       [["touch"; "/a"];
3298        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3299        ["read_file"; "/a"]]);
3300     InitBasicFS, Always, TestLastFail (
3301       [["touch"; "/a"];
3302        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3303        ["read_file"; "/a"]])],
3304    "read a file",
3305    "\
3306 This calls returns the contents of the file C<path> as a
3307 buffer.
3308
3309 Unlike C<guestfs_cat>, this function can correctly
3310 handle files that contain embedded ASCII NUL characters.
3311 However unlike C<guestfs_download>, this function is limited
3312 in the total size of file that can be handled.");
3313
3314   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3315    [InitISOFS, Always, TestOutputList (
3316       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3317     InitISOFS, Always, TestOutputList (
3318       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3319     (* Test for RHBZ#579608, absolute symbolic links. *)
3320     InitISOFS, Always, TestOutputList (
3321       [["grep"; "nomatch"; "/abssymlink"]], [])],
3322    "return lines matching a pattern",
3323    "\
3324 This calls the external C<grep> program and returns the
3325 matching lines.");
3326
3327   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3328    [InitISOFS, Always, TestOutputList (
3329       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3330    "return lines matching a pattern",
3331    "\
3332 This calls the external C<egrep> program and returns the
3333 matching lines.");
3334
3335   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3336    [InitISOFS, Always, TestOutputList (
3337       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3338    "return lines matching a pattern",
3339    "\
3340 This calls the external C<fgrep> program and returns the
3341 matching lines.");
3342
3343   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3344    [InitISOFS, Always, TestOutputList (
3345       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3346    "return lines matching a pattern",
3347    "\
3348 This calls the external C<grep -i> program and returns the
3349 matching lines.");
3350
3351   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3352    [InitISOFS, Always, TestOutputList (
3353       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3354    "return lines matching a pattern",
3355    "\
3356 This calls the external C<egrep -i> program and returns the
3357 matching lines.");
3358
3359   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3360    [InitISOFS, Always, TestOutputList (
3361       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3362    "return lines matching a pattern",
3363    "\
3364 This calls the external C<fgrep -i> program and returns the
3365 matching lines.");
3366
3367   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3368    [InitISOFS, Always, TestOutputList (
3369       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3370    "return lines matching a pattern",
3371    "\
3372 This calls the external C<zgrep> program and returns the
3373 matching lines.");
3374
3375   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3376    [InitISOFS, Always, TestOutputList (
3377       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3378    "return lines matching a pattern",
3379    "\
3380 This calls the external C<zegrep> program and returns the
3381 matching lines.");
3382
3383   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3384    [InitISOFS, Always, TestOutputList (
3385       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3386    "return lines matching a pattern",
3387    "\
3388 This calls the external C<zfgrep> program and returns the
3389 matching lines.");
3390
3391   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3392    [InitISOFS, Always, TestOutputList (
3393       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3394    "return lines matching a pattern",
3395    "\
3396 This calls the external C<zgrep -i> program and returns the
3397 matching lines.");
3398
3399   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3400    [InitISOFS, Always, TestOutputList (
3401       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3402    "return lines matching a pattern",
3403    "\
3404 This calls the external C<zegrep -i> program and returns the
3405 matching lines.");
3406
3407   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3408    [InitISOFS, Always, TestOutputList (
3409       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3410    "return lines matching a pattern",
3411    "\
3412 This calls the external C<zfgrep -i> program and returns the
3413 matching lines.");
3414
3415   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3416    [InitISOFS, Always, TestOutput (
3417       [["realpath"; "/../directory"]], "/directory")],
3418    "canonicalized absolute pathname",
3419    "\
3420 Return the canonicalized absolute pathname of C<path>.  The
3421 returned path has no C<.>, C<..> or symbolic link path elements.");
3422
3423   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3424    [InitBasicFS, Always, TestOutputStruct (
3425       [["touch"; "/a"];
3426        ["ln"; "/a"; "/b"];
3427        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3428    "create a hard link",
3429    "\
3430 This command creates a hard link using the C<ln> command.");
3431
3432   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3433    [InitBasicFS, Always, TestOutputStruct (
3434       [["touch"; "/a"];
3435        ["touch"; "/b"];
3436        ["ln_f"; "/a"; "/b"];
3437        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3438    "create a hard link",
3439    "\
3440 This command creates a hard link using the C<ln -f> command.
3441 The C<-f> option removes the link (C<linkname>) if it exists already.");
3442
3443   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3444    [InitBasicFS, Always, TestOutputStruct (
3445       [["touch"; "/a"];
3446        ["ln_s"; "a"; "/b"];
3447        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3448    "create a symbolic link",
3449    "\
3450 This command creates a symbolic link using the C<ln -s> command.");
3451
3452   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3453    [InitBasicFS, Always, TestOutput (
3454       [["mkdir_p"; "/a/b"];
3455        ["touch"; "/a/b/c"];
3456        ["ln_sf"; "../d"; "/a/b/c"];
3457        ["readlink"; "/a/b/c"]], "../d")],
3458    "create a symbolic link",
3459    "\
3460 This command creates a symbolic link using the C<ln -sf> command,
3461 The C<-f> option removes the link (C<linkname>) if it exists already.");
3462
3463   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3464    [] (* XXX tested above *),
3465    "read the target of a symbolic link",
3466    "\
3467 This command reads the target of a symbolic link.");
3468
3469   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3470    [InitBasicFS, Always, TestOutputStruct (
3471       [["fallocate"; "/a"; "1000000"];
3472        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3473    "preallocate a file in the guest filesystem",
3474    "\
3475 This command preallocates a file (containing zero bytes) named
3476 C<path> of size C<len> bytes.  If the file exists already, it
3477 is overwritten.
3478
3479 Do not confuse this with the guestfish-specific
3480 C<alloc> command which allocates a file in the host and
3481 attaches it as a device.");
3482
3483   ("swapon_device", (RErr, [Device "device"]), 170, [],
3484    [InitPartition, Always, TestRun (
3485       [["mkswap"; "/dev/sda1"];
3486        ["swapon_device"; "/dev/sda1"];
3487        ["swapoff_device"; "/dev/sda1"]])],
3488    "enable swap on device",
3489    "\
3490 This command enables the libguestfs appliance to use the
3491 swap device or partition named C<device>.  The increased
3492 memory is made available for all commands, for example
3493 those run using C<guestfs_command> or C<guestfs_sh>.
3494
3495 Note that you should not swap to existing guest swap
3496 partitions unless you know what you are doing.  They may
3497 contain hibernation information, or other information that
3498 the guest doesn't want you to trash.  You also risk leaking
3499 information about the host to the guest this way.  Instead,
3500 attach a new host device to the guest and swap on that.");
3501
3502   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3503    [], (* XXX tested by swapon_device *)
3504    "disable swap on device",
3505    "\
3506 This command disables the libguestfs appliance swap
3507 device or partition named C<device>.
3508 See C<guestfs_swapon_device>.");
3509
3510   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3511    [InitBasicFS, Always, TestRun (
3512       [["fallocate"; "/swap"; "8388608"];
3513        ["mkswap_file"; "/swap"];
3514        ["swapon_file"; "/swap"];
3515        ["swapoff_file"; "/swap"]])],
3516    "enable swap on file",
3517    "\
3518 This command enables swap to a file.
3519 See C<guestfs_swapon_device> for other notes.");
3520
3521   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3522    [], (* XXX tested by swapon_file *)
3523    "disable swap on file",
3524    "\
3525 This command disables the libguestfs appliance swap on file.");
3526
3527   ("swapon_label", (RErr, [String "label"]), 174, [],
3528    [InitEmpty, Always, TestRun (
3529       [["part_disk"; "/dev/sdb"; "mbr"];
3530        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3531        ["swapon_label"; "swapit"];
3532        ["swapoff_label"; "swapit"];
3533        ["zero"; "/dev/sdb"];
3534        ["blockdev_rereadpt"; "/dev/sdb"]])],
3535    "enable swap on labeled swap partition",
3536    "\
3537 This command enables swap to a labeled swap partition.
3538 See C<guestfs_swapon_device> for other notes.");
3539
3540   ("swapoff_label", (RErr, [String "label"]), 175, [],
3541    [], (* XXX tested by swapon_label *)
3542    "disable swap on labeled swap partition",
3543    "\
3544 This command disables the libguestfs appliance swap on
3545 labeled swap partition.");
3546
3547   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3548    (let uuid = uuidgen () in
3549     [InitEmpty, Always, TestRun (
3550        [["mkswap_U"; uuid; "/dev/sdb"];
3551         ["swapon_uuid"; uuid];
3552         ["swapoff_uuid"; uuid]])]),
3553    "enable swap on swap partition by UUID",
3554    "\
3555 This command enables swap to a swap partition with the given UUID.
3556 See C<guestfs_swapon_device> for other notes.");
3557
3558   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3559    [], (* XXX tested by swapon_uuid *)
3560    "disable swap on swap partition by UUID",
3561    "\
3562 This command disables the libguestfs appliance swap partition
3563 with the given UUID.");
3564
3565   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3566    [InitBasicFS, Always, TestRun (
3567       [["fallocate"; "/swap"; "8388608"];
3568        ["mkswap_file"; "/swap"]])],
3569    "create a swap file",
3570    "\
3571 Create a swap file.
3572
3573 This command just writes a swap file signature to an existing
3574 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3575
3576   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3577    [InitISOFS, Always, TestRun (
3578       [["inotify_init"; "0"]])],
3579    "create an inotify handle",
3580    "\
3581 This command creates a new inotify handle.
3582 The inotify subsystem can be used to notify events which happen to
3583 objects in the guest filesystem.
3584
3585 C<maxevents> is the maximum number of events which will be
3586 queued up between calls to C<guestfs_inotify_read> or
3587 C<guestfs_inotify_files>.
3588 If this is passed as C<0>, then the kernel (or previously set)
3589 default is used.  For Linux 2.6.29 the default was 16384 events.
3590 Beyond this limit, the kernel throws away events, but records
3591 the fact that it threw them away by setting a flag
3592 C<IN_Q_OVERFLOW> in the returned structure list (see
3593 C<guestfs_inotify_read>).
3594
3595 Before any events are generated, you have to add some
3596 watches to the internal watch list.  See:
3597 C<guestfs_inotify_add_watch>,
3598 C<guestfs_inotify_rm_watch> and
3599 C<guestfs_inotify_watch_all>.
3600
3601 Queued up events should be read periodically by calling
3602 C<guestfs_inotify_read>
3603 (or C<guestfs_inotify_files> which is just a helpful
3604 wrapper around C<guestfs_inotify_read>).  If you don't
3605 read the events out often enough then you risk the internal
3606 queue overflowing.
3607
3608 The handle should be closed after use by calling
3609 C<guestfs_inotify_close>.  This also removes any
3610 watches automatically.
3611
3612 See also L<inotify(7)> for an overview of the inotify interface
3613 as exposed by the Linux kernel, which is roughly what we expose
3614 via libguestfs.  Note that there is one global inotify handle
3615 per libguestfs instance.");
3616
3617   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3618    [InitBasicFS, Always, TestOutputList (
3619       [["inotify_init"; "0"];
3620        ["inotify_add_watch"; "/"; "1073741823"];
3621        ["touch"; "/a"];
3622        ["touch"; "/b"];
3623        ["inotify_files"]], ["a"; "b"])],
3624    "add an inotify watch",
3625    "\
3626 Watch C<path> for the events listed in C<mask>.
3627
3628 Note that if C<path> is a directory then events within that
3629 directory are watched, but this does I<not> happen recursively
3630 (in subdirectories).
3631
3632 Note for non-C or non-Linux callers: the inotify events are
3633 defined by the Linux kernel ABI and are listed in
3634 C</usr/include/sys/inotify.h>.");
3635
3636   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3637    [],
3638    "remove an inotify watch",
3639    "\
3640 Remove a previously defined inotify watch.
3641 See C<guestfs_inotify_add_watch>.");
3642
3643   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3644    [],
3645    "return list of inotify events",
3646    "\
3647 Return the complete queue of events that have happened
3648 since the previous read call.
3649
3650 If no events have happened, this returns an empty list.
3651
3652 I<Note>: In order to make sure that all events have been
3653 read, you must call this function repeatedly until it
3654 returns an empty list.  The reason is that the call will
3655 read events up to the maximum appliance-to-host message
3656 size and leave remaining events in the queue.");
3657
3658   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3659    [],
3660    "return list of watched files that had events",
3661    "\
3662 This function is a helpful wrapper around C<guestfs_inotify_read>
3663 which just returns a list of pathnames of objects that were
3664 touched.  The returned pathnames are sorted and deduplicated.");
3665
3666   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3667    [],
3668    "close the inotify handle",
3669    "\
3670 This closes the inotify handle which was previously
3671 opened by inotify_init.  It removes all watches, throws
3672 away any pending events, and deallocates all resources.");
3673
3674   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3675    [],
3676    "set SELinux security context",
3677    "\
3678 This sets the SELinux security context of the daemon
3679 to the string C<context>.
3680
3681 See the documentation about SELINUX in L<guestfs(3)>.");
3682
3683   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3684    [],
3685    "get SELinux security context",
3686    "\
3687 This gets the SELinux security context of the daemon.
3688
3689 See the documentation about SELINUX in L<guestfs(3)>,
3690 and C<guestfs_setcon>");
3691
3692   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3693    [InitEmpty, Always, TestOutput (
3694       [["part_disk"; "/dev/sda"; "mbr"];
3695        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3696        ["mount_options"; ""; "/dev/sda1"; "/"];
3697        ["write_file"; "/new"; "new file contents"; "0"];
3698        ["cat"; "/new"]], "new file contents")],
3699    "make a filesystem with block size",
3700    "\
3701 This call is similar to C<guestfs_mkfs>, but it allows you to
3702 control the block size of the resulting filesystem.  Supported
3703 block sizes depend on the filesystem type, but typically they
3704 are C<1024>, C<2048> or C<4096> only.");
3705
3706   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3707    [InitEmpty, Always, TestOutput (
3708       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3709        ["mke2journal"; "4096"; "/dev/sda1"];
3710        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3711        ["mount_options"; ""; "/dev/sda2"; "/"];
3712        ["write_file"; "/new"; "new file contents"; "0"];
3713        ["cat"; "/new"]], "new file contents")],
3714    "make ext2/3/4 external journal",
3715    "\
3716 This creates an ext2 external journal on C<device>.  It is equivalent
3717 to the command:
3718
3719  mke2fs -O journal_dev -b blocksize device");
3720
3721   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3722    [InitEmpty, Always, TestOutput (
3723       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3724        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3725        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3726        ["mount_options"; ""; "/dev/sda2"; "/"];
3727        ["write_file"; "/new"; "new file contents"; "0"];
3728        ["cat"; "/new"]], "new file contents")],
3729    "make ext2/3/4 external journal with label",
3730    "\
3731 This creates an ext2 external journal on C<device> with label C<label>.");
3732
3733   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3734    (let uuid = uuidgen () in
3735     [InitEmpty, Always, TestOutput (
3736        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3737         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3738         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3739         ["mount_options"; ""; "/dev/sda2"; "/"];
3740         ["write_file"; "/new"; "new file contents"; "0"];
3741         ["cat"; "/new"]], "new file contents")]),
3742    "make ext2/3/4 external journal with UUID",
3743    "\
3744 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3745
3746   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3747    [],
3748    "make ext2/3/4 filesystem with external journal",
3749    "\
3750 This creates an ext2/3/4 filesystem on C<device> with
3751 an external journal on C<journal>.  It is equivalent
3752 to the command:
3753
3754  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3755
3756 See also C<guestfs_mke2journal>.");
3757
3758   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3759    [],
3760    "make ext2/3/4 filesystem with external journal",
3761    "\
3762 This creates an ext2/3/4 filesystem on C<device> with
3763 an external journal on the journal labeled C<label>.
3764
3765 See also C<guestfs_mke2journal_L>.");
3766
3767   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3768    [],
3769    "make ext2/3/4 filesystem with external journal",
3770    "\
3771 This creates an ext2/3/4 filesystem on C<device> with
3772 an external journal on the journal with UUID C<uuid>.
3773
3774 See also C<guestfs_mke2journal_U>.");
3775
3776   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3777    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3778    "load a kernel module",
3779    "\
3780 This loads a kernel module in the appliance.
3781
3782 The kernel module must have been whitelisted when libguestfs
3783 was built (see C<appliance/kmod.whitelist.in> in the source).");
3784
3785   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3786    [InitNone, Always, TestOutput (
3787       [["echo_daemon"; "This is a test"]], "This is a test"
3788     )],
3789    "echo arguments back to the client",
3790    "\
3791 This command concatenate the list of C<words> passed with single spaces between
3792 them and returns the resulting string.
3793
3794 You can use this command to test the connection through to the daemon.
3795
3796 See also C<guestfs_ping_daemon>.");
3797
3798   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3799    [], (* There is a regression test for this. *)
3800    "find all files and directories, returning NUL-separated list",
3801    "\
3802 This command lists out all files and directories, recursively,
3803 starting at C<directory>, placing the resulting list in the
3804 external file called C<files>.
3805
3806 This command works the same way as C<guestfs_find> with the
3807 following exceptions:
3808
3809 =over 4
3810
3811 =item *
3812
3813 The resulting list is written to an external file.
3814
3815 =item *
3816
3817 Items (filenames) in the result are separated
3818 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3819
3820 =item *
3821
3822 This command is not limited in the number of names that it
3823 can return.
3824
3825 =item *
3826
3827 The result list is not sorted.
3828
3829 =back");
3830
3831   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3832    [InitISOFS, Always, TestOutput (
3833       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3834     InitISOFS, Always, TestOutput (
3835       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3836     InitISOFS, Always, TestOutput (
3837       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3838     InitISOFS, Always, TestLastFail (
3839       [["case_sensitive_path"; "/Known-1/"]]);
3840     InitBasicFS, Always, TestOutput (
3841       [["mkdir"; "/a"];
3842        ["mkdir"; "/a/bbb"];
3843        ["touch"; "/a/bbb/c"];
3844        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3845     InitBasicFS, Always, TestOutput (
3846       [["mkdir"; "/a"];
3847        ["mkdir"; "/a/bbb"];
3848        ["touch"; "/a/bbb/c"];
3849        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3850     InitBasicFS, Always, TestLastFail (
3851       [["mkdir"; "/a"];
3852        ["mkdir"; "/a/bbb"];
3853        ["touch"; "/a/bbb/c"];
3854        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3855    "return true path on case-insensitive filesystem",
3856    "\
3857 This can be used to resolve case insensitive paths on
3858 a filesystem which is case sensitive.  The use case is
3859 to resolve paths which you have read from Windows configuration
3860 files or the Windows Registry, to the true path.
3861
3862 The command handles a peculiarity of the Linux ntfs-3g
3863 filesystem driver (and probably others), which is that although
3864 the underlying filesystem is case-insensitive, the driver
3865 exports the filesystem to Linux as case-sensitive.
3866
3867 One consequence of this is that special directories such
3868 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3869 (or other things) depending on the precise details of how
3870 they were created.  In Windows itself this would not be
3871 a problem.
3872
3873 Bug or feature?  You decide:
3874 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3875
3876 This function resolves the true case of each element in the
3877 path and returns the case-sensitive path.
3878
3879 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3880 might return C<\"/WINDOWS/system32\"> (the exact return value
3881 would depend on details of how the directories were originally
3882 created under Windows).
3883
3884 I<Note>:
3885 This function does not handle drive names, backslashes etc.
3886
3887 See also C<guestfs_realpath>.");
3888
3889   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3890    [InitBasicFS, Always, TestOutput (
3891       [["vfs_type"; "/dev/sda1"]], "ext2")],
3892    "get the Linux VFS type corresponding to a mounted device",
3893    "\
3894 This command gets the block device type corresponding to
3895 a mounted device called C<device>.
3896
3897 Usually the result is the name of the Linux VFS module that
3898 is used to mount this device (probably determined automatically
3899 if you used the C<guestfs_mount> call).");
3900
3901   ("truncate", (RErr, [Pathname "path"]), 199, [],
3902    [InitBasicFS, Always, TestOutputStruct (
3903       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3904        ["truncate"; "/test"];
3905        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3906    "truncate a file to zero size",
3907    "\
3908 This command truncates C<path> to a zero-length file.  The
3909 file must exist already.");
3910
3911   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3912    [InitBasicFS, Always, TestOutputStruct (
3913       [["touch"; "/test"];
3914        ["truncate_size"; "/test"; "1000"];
3915        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3916    "truncate a file to a particular size",
3917    "\
3918 This command truncates C<path> to size C<size> bytes.  The file
3919 must exist already.  If the file is smaller than C<size> then
3920 the file is extended to the required size with null bytes.");
3921
3922   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3923    [InitBasicFS, Always, TestOutputStruct (
3924       [["touch"; "/test"];
3925        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3926        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3927    "set timestamp of a file with nanosecond precision",
3928    "\
3929 This command sets the timestamps of a file with nanosecond
3930 precision.
3931
3932 C<atsecs, atnsecs> are the last access time (atime) in secs and
3933 nanoseconds from the epoch.
3934
3935 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3936 secs and nanoseconds from the epoch.
3937
3938 If the C<*nsecs> field contains the special value C<-1> then
3939 the corresponding timestamp is set to the current time.  (The
3940 C<*secs> field is ignored in this case).
3941
3942 If the C<*nsecs> field contains the special value C<-2> then
3943 the corresponding timestamp is left unchanged.  (The
3944 C<*secs> field is ignored in this case).");
3945
3946   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3947    [InitBasicFS, Always, TestOutputStruct (
3948       [["mkdir_mode"; "/test"; "0o111"];
3949        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3950    "create a directory with a particular mode",
3951    "\
3952 This command creates a directory, setting the initial permissions
3953 of the directory to C<mode>.
3954
3955 For common Linux filesystems, the actual mode which is set will
3956 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3957 interpret the mode in other ways.
3958
3959 See also C<guestfs_mkdir>, C<guestfs_umask>");
3960
3961   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3962    [], (* XXX *)
3963    "change file owner and group",
3964    "\
3965 Change the file owner to C<owner> and group to C<group>.
3966 This is like C<guestfs_chown> but if C<path> is a symlink then
3967 the link itself is changed, not the target.
3968
3969 Only numeric uid and gid are supported.  If you want to use
3970 names, you will need to locate and parse the password file
3971 yourself (Augeas support makes this relatively easy).");
3972
3973   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3974    [], (* XXX *)
3975    "lstat on multiple files",
3976    "\
3977 This call allows you to perform the C<guestfs_lstat> operation
3978 on multiple files, where all files are in the directory C<path>.
3979 C<names> is the list of files from this directory.
3980
3981 On return you get a list of stat structs, with a one-to-one
3982 correspondence to the C<names> list.  If any name did not exist
3983 or could not be lstat'd, then the C<ino> field of that structure
3984 is set to C<-1>.
3985
3986 This call is intended for programs that want to efficiently
3987 list a directory contents without making many round-trips.
3988 See also C<guestfs_lxattrlist> for a similarly efficient call
3989 for getting extended attributes.  Very long directory listings
3990 might cause the protocol message size to be exceeded, causing
3991 this call to fail.  The caller must split up such requests
3992 into smaller groups of names.");
3993
3994   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3995    [], (* XXX *)
3996    "lgetxattr on multiple files",
3997    "\
3998 This call allows you to get the extended attributes
3999 of multiple files, where all files are in the directory C<path>.
4000 C<names> is the list of files from this directory.
4001
4002 On return you get a flat list of xattr structs which must be
4003 interpreted sequentially.  The first xattr struct always has a zero-length
4004 C<attrname>.  C<attrval> in this struct is zero-length
4005 to indicate there was an error doing C<lgetxattr> for this
4006 file, I<or> is a C string which is a decimal number
4007 (the number of following attributes for this file, which could
4008 be C<\"0\">).  Then after the first xattr struct are the
4009 zero or more attributes for the first named file.
4010 This repeats for the second and subsequent files.
4011
4012 This call is intended for programs that want to efficiently
4013 list a directory contents without making many round-trips.
4014 See also C<guestfs_lstatlist> for a similarly efficient call
4015 for getting standard stats.  Very long directory listings
4016 might cause the protocol message size to be exceeded, causing
4017 this call to fail.  The caller must split up such requests
4018 into smaller groups of names.");
4019
4020   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4021    [], (* XXX *)
4022    "readlink on multiple files",
4023    "\
4024 This call allows you to do a C<readlink> operation
4025 on multiple files, where all files are in the directory C<path>.
4026 C<names> is the list of files from this directory.
4027
4028 On return you get a list of strings, with a one-to-one
4029 correspondence to the C<names> list.  Each string is the
4030 value of the symbol link.
4031
4032 If the C<readlink(2)> operation fails on any name, then
4033 the corresponding result string is the empty string C<\"\">.
4034 However the whole operation is completed even if there
4035 were C<readlink(2)> errors, and so you can call this
4036 function with names where you don't know if they are
4037 symbolic links already (albeit slightly less efficient).
4038
4039 This call is intended for programs that want to efficiently
4040 list a directory contents without making many round-trips.
4041 Very long directory listings might cause the protocol
4042 message size to be exceeded, causing
4043 this call to fail.  The caller must split up such requests
4044 into smaller groups of names.");
4045
4046   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4047    [InitISOFS, Always, TestOutputBuffer (
4048       [["pread"; "/known-4"; "1"; "3"]], "\n");
4049     InitISOFS, Always, TestOutputBuffer (
4050       [["pread"; "/empty"; "0"; "100"]], "")],
4051    "read part of a file",
4052    "\
4053 This command lets you read part of a file.  It reads C<count>
4054 bytes of the file, starting at C<offset>, from file C<path>.
4055
4056 This may read fewer bytes than requested.  For further details
4057 see the L<pread(2)> system call.");
4058
4059   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4060    [InitEmpty, Always, TestRun (
4061       [["part_init"; "/dev/sda"; "gpt"]])],
4062    "create an empty partition table",
4063    "\
4064 This creates an empty partition table on C<device> of one of the
4065 partition types listed below.  Usually C<parttype> should be
4066 either C<msdos> or C<gpt> (for large disks).
4067
4068 Initially there are no partitions.  Following this, you should
4069 call C<guestfs_part_add> for each partition required.
4070
4071 Possible values for C<parttype> are:
4072
4073 =over 4
4074
4075 =item B<efi> | B<gpt>
4076
4077 Intel EFI / GPT partition table.
4078
4079 This is recommended for >= 2 TB partitions that will be accessed
4080 from Linux and Intel-based Mac OS X.  It also has limited backwards
4081 compatibility with the C<mbr> format.
4082
4083 =item B<mbr> | B<msdos>
4084
4085 The standard PC \"Master Boot Record\" (MBR) format used
4086 by MS-DOS and Windows.  This partition type will B<only> work
4087 for device sizes up to 2 TB.  For large disks we recommend
4088 using C<gpt>.
4089
4090 =back
4091
4092 Other partition table types that may work but are not
4093 supported include:
4094
4095 =over 4
4096
4097 =item B<aix>
4098
4099 AIX disk labels.
4100
4101 =item B<amiga> | B<rdb>
4102
4103 Amiga \"Rigid Disk Block\" format.
4104
4105 =item B<bsd>
4106
4107 BSD disk labels.
4108
4109 =item B<dasd>
4110
4111 DASD, used on IBM mainframes.
4112
4113 =item B<dvh>
4114
4115 MIPS/SGI volumes.
4116
4117 =item B<mac>
4118
4119 Old Mac partition format.  Modern Macs use C<gpt>.
4120
4121 =item B<pc98>
4122
4123 NEC PC-98 format, common in Japan apparently.
4124
4125 =item B<sun>
4126
4127 Sun disk labels.
4128
4129 =back");
4130
4131   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4132    [InitEmpty, Always, TestRun (
4133       [["part_init"; "/dev/sda"; "mbr"];
4134        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4135     InitEmpty, Always, TestRun (
4136       [["part_init"; "/dev/sda"; "gpt"];
4137        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4138        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4139     InitEmpty, Always, TestRun (
4140       [["part_init"; "/dev/sda"; "mbr"];
4141        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4142        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4143        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4144        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4145    "add a partition to the device",
4146    "\
4147 This command adds a partition to C<device>.  If there is no partition
4148 table on the device, call C<guestfs_part_init> first.
4149
4150 The C<prlogex> parameter is the type of partition.  Normally you
4151 should pass C<p> or C<primary> here, but MBR partition tables also
4152 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4153 types.
4154
4155 C<startsect> and C<endsect> are the start and end of the partition
4156 in I<sectors>.  C<endsect> may be negative, which means it counts
4157 backwards from the end of the disk (C<-1> is the last sector).
4158
4159 Creating a partition which covers the whole disk is not so easy.
4160 Use C<guestfs_part_disk> to do that.");
4161
4162   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4163    [InitEmpty, Always, TestRun (
4164       [["part_disk"; "/dev/sda"; "mbr"]]);
4165     InitEmpty, Always, TestRun (
4166       [["part_disk"; "/dev/sda"; "gpt"]])],
4167    "partition whole disk with a single primary partition",
4168    "\
4169 This command is simply a combination of C<guestfs_part_init>
4170 followed by C<guestfs_part_add> to create a single primary partition
4171 covering the whole disk.
4172
4173 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4174 but other possible values are described in C<guestfs_part_init>.");
4175
4176   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4177    [InitEmpty, Always, TestRun (
4178       [["part_disk"; "/dev/sda"; "mbr"];
4179        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4180    "make a partition bootable",
4181    "\
4182 This sets the bootable flag on partition numbered C<partnum> on
4183 device C<device>.  Note that partitions are numbered from 1.
4184
4185 The bootable flag is used by some operating systems (notably
4186 Windows) to determine which partition to boot from.  It is by
4187 no means universally recognized.");
4188
4189   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4190    [InitEmpty, Always, TestRun (
4191       [["part_disk"; "/dev/sda"; "gpt"];
4192        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4193    "set partition name",
4194    "\
4195 This sets the partition name on partition numbered C<partnum> on
4196 device C<device>.  Note that partitions are numbered from 1.
4197
4198 The partition name can only be set on certain types of partition
4199 table.  This works on C<gpt> but not on C<mbr> partitions.");
4200
4201   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4202    [], (* XXX Add a regression test for this. *)
4203    "list partitions on a device",
4204    "\
4205 This command parses the partition table on C<device> and
4206 returns the list of partitions found.
4207
4208 The fields in the returned structure are:
4209
4210 =over 4
4211
4212 =item B<part_num>
4213
4214 Partition number, counting from 1.
4215
4216 =item B<part_start>
4217
4218 Start of the partition I<in bytes>.  To get sectors you have to
4219 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4220
4221 =item B<part_end>
4222
4223 End of the partition in bytes.
4224
4225 =item B<part_size>
4226
4227 Size of the partition in bytes.
4228
4229 =back");
4230
4231   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4232    [InitEmpty, Always, TestOutput (
4233       [["part_disk"; "/dev/sda"; "gpt"];
4234        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4235    "get the partition table type",
4236    "\
4237 This command examines the partition table on C<device> and
4238 returns the partition table type (format) being used.
4239
4240 Common return values include: C<msdos> (a DOS/Windows style MBR
4241 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4242 values are possible, although unusual.  See C<guestfs_part_init>
4243 for a full list.");
4244
4245   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4246    [InitBasicFS, Always, TestOutputBuffer (
4247       [["fill"; "0x63"; "10"; "/test"];
4248        ["read_file"; "/test"]], "cccccccccc")],
4249    "fill a file with octets",
4250    "\
4251 This command creates a new file called C<path>.  The initial
4252 content of the file is C<len> octets of C<c>, where C<c>
4253 must be a number in the range C<[0..255]>.
4254
4255 To fill a file with zero bytes (sparsely), it is
4256 much more efficient to use C<guestfs_truncate_size>.");
4257
4258   ("available", (RErr, [StringList "groups"]), 216, [],
4259    [InitNone, Always, TestRun [["available"; ""]]],
4260    "test availability of some parts of the API",
4261    "\
4262 This command is used to check the availability of some
4263 groups of functionality in the appliance, which not all builds of
4264 the libguestfs appliance will be able to provide.
4265
4266 The libguestfs groups, and the functions that those
4267 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4268
4269 The argument C<groups> is a list of group names, eg:
4270 C<[\"inotify\", \"augeas\"]> would check for the availability of
4271 the Linux inotify functions and Augeas (configuration file
4272 editing) functions.
4273
4274 The command returns no error if I<all> requested groups are available.
4275
4276 It fails with an error if one or more of the requested
4277 groups is unavailable in the appliance.
4278
4279 If an unknown group name is included in the
4280 list of groups then an error is always returned.
4281
4282 I<Notes:>
4283
4284 =over 4
4285
4286 =item *
4287
4288 You must call C<guestfs_launch> before calling this function.
4289
4290 The reason is because we don't know what groups are
4291 supported by the appliance/daemon until it is running and can
4292 be queried.
4293
4294 =item *
4295
4296 If a group of functions is available, this does not necessarily
4297 mean that they will work.  You still have to check for errors
4298 when calling individual API functions even if they are
4299 available.
4300
4301 =item *
4302
4303 It is usually the job of distro packagers to build
4304 complete functionality into the libguestfs appliance.
4305 Upstream libguestfs, if built from source with all
4306 requirements satisfied, will support everything.
4307
4308 =item *
4309
4310 This call was added in version C<1.0.80>.  In previous
4311 versions of libguestfs all you could do would be to speculatively
4312 execute a command to find out if the daemon implemented it.
4313 See also C<guestfs_version>.
4314
4315 =back");
4316
4317   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4318    [InitBasicFS, Always, TestOutputBuffer (
4319       [["write_file"; "/src"; "hello, world"; "0"];
4320        ["dd"; "/src"; "/dest"];
4321        ["read_file"; "/dest"]], "hello, world")],
4322    "copy from source to destination using dd",
4323    "\
4324 This command copies from one source device or file C<src>
4325 to another destination device or file C<dest>.  Normally you
4326 would use this to copy to or from a device or partition, for
4327 example to duplicate a filesystem.
4328
4329 If the destination is a device, it must be as large or larger
4330 than the source file or device, otherwise the copy will fail.
4331 This command cannot do partial copies (see C<guestfs_copy_size>).");
4332
4333   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4334    [InitBasicFS, Always, TestOutputInt (
4335       [["write_file"; "/file"; "hello, world"; "0"];
4336        ["filesize"; "/file"]], 12)],
4337    "return the size of the file in bytes",
4338    "\
4339 This command returns the size of C<file> in bytes.
4340
4341 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4342 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4343 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4344
4345   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4346    [InitBasicFSonLVM, Always, TestOutputList (
4347       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4348        ["lvs"]], ["/dev/VG/LV2"])],
4349    "rename an LVM logical volume",
4350    "\
4351 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4352
4353   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4354    [InitBasicFSonLVM, Always, TestOutputList (
4355       [["umount"; "/"];
4356        ["vg_activate"; "false"; "VG"];
4357        ["vgrename"; "VG"; "VG2"];
4358        ["vg_activate"; "true"; "VG2"];
4359        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4360        ["vgs"]], ["VG2"])],
4361    "rename an LVM volume group",
4362    "\
4363 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4364
4365   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4366    [InitISOFS, Always, TestOutputBuffer (
4367       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4368    "list the contents of a single file in an initrd",
4369    "\
4370 This command unpacks the file C<filename> from the initrd file
4371 called C<initrdpath>.  The filename must be given I<without> the
4372 initial C</> character.
4373
4374 For example, in guestfish you could use the following command
4375 to examine the boot script (usually called C</init>)
4376 contained in a Linux initrd or initramfs image:
4377
4378  initrd-cat /boot/initrd-<version>.img init
4379
4380 See also C<guestfs_initrd_list>.");
4381
4382   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4383    [],
4384    "get the UUID of a physical volume",
4385    "\
4386 This command returns the UUID of the LVM PV C<device>.");
4387
4388   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4389    [],
4390    "get the UUID of a volume group",
4391    "\
4392 This command returns the UUID of the LVM VG named C<vgname>.");
4393
4394   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4395    [],
4396    "get the UUID of a logical volume",
4397    "\
4398 This command returns the UUID of the LVM LV C<device>.");
4399
4400   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4401    [],
4402    "get the PV UUIDs containing the volume group",
4403    "\
4404 Given a VG called C<vgname>, this returns the UUIDs of all
4405 the physical volumes that this volume group resides on.
4406
4407 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4408 calls to associate physical volumes and volume groups.
4409
4410 See also C<guestfs_vglvuuids>.");
4411
4412   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4413    [],
4414    "get the LV UUIDs of all LVs in the volume group",
4415    "\
4416 Given a VG called C<vgname>, this returns the UUIDs of all
4417 the logical volumes created in this volume group.
4418
4419 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4420 calls to associate logical volumes and volume groups.
4421
4422 See also C<guestfs_vgpvuuids>.");
4423
4424   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4425    [InitBasicFS, Always, TestOutputBuffer (
4426       [["write_file"; "/src"; "hello, world"; "0"];
4427        ["copy_size"; "/src"; "/dest"; "5"];
4428        ["read_file"; "/dest"]], "hello")],
4429    "copy size bytes from source to destination using dd",
4430    "\
4431 This command copies exactly C<size> bytes from one source device
4432 or file C<src> to another destination device or file C<dest>.
4433
4434 Note this will fail if the source is too short or if the destination
4435 is not large enough.");
4436
4437   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4438    [InitBasicFSonLVM, Always, TestRun (
4439       [["zero_device"; "/dev/VG/LV"]])],
4440    "write zeroes to an entire device",
4441    "\
4442 This command writes zeroes over the entire C<device>.  Compare
4443 with C<guestfs_zero> which just zeroes the first few blocks of
4444 a device.");
4445
4446   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4447    [InitBasicFS, Always, TestOutput (
4448       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4449        ["cat"; "/hello"]], "hello\n")],
4450    "unpack compressed tarball to directory",
4451    "\
4452 This command uploads and unpacks local file C<tarball> (an
4453 I<xz compressed> tar file) into C<directory>.");
4454
4455   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4456    [],
4457    "pack directory into compressed tarball",
4458    "\
4459 This command packs the contents of C<directory> and downloads
4460 it to local file C<tarball> (as an xz compressed tar archive).");
4461
4462   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4463    [],
4464    "resize an NTFS filesystem",
4465    "\
4466 This command resizes an NTFS filesystem, expanding or
4467 shrinking it to the size of the underlying device.
4468 See also L<ntfsresize(8)>.");
4469
4470   ("vgscan", (RErr, []), 232, [],
4471    [InitEmpty, Always, TestRun (
4472       [["vgscan"]])],
4473    "rescan for LVM physical volumes, volume groups and logical volumes",
4474    "\
4475 This rescans all block devices and rebuilds the list of LVM
4476 physical volumes, volume groups and logical volumes.");
4477
4478   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4479    [InitEmpty, Always, TestRun (
4480       [["part_init"; "/dev/sda"; "mbr"];
4481        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4482        ["part_del"; "/dev/sda"; "1"]])],
4483    "delete a partition",
4484    "\
4485 This command deletes the partition numbered C<partnum> on C<device>.
4486
4487 Note that in the case of MBR partitioning, deleting an
4488 extended partition also deletes any logical partitions
4489 it contains.");
4490
4491   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4492    [InitEmpty, Always, TestOutputTrue (
4493       [["part_init"; "/dev/sda"; "mbr"];
4494        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4495        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4496        ["part_get_bootable"; "/dev/sda"; "1"]])],
4497    "return true if a partition is bootable",
4498    "\
4499 This command returns true if the partition C<partnum> on
4500 C<device> has the bootable flag set.
4501
4502 See also C<guestfs_part_set_bootable>.");
4503
4504   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4505    [InitEmpty, Always, TestOutputInt (
4506       [["part_init"; "/dev/sda"; "mbr"];
4507        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4508        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4509        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4510    "get the MBR type byte (ID byte) from a partition",
4511    "\
4512 Returns the MBR type byte (also known as the ID byte) from
4513 the numbered partition C<partnum>.
4514
4515 Note that only MBR (old DOS-style) partitions have type bytes.
4516 You will get undefined results for other partition table
4517 types (see C<guestfs_part_get_parttype>).");
4518
4519   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4520    [], (* tested by part_get_mbr_id *)
4521    "set the MBR type byte (ID byte) of a partition",
4522    "\
4523 Sets the MBR type byte (also known as the ID byte) of
4524 the numbered partition C<partnum> to C<idbyte>.  Note
4525 that the type bytes quoted in most documentation are
4526 in fact hexadecimal numbers, but usually documented
4527 without any leading \"0x\" which might be confusing.
4528
4529 Note that only MBR (old DOS-style) partitions have type bytes.
4530 You will get undefined results for other partition table
4531 types (see C<guestfs_part_get_parttype>).");
4532
4533   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4534    [InitISOFS, Always, TestOutput (
4535       [["checksum_device"; "md5"; "/dev/sdd"]],
4536       (Digest.to_hex (Digest.file "images/test.iso")))],
4537    "compute MD5, SHAx or CRC checksum of the contents of a device",
4538    "\
4539 This call computes the MD5, SHAx or CRC checksum of the
4540 contents of the device named C<device>.  For the types of
4541 checksums supported see the C<guestfs_checksum> command.");
4542
4543   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4544    [InitNone, Always, TestRun (
4545       [["part_disk"; "/dev/sda"; "mbr"];
4546        ["pvcreate"; "/dev/sda1"];
4547        ["vgcreate"; "VG"; "/dev/sda1"];
4548        ["lvcreate"; "LV"; "VG"; "10"];
4549        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4550    "expand an LV to fill free space",
4551    "\
4552 This expands an existing logical volume C<lv> so that it fills
4553 C<pc>% of the remaining free space in the volume group.  Commonly
4554 you would call this with pc = 100 which expands the logical volume
4555 as much as possible, using all remaining free space in the volume
4556 group.");
4557
4558   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4559    [], (* XXX Augeas code needs tests. *)
4560    "clear Augeas path",
4561    "\
4562 Set the value associated with C<path> to C<NULL>.  This
4563 is the same as the L<augtool(1)> C<clear> command.");
4564
4565   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4566    [InitEmpty, Always, TestOutputInt (
4567       [["get_umask"]], 0o22)],
4568    "get the current umask",
4569    "\
4570 Return the current umask.  By default the umask is C<022>
4571 unless it has been set by calling C<guestfs_umask>.");
4572
4573   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4574    [],
4575    "upload a file to the appliance (internal use only)",
4576    "\
4577 The C<guestfs_debug_upload> command uploads a file to
4578 the libguestfs appliance.
4579
4580 There is no comprehensive help for this command.  You have
4581 to look at the file C<daemon/debug.c> in the libguestfs source
4582 to find out what it is for.");
4583
4584   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4585    [InitBasicFS, Always, TestOutput (
4586       [["base64_in"; "../images/hello.b64"; "/hello"];
4587        ["cat"; "/hello"]], "hello\n")],
4588    "upload base64-encoded data to file",
4589    "\
4590 This command uploads base64-encoded data from C<base64file>
4591 to C<filename>.");
4592
4593   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4594    [],
4595    "download file and encode as base64",
4596    "\
4597 This command downloads the contents of C<filename>, writing
4598 it out to local file C<base64file> encoded as base64.");
4599
4600   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4601    [],
4602    "compute MD5, SHAx or CRC checksum of files in a directory",
4603    "\
4604 This command computes the checksums of all regular files in
4605 C<directory> and then emits a list of those checksums to
4606 the local output file C<sumsfile>.
4607
4608 This can be used for verifying the integrity of a virtual
4609 machine.  However to be properly secure you should pay
4610 attention to the output of the checksum command (it uses
4611 the ones from GNU coreutils).  In particular when the
4612 filename is not printable, coreutils uses a special
4613 backslash syntax.  For more information, see the GNU
4614 coreutils info file.");
4615
4616 ]
4617
4618 let all_functions = non_daemon_functions @ daemon_functions
4619
4620 (* In some places we want the functions to be displayed sorted
4621  * alphabetically, so this is useful:
4622  *)
4623 let all_functions_sorted =
4624   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4625                compare n1 n2) all_functions
4626
4627 (* Field types for structures. *)
4628 type field =
4629   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4630   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4631   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4632   | FUInt32
4633   | FInt32
4634   | FUInt64
4635   | FInt64
4636   | FBytes                      (* Any int measure that counts bytes. *)
4637   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4638   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4639
4640 (* Because we generate extra parsing code for LVM command line tools,
4641  * we have to pull out the LVM columns separately here.
4642  *)
4643 let lvm_pv_cols = [
4644   "pv_name", FString;
4645   "pv_uuid", FUUID;
4646   "pv_fmt", FString;
4647   "pv_size", FBytes;
4648   "dev_size", FBytes;
4649   "pv_free", FBytes;
4650   "pv_used", FBytes;
4651   "pv_attr", FString (* XXX *);
4652   "pv_pe_count", FInt64;
4653   "pv_pe_alloc_count", FInt64;
4654   "pv_tags", FString;
4655   "pe_start", FBytes;
4656   "pv_mda_count", FInt64;
4657   "pv_mda_free", FBytes;
4658   (* Not in Fedora 10:
4659      "pv_mda_size", FBytes;
4660   *)
4661 ]
4662 let lvm_vg_cols = [
4663   "vg_name", FString;
4664   "vg_uuid", FUUID;
4665   "vg_fmt", FString;
4666   "vg_attr", FString (* XXX *);
4667   "vg_size", FBytes;
4668   "vg_free", FBytes;
4669   "vg_sysid", FString;
4670   "vg_extent_size", FBytes;
4671   "vg_extent_count", FInt64;
4672   "vg_free_count", FInt64;
4673   "max_lv", FInt64;
4674   "max_pv", FInt64;
4675   "pv_count", FInt64;
4676   "lv_count", FInt64;
4677   "snap_count", FInt64;
4678   "vg_seqno", FInt64;
4679   "vg_tags", FString;
4680   "vg_mda_count", FInt64;
4681   "vg_mda_free", FBytes;
4682   (* Not in Fedora 10:
4683      "vg_mda_size", FBytes;
4684   *)
4685 ]
4686 let lvm_lv_cols = [
4687   "lv_name", FString;
4688   "lv_uuid", FUUID;
4689   "lv_attr", FString (* XXX *);
4690   "lv_major", FInt64;
4691   "lv_minor", FInt64;
4692   "lv_kernel_major", FInt64;
4693   "lv_kernel_minor", FInt64;
4694   "lv_size", FBytes;
4695   "seg_count", FInt64;
4696   "origin", FString;
4697   "snap_percent", FOptPercent;
4698   "copy_percent", FOptPercent;
4699   "move_pv", FString;
4700   "lv_tags", FString;
4701   "mirror_log", FString;
4702   "modules", FString;
4703 ]
4704
4705 (* Names and fields in all structures (in RStruct and RStructList)
4706  * that we support.
4707  *)
4708 let structs = [
4709   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4710    * not use this struct in any new code.
4711    *)
4712   "int_bool", [
4713     "i", FInt32;                (* for historical compatibility *)
4714     "b", FInt32;                (* for historical compatibility *)
4715   ];
4716
4717   (* LVM PVs, VGs, LVs. *)
4718   "lvm_pv", lvm_pv_cols;
4719   "lvm_vg", lvm_vg_cols;
4720   "lvm_lv", lvm_lv_cols;
4721
4722   (* Column names and types from stat structures.
4723    * NB. Can't use things like 'st_atime' because glibc header files
4724    * define some of these as macros.  Ugh.
4725    *)
4726   "stat", [
4727     "dev", FInt64;
4728     "ino", FInt64;
4729     "mode", FInt64;
4730     "nlink", FInt64;
4731     "uid", FInt64;
4732     "gid", FInt64;
4733     "rdev", FInt64;
4734     "size", FInt64;
4735     "blksize", FInt64;
4736     "blocks", FInt64;
4737     "atime", FInt64;
4738     "mtime", FInt64;
4739     "ctime", FInt64;
4740   ];
4741   "statvfs", [
4742     "bsize", FInt64;
4743     "frsize", FInt64;
4744     "blocks", FInt64;
4745     "bfree", FInt64;
4746     "bavail", FInt64;
4747     "files", FInt64;
4748     "ffree", FInt64;
4749     "favail", FInt64;
4750     "fsid", FInt64;
4751     "flag", FInt64;
4752     "namemax", FInt64;
4753   ];
4754
4755   (* Column names in dirent structure. *)
4756   "dirent", [
4757     "ino", FInt64;
4758     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4759     "ftyp", FChar;
4760     "name", FString;
4761   ];
4762
4763   (* Version numbers. *)
4764   "version", [
4765     "major", FInt64;
4766     "minor", FInt64;
4767     "release", FInt64;
4768     "extra", FString;
4769   ];
4770
4771   (* Extended attribute. *)
4772   "xattr", [
4773     "attrname", FString;
4774     "attrval", FBuffer;
4775   ];
4776
4777   (* Inotify events. *)
4778   "inotify_event", [
4779     "in_wd", FInt64;
4780     "in_mask", FUInt32;
4781     "in_cookie", FUInt32;
4782     "in_name", FString;
4783   ];
4784
4785   (* Partition table entry. *)
4786   "partition", [
4787     "part_num", FInt32;
4788     "part_start", FBytes;
4789     "part_end", FBytes;
4790     "part_size", FBytes;
4791   ];
4792 ] (* end of structs *)
4793
4794 (* Ugh, Java has to be different ..
4795  * These names are also used by the Haskell bindings.
4796  *)
4797 let java_structs = [
4798   "int_bool", "IntBool";
4799   "lvm_pv", "PV";
4800   "lvm_vg", "VG";
4801   "lvm_lv", "LV";
4802   "stat", "Stat";
4803   "statvfs", "StatVFS";
4804   "dirent", "Dirent";
4805   "version", "Version";
4806   "xattr", "XAttr";
4807   "inotify_event", "INotifyEvent";
4808   "partition", "Partition";
4809 ]
4810
4811 (* What structs are actually returned. *)
4812 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4813
4814 (* Returns a list of RStruct/RStructList structs that are returned
4815  * by any function.  Each element of returned list is a pair:
4816  *
4817  * (structname, RStructOnly)
4818  *    == there exists function which returns RStruct (_, structname)
4819  * (structname, RStructListOnly)
4820  *    == there exists function which returns RStructList (_, structname)
4821  * (structname, RStructAndList)
4822  *    == there are functions returning both RStruct (_, structname)
4823  *                                      and RStructList (_, structname)
4824  *)
4825 let rstructs_used_by functions =
4826   (* ||| is a "logical OR" for rstructs_used_t *)
4827   let (|||) a b =
4828     match a, b with
4829     | RStructAndList, _
4830     | _, RStructAndList -> RStructAndList
4831     | RStructOnly, RStructListOnly
4832     | RStructListOnly, RStructOnly -> RStructAndList
4833     | RStructOnly, RStructOnly -> RStructOnly
4834     | RStructListOnly, RStructListOnly -> RStructListOnly
4835   in
4836
4837   let h = Hashtbl.create 13 in
4838
4839   (* if elem->oldv exists, update entry using ||| operator,
4840    * else just add elem->newv to the hash
4841    *)
4842   let update elem newv =
4843     try  let oldv = Hashtbl.find h elem in
4844          Hashtbl.replace h elem (newv ||| oldv)
4845     with Not_found -> Hashtbl.add h elem newv
4846   in
4847
4848   List.iter (
4849     fun (_, style, _, _, _, _, _) ->
4850       match fst style with
4851       | RStruct (_, structname) -> update structname RStructOnly
4852       | RStructList (_, structname) -> update structname RStructListOnly
4853       | _ -> ()
4854   ) functions;
4855
4856   (* return key->values as a list of (key,value) *)
4857   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4858
4859 (* Used for testing language bindings. *)
4860 type callt =
4861   | CallString of string
4862   | CallOptString of string option
4863   | CallStringList of string list
4864   | CallInt of int
4865   | CallInt64 of int64
4866   | CallBool of bool
4867
4868 (* Used to memoize the result of pod2text. *)
4869 let pod2text_memo_filename = "src/.pod2text.data"
4870 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4871   try
4872     let chan = open_in pod2text_memo_filename in
4873     let v = input_value chan in
4874     close_in chan;
4875     v
4876   with
4877     _ -> Hashtbl.create 13
4878 let pod2text_memo_updated () =
4879   let chan = open_out pod2text_memo_filename in
4880   output_value chan pod2text_memo;
4881   close_out chan
4882
4883 (* Useful functions.
4884  * Note we don't want to use any external OCaml libraries which
4885  * makes this a bit harder than it should be.
4886  *)
4887 module StringMap = Map.Make (String)
4888
4889 let failwithf fs = ksprintf failwith fs
4890
4891 let unique = let i = ref 0 in fun () -> incr i; !i
4892
4893 let replace_char s c1 c2 =
4894   let s2 = String.copy s in
4895   let r = ref false in
4896   for i = 0 to String.length s2 - 1 do
4897     if String.unsafe_get s2 i = c1 then (
4898       String.unsafe_set s2 i c2;
4899       r := true
4900     )
4901   done;
4902   if not !r then s else s2
4903
4904 let isspace c =
4905   c = ' '
4906   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4907
4908 let triml ?(test = isspace) str =
4909   let i = ref 0 in
4910   let n = ref (String.length str) in
4911   while !n > 0 && test str.[!i]; do
4912     decr n;
4913     incr i
4914   done;
4915   if !i = 0 then str
4916   else String.sub str !i !n
4917
4918 let trimr ?(test = isspace) str =
4919   let n = ref (String.length str) in
4920   while !n > 0 && test str.[!n-1]; do
4921     decr n
4922   done;
4923   if !n = String.length str then str
4924   else String.sub str 0 !n
4925
4926 let trim ?(test = isspace) str =
4927   trimr ~test (triml ~test str)
4928
4929 let rec find s sub =
4930   let len = String.length s in
4931   let sublen = String.length sub in
4932   let rec loop i =
4933     if i <= len-sublen then (
4934       let rec loop2 j =
4935         if j < sublen then (
4936           if s.[i+j] = sub.[j] then loop2 (j+1)
4937           else -1
4938         ) else
4939           i (* found *)
4940       in
4941       let r = loop2 0 in
4942       if r = -1 then loop (i+1) else r
4943     ) else
4944       -1 (* not found *)
4945   in
4946   loop 0
4947
4948 let rec replace_str s s1 s2 =
4949   let len = String.length s in
4950   let sublen = String.length s1 in
4951   let i = find s s1 in
4952   if i = -1 then s
4953   else (
4954     let s' = String.sub s 0 i in
4955     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4956     s' ^ s2 ^ replace_str s'' s1 s2
4957   )
4958
4959 let rec string_split sep str =
4960   let len = String.length str in
4961   let seplen = String.length sep in
4962   let i = find str sep in
4963   if i = -1 then [str]
4964   else (
4965     let s' = String.sub str 0 i in
4966     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4967     s' :: string_split sep s''
4968   )
4969
4970 let files_equal n1 n2 =
4971   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4972   match Sys.command cmd with
4973   | 0 -> true
4974   | 1 -> false
4975   | i -> failwithf "%s: failed with error code %d" cmd i
4976
4977 let rec filter_map f = function
4978   | [] -> []
4979   | x :: xs ->
4980       match f x with
4981       | Some y -> y :: filter_map f xs
4982       | None -> filter_map f xs
4983
4984 let rec find_map f = function
4985   | [] -> raise Not_found
4986   | x :: xs ->
4987       match f x with
4988       | Some y -> y
4989       | None -> find_map f xs
4990
4991 let iteri f xs =
4992   let rec loop i = function
4993     | [] -> ()
4994     | x :: xs -> f i x; loop (i+1) xs
4995   in
4996   loop 0 xs
4997
4998 let mapi f xs =
4999   let rec loop i = function
5000     | [] -> []
5001     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5002   in
5003   loop 0 xs
5004
5005 let count_chars c str =
5006   let count = ref 0 in
5007   for i = 0 to String.length str - 1 do
5008     if c = String.unsafe_get str i then incr count
5009   done;
5010   !count
5011
5012 let name_of_argt = function
5013   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5014   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5015   | FileIn n | FileOut n -> n
5016
5017 let java_name_of_struct typ =
5018   try List.assoc typ java_structs
5019   with Not_found ->
5020     failwithf
5021       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5022
5023 let cols_of_struct typ =
5024   try List.assoc typ structs
5025   with Not_found ->
5026     failwithf "cols_of_struct: unknown struct %s" typ
5027
5028 let seq_of_test = function
5029   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5030   | TestOutputListOfDevices (s, _)
5031   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5032   | TestOutputTrue s | TestOutputFalse s
5033   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5034   | TestOutputStruct (s, _)
5035   | TestLastFail s -> s
5036
5037 (* Handling for function flags. *)
5038 let protocol_limit_warning =
5039   "Because of the message protocol, there is a transfer limit
5040 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5041
5042 let danger_will_robinson =
5043   "B<This command is dangerous.  Without careful use you
5044 can easily destroy all your data>."
5045
5046 let deprecation_notice flags =
5047   try
5048     let alt =
5049       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5050     let txt =
5051       sprintf "This function is deprecated.
5052 In new code, use the C<%s> call instead.
5053
5054 Deprecated functions will not be removed from the API, but the
5055 fact that they are deprecated indicates that there are problems
5056 with correct use of these functions." alt in
5057     Some txt
5058   with
5059     Not_found -> None
5060
5061 (* Create list of optional groups. *)
5062 let optgroups =
5063   let h = Hashtbl.create 13 in
5064   List.iter (
5065     fun (name, _, _, flags, _, _, _) ->
5066       List.iter (
5067         function
5068         | Optional group ->
5069             let names = try Hashtbl.find h group with Not_found -> [] in
5070             Hashtbl.replace h group (name :: names)
5071         | _ -> ()
5072       ) flags
5073   ) daemon_functions;
5074   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5075   let groups =
5076     List.map (
5077       fun group -> group, List.sort compare (Hashtbl.find h group)
5078     ) groups in
5079   List.sort (fun x y -> compare (fst x) (fst y)) groups
5080
5081 (* Check function names etc. for consistency. *)
5082 let check_functions () =
5083   let contains_uppercase str =
5084     let len = String.length str in
5085     let rec loop i =
5086       if i >= len then false
5087       else (
5088         let c = str.[i] in
5089         if c >= 'A' && c <= 'Z' then true
5090         else loop (i+1)
5091       )
5092     in
5093     loop 0
5094   in
5095
5096   (* Check function names. *)
5097   List.iter (
5098     fun (name, _, _, _, _, _, _) ->
5099       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5100         failwithf "function name %s does not need 'guestfs' prefix" name;
5101       if name = "" then
5102         failwithf "function name is empty";
5103       if name.[0] < 'a' || name.[0] > 'z' then
5104         failwithf "function name %s must start with lowercase a-z" name;
5105       if String.contains name '-' then
5106         failwithf "function name %s should not contain '-', use '_' instead."
5107           name
5108   ) all_functions;
5109
5110   (* Check function parameter/return names. *)
5111   List.iter (
5112     fun (name, style, _, _, _, _, _) ->
5113       let check_arg_ret_name n =
5114         if contains_uppercase n then
5115           failwithf "%s param/ret %s should not contain uppercase chars"
5116             name n;
5117         if String.contains n '-' || String.contains n '_' then
5118           failwithf "%s param/ret %s should not contain '-' or '_'"
5119             name n;
5120         if n = "value" then
5121           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;
5122         if n = "int" || n = "char" || n = "short" || n = "long" then
5123           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5124         if n = "i" || n = "n" then
5125           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5126         if n = "argv" || n = "args" then
5127           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5128
5129         (* List Haskell, OCaml and C keywords here.
5130          * http://www.haskell.org/haskellwiki/Keywords
5131          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5132          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5133          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5134          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5135          * Omitting _-containing words, since they're handled above.
5136          * Omitting the OCaml reserved word, "val", is ok,
5137          * and saves us from renaming several parameters.
5138          *)
5139         let reserved = [
5140           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5141           "char"; "class"; "const"; "constraint"; "continue"; "data";
5142           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5143           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5144           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5145           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5146           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5147           "interface";
5148           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5149           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5150           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5151           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5152           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5153           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5154           "volatile"; "when"; "where"; "while";
5155           ] in
5156         if List.mem n reserved then
5157           failwithf "%s has param/ret using reserved word %s" name n;
5158       in
5159
5160       (match fst style with
5161        | RErr -> ()
5162        | RInt n | RInt64 n | RBool n
5163        | RConstString n | RConstOptString n | RString n
5164        | RStringList n | RStruct (n, _) | RStructList (n, _)
5165        | RHashtable n | RBufferOut n ->
5166            check_arg_ret_name n
5167       );
5168       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5169   ) all_functions;
5170
5171   (* Check short descriptions. *)
5172   List.iter (
5173     fun (name, _, _, _, _, shortdesc, _) ->
5174       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5175         failwithf "short description of %s should begin with lowercase." name;
5176       let c = shortdesc.[String.length shortdesc-1] in
5177       if c = '\n' || c = '.' then
5178         failwithf "short description of %s should not end with . or \\n." name
5179   ) all_functions;
5180
5181   (* Check long descriptions. *)
5182   List.iter (
5183     fun (name, _, _, _, _, _, longdesc) ->
5184       if longdesc.[String.length longdesc-1] = '\n' then
5185         failwithf "long description of %s should not end with \\n." name
5186   ) all_functions;
5187
5188   (* Check proc_nrs. *)
5189   List.iter (
5190     fun (name, _, proc_nr, _, _, _, _) ->
5191       if proc_nr <= 0 then
5192         failwithf "daemon function %s should have proc_nr > 0" name
5193   ) daemon_functions;
5194
5195   List.iter (
5196     fun (name, _, proc_nr, _, _, _, _) ->
5197       if proc_nr <> -1 then
5198         failwithf "non-daemon function %s should have proc_nr -1" name
5199   ) non_daemon_functions;
5200
5201   let proc_nrs =
5202     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5203       daemon_functions in
5204   let proc_nrs =
5205     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5206   let rec loop = function
5207     | [] -> ()
5208     | [_] -> ()
5209     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5210         loop rest
5211     | (name1,nr1) :: (name2,nr2) :: _ ->
5212         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5213           name1 name2 nr1 nr2
5214   in
5215   loop proc_nrs;
5216
5217   (* Check tests. *)
5218   List.iter (
5219     function
5220       (* Ignore functions that have no tests.  We generate a
5221        * warning when the user does 'make check' instead.
5222        *)
5223     | name, _, _, _, [], _, _ -> ()
5224     | name, _, _, _, tests, _, _ ->
5225         let funcs =
5226           List.map (
5227             fun (_, _, test) ->
5228               match seq_of_test test with
5229               | [] ->
5230                   failwithf "%s has a test containing an empty sequence" name
5231               | cmds -> List.map List.hd cmds
5232           ) tests in
5233         let funcs = List.flatten funcs in
5234
5235         let tested = List.mem name funcs in
5236
5237         if not tested then
5238           failwithf "function %s has tests but does not test itself" name
5239   ) all_functions
5240
5241 (* 'pr' prints to the current output file. *)
5242 let chan = ref Pervasives.stdout
5243 let lines = ref 0
5244 let pr fs =
5245   ksprintf
5246     (fun str ->
5247        let i = count_chars '\n' str in
5248        lines := !lines + i;
5249        output_string !chan str
5250     ) fs
5251
5252 let copyright_years =
5253   let this_year = 1900 + (localtime (time ())).tm_year in
5254   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5255
5256 (* Generate a header block in a number of standard styles. *)
5257 type comment_style =
5258     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5259 type license = GPLv2plus | LGPLv2plus
5260
5261 let generate_header ?(extra_inputs = []) comment license =
5262   let inputs = "src/generator.ml" :: extra_inputs in
5263   let c = match comment with
5264     | CStyle ->         pr "/* "; " *"
5265     | CPlusPlusStyle -> pr "// "; "//"
5266     | HashStyle ->      pr "# ";  "#"
5267     | OCamlStyle ->     pr "(* "; " *"
5268     | HaskellStyle ->   pr "{- "; "  " in
5269   pr "libguestfs generated file\n";
5270   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5271   List.iter (pr "%s   %s\n" c) inputs;
5272   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5273   pr "%s\n" c;
5274   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5275   pr "%s\n" c;
5276   (match license with
5277    | GPLv2plus ->
5278        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5279        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5280        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5281        pr "%s (at your option) any later version.\n" c;
5282        pr "%s\n" c;
5283        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5284        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5285        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5286        pr "%s GNU General Public License for more details.\n" c;
5287        pr "%s\n" c;
5288        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5289        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5290        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5291
5292    | LGPLv2plus ->
5293        pr "%s This library is free software; you can redistribute it and/or\n" c;
5294        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5295        pr "%s License as published by the Free Software Foundation; either\n" c;
5296        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5297        pr "%s\n" c;
5298        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5299        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5300        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5301        pr "%s Lesser General Public License for more details.\n" c;
5302        pr "%s\n" c;
5303        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5304        pr "%s License along with this library; if not, write to the Free Software\n" c;
5305        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5306   );
5307   (match comment with
5308    | CStyle -> pr " */\n"
5309    | CPlusPlusStyle
5310    | HashStyle -> ()
5311    | OCamlStyle -> pr " *)\n"
5312    | HaskellStyle -> pr "-}\n"
5313   );
5314   pr "\n"
5315
5316 (* Start of main code generation functions below this line. *)
5317
5318 (* Generate the pod documentation for the C API. *)
5319 let rec generate_actions_pod () =
5320   List.iter (
5321     fun (shortname, style, _, flags, _, _, longdesc) ->
5322       if not (List.mem NotInDocs flags) then (
5323         let name = "guestfs_" ^ shortname in
5324         pr "=head2 %s\n\n" name;
5325         pr " ";
5326         generate_prototype ~extern:false ~handle:"g" name style;
5327         pr "\n\n";
5328         pr "%s\n\n" longdesc;
5329         (match fst style with
5330          | RErr ->
5331              pr "This function returns 0 on success or -1 on error.\n\n"
5332          | RInt _ ->
5333              pr "On error this function returns -1.\n\n"
5334          | RInt64 _ ->
5335              pr "On error this function returns -1.\n\n"
5336          | RBool _ ->
5337              pr "This function returns a C truth value on success or -1 on error.\n\n"
5338          | RConstString _ ->
5339              pr "This function returns a string, or NULL on error.
5340 The string is owned by the guest handle and must I<not> be freed.\n\n"
5341          | RConstOptString _ ->
5342              pr "This function returns a string which may be NULL.
5343 There is way to return an error from this function.
5344 The string is owned by the guest handle and must I<not> be freed.\n\n"
5345          | RString _ ->
5346              pr "This function returns a string, or NULL on error.
5347 I<The caller must free the returned string after use>.\n\n"
5348          | RStringList _ ->
5349              pr "This function returns a NULL-terminated array of strings
5350 (like L<environ(3)>), or NULL if there was an error.
5351 I<The caller must free the strings and the array after use>.\n\n"
5352          | RStruct (_, typ) ->
5353              pr "This function returns a C<struct guestfs_%s *>,
5354 or NULL if there was an error.
5355 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5356          | RStructList (_, typ) ->
5357              pr "This function returns a C<struct guestfs_%s_list *>
5358 (see E<lt>guestfs-structs.hE<gt>),
5359 or NULL if there was an error.
5360 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5361          | RHashtable _ ->
5362              pr "This function returns a NULL-terminated array of
5363 strings, or NULL if there was an error.
5364 The array of strings will always have length C<2n+1>, where
5365 C<n> keys and values alternate, followed by the trailing NULL entry.
5366 I<The caller must free the strings and the array after use>.\n\n"
5367          | RBufferOut _ ->
5368              pr "This function returns a buffer, or NULL on error.
5369 The size of the returned buffer is written to C<*size_r>.
5370 I<The caller must free the returned buffer after use>.\n\n"
5371         );
5372         if List.mem ProtocolLimitWarning flags then
5373           pr "%s\n\n" protocol_limit_warning;
5374         if List.mem DangerWillRobinson flags then
5375           pr "%s\n\n" danger_will_robinson;
5376         match deprecation_notice flags with
5377         | None -> ()
5378         | Some txt -> pr "%s\n\n" txt
5379       )
5380   ) all_functions_sorted
5381
5382 and generate_structs_pod () =
5383   (* Structs documentation. *)
5384   List.iter (
5385     fun (typ, cols) ->
5386       pr "=head2 guestfs_%s\n" typ;
5387       pr "\n";
5388       pr " struct guestfs_%s {\n" typ;
5389       List.iter (
5390         function
5391         | name, FChar -> pr "   char %s;\n" name
5392         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5393         | name, FInt32 -> pr "   int32_t %s;\n" name
5394         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5395         | name, FInt64 -> pr "   int64_t %s;\n" name
5396         | name, FString -> pr "   char *%s;\n" name
5397         | name, FBuffer ->
5398             pr "   /* The next two fields describe a byte array. */\n";
5399             pr "   uint32_t %s_len;\n" name;
5400             pr "   char *%s;\n" name
5401         | name, FUUID ->
5402             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5403             pr "   char %s[32];\n" name
5404         | name, FOptPercent ->
5405             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5406             pr "   float %s;\n" name
5407       ) cols;
5408       pr " };\n";
5409       pr " \n";
5410       pr " struct guestfs_%s_list {\n" typ;
5411       pr "   uint32_t len; /* Number of elements in list. */\n";
5412       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5413       pr " };\n";
5414       pr " \n";
5415       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5416       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5417         typ typ;
5418       pr "\n"
5419   ) structs
5420
5421 and generate_availability_pod () =
5422   (* Availability documentation. *)
5423   pr "=over 4\n";
5424   pr "\n";
5425   List.iter (
5426     fun (group, functions) ->
5427       pr "=item B<%s>\n" group;
5428       pr "\n";
5429       pr "The following functions:\n";
5430       List.iter (pr "L</guestfs_%s>\n") functions;
5431       pr "\n"
5432   ) optgroups;
5433   pr "=back\n";
5434   pr "\n"
5435
5436 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5437  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5438  *
5439  * We have to use an underscore instead of a dash because otherwise
5440  * rpcgen generates incorrect code.
5441  *
5442  * This header is NOT exported to clients, but see also generate_structs_h.
5443  *)
5444 and generate_xdr () =
5445   generate_header CStyle LGPLv2plus;
5446
5447   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5448   pr "typedef string str<>;\n";
5449   pr "\n";
5450
5451   (* Internal structures. *)
5452   List.iter (
5453     function
5454     | typ, cols ->
5455         pr "struct guestfs_int_%s {\n" typ;
5456         List.iter (function
5457                    | name, FChar -> pr "  char %s;\n" name
5458                    | name, FString -> pr "  string %s<>;\n" name
5459                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5460                    | name, FUUID -> pr "  opaque %s[32];\n" name
5461                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5462                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5463                    | name, FOptPercent -> pr "  float %s;\n" name
5464                   ) cols;
5465         pr "};\n";
5466         pr "\n";
5467         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5468         pr "\n";
5469   ) structs;
5470
5471   List.iter (
5472     fun (shortname, style, _, _, _, _, _) ->
5473       let name = "guestfs_" ^ shortname in
5474
5475       (match snd style with
5476        | [] -> ()
5477        | args ->
5478            pr "struct %s_args {\n" name;
5479            List.iter (
5480              function
5481              | Pathname n | Device n | Dev_or_Path n | String n ->
5482                  pr "  string %s<>;\n" n
5483              | OptString n -> pr "  str *%s;\n" n
5484              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5485              | Bool n -> pr "  bool %s;\n" n
5486              | Int n -> pr "  int %s;\n" n
5487              | Int64 n -> pr "  hyper %s;\n" n
5488              | FileIn _ | FileOut _ -> ()
5489            ) args;
5490            pr "};\n\n"
5491       );
5492       (match fst style with
5493        | RErr -> ()
5494        | RInt n ->
5495            pr "struct %s_ret {\n" name;
5496            pr "  int %s;\n" n;
5497            pr "};\n\n"
5498        | RInt64 n ->
5499            pr "struct %s_ret {\n" name;
5500            pr "  hyper %s;\n" n;
5501            pr "};\n\n"
5502        | RBool n ->
5503            pr "struct %s_ret {\n" name;
5504            pr "  bool %s;\n" n;
5505            pr "};\n\n"
5506        | RConstString _ | RConstOptString _ ->
5507            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5508        | RString n ->
5509            pr "struct %s_ret {\n" name;
5510            pr "  string %s<>;\n" n;
5511            pr "};\n\n"
5512        | RStringList n ->
5513            pr "struct %s_ret {\n" name;
5514            pr "  str %s<>;\n" n;
5515            pr "};\n\n"
5516        | RStruct (n, typ) ->
5517            pr "struct %s_ret {\n" name;
5518            pr "  guestfs_int_%s %s;\n" typ n;
5519            pr "};\n\n"
5520        | RStructList (n, typ) ->
5521            pr "struct %s_ret {\n" name;
5522            pr "  guestfs_int_%s_list %s;\n" typ n;
5523            pr "};\n\n"
5524        | RHashtable n ->
5525            pr "struct %s_ret {\n" name;
5526            pr "  str %s<>;\n" n;
5527            pr "};\n\n"
5528        | RBufferOut n ->
5529            pr "struct %s_ret {\n" name;
5530            pr "  opaque %s<>;\n" n;
5531            pr "};\n\n"
5532       );
5533   ) daemon_functions;
5534
5535   (* Table of procedure numbers. *)
5536   pr "enum guestfs_procedure {\n";
5537   List.iter (
5538     fun (shortname, _, proc_nr, _, _, _, _) ->
5539       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5540   ) daemon_functions;
5541   pr "  GUESTFS_PROC_NR_PROCS\n";
5542   pr "};\n";
5543   pr "\n";
5544
5545   (* Having to choose a maximum message size is annoying for several
5546    * reasons (it limits what we can do in the API), but it (a) makes
5547    * the protocol a lot simpler, and (b) provides a bound on the size
5548    * of the daemon which operates in limited memory space.
5549    *)
5550   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5551   pr "\n";
5552
5553   (* Message header, etc. *)
5554   pr "\
5555 /* The communication protocol is now documented in the guestfs(3)
5556  * manpage.
5557  */
5558
5559 const GUESTFS_PROGRAM = 0x2000F5F5;
5560 const GUESTFS_PROTOCOL_VERSION = 1;
5561
5562 /* These constants must be larger than any possible message length. */
5563 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5564 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5565
5566 enum guestfs_message_direction {
5567   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5568   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5569 };
5570
5571 enum guestfs_message_status {
5572   GUESTFS_STATUS_OK = 0,
5573   GUESTFS_STATUS_ERROR = 1
5574 };
5575
5576 const GUESTFS_ERROR_LEN = 256;
5577
5578 struct guestfs_message_error {
5579   string error_message<GUESTFS_ERROR_LEN>;
5580 };
5581
5582 struct guestfs_message_header {
5583   unsigned prog;                     /* GUESTFS_PROGRAM */
5584   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5585   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5586   guestfs_message_direction direction;
5587   unsigned serial;                   /* message serial number */
5588   guestfs_message_status status;
5589 };
5590
5591 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5592
5593 struct guestfs_chunk {
5594   int cancel;                        /* if non-zero, transfer is cancelled */
5595   /* data size is 0 bytes if the transfer has finished successfully */
5596   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5597 };
5598 "
5599
5600 (* Generate the guestfs-structs.h file. *)
5601 and generate_structs_h () =
5602   generate_header CStyle LGPLv2plus;
5603
5604   (* This is a public exported header file containing various
5605    * structures.  The structures are carefully written to have
5606    * exactly the same in-memory format as the XDR structures that
5607    * we use on the wire to the daemon.  The reason for creating
5608    * copies of these structures here is just so we don't have to
5609    * export the whole of guestfs_protocol.h (which includes much
5610    * unrelated and XDR-dependent stuff that we don't want to be
5611    * public, or required by clients).
5612    *
5613    * To reiterate, we will pass these structures to and from the
5614    * client with a simple assignment or memcpy, so the format
5615    * must be identical to what rpcgen / the RFC defines.
5616    *)
5617
5618   (* Public structures. *)
5619   List.iter (
5620     fun (typ, cols) ->
5621       pr "struct guestfs_%s {\n" typ;
5622       List.iter (
5623         function
5624         | name, FChar -> pr "  char %s;\n" name
5625         | name, FString -> pr "  char *%s;\n" name
5626         | name, FBuffer ->
5627             pr "  uint32_t %s_len;\n" name;
5628             pr "  char *%s;\n" name
5629         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5630         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5631         | name, FInt32 -> pr "  int32_t %s;\n" name
5632         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5633         | name, FInt64 -> pr "  int64_t %s;\n" name
5634         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5635       ) cols;
5636       pr "};\n";
5637       pr "\n";
5638       pr "struct guestfs_%s_list {\n" typ;
5639       pr "  uint32_t len;\n";
5640       pr "  struct guestfs_%s *val;\n" typ;
5641       pr "};\n";
5642       pr "\n";
5643       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5644       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5645       pr "\n"
5646   ) structs
5647
5648 (* Generate the guestfs-actions.h file. *)
5649 and generate_actions_h () =
5650   generate_header CStyle LGPLv2plus;
5651   List.iter (
5652     fun (shortname, style, _, _, _, _, _) ->
5653       let name = "guestfs_" ^ shortname in
5654       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5655         name style
5656   ) all_functions
5657
5658 (* Generate the guestfs-internal-actions.h file. *)
5659 and generate_internal_actions_h () =
5660   generate_header CStyle LGPLv2plus;
5661   List.iter (
5662     fun (shortname, style, _, _, _, _, _) ->
5663       let name = "guestfs__" ^ shortname in
5664       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5665         name style
5666   ) non_daemon_functions
5667
5668 (* Generate the client-side dispatch stubs. *)
5669 and generate_client_actions () =
5670   generate_header CStyle LGPLv2plus;
5671
5672   pr "\
5673 #include <stdio.h>
5674 #include <stdlib.h>
5675 #include <stdint.h>
5676 #include <string.h>
5677 #include <inttypes.h>
5678
5679 #include \"guestfs.h\"
5680 #include \"guestfs-internal.h\"
5681 #include \"guestfs-internal-actions.h\"
5682 #include \"guestfs_protocol.h\"
5683
5684 #define error guestfs_error
5685 //#define perrorf guestfs_perrorf
5686 #define safe_malloc guestfs_safe_malloc
5687 #define safe_realloc guestfs_safe_realloc
5688 //#define safe_strdup guestfs_safe_strdup
5689 #define safe_memdup guestfs_safe_memdup
5690
5691 /* Check the return message from a call for validity. */
5692 static int
5693 check_reply_header (guestfs_h *g,
5694                     const struct guestfs_message_header *hdr,
5695                     unsigned int proc_nr, unsigned int serial)
5696 {
5697   if (hdr->prog != GUESTFS_PROGRAM) {
5698     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5699     return -1;
5700   }
5701   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5702     error (g, \"wrong protocol version (%%d/%%d)\",
5703            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5704     return -1;
5705   }
5706   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5707     error (g, \"unexpected message direction (%%d/%%d)\",
5708            hdr->direction, GUESTFS_DIRECTION_REPLY);
5709     return -1;
5710   }
5711   if (hdr->proc != proc_nr) {
5712     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5713     return -1;
5714   }
5715   if (hdr->serial != serial) {
5716     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5717     return -1;
5718   }
5719
5720   return 0;
5721 }
5722
5723 /* Check we are in the right state to run a high-level action. */
5724 static int
5725 check_state (guestfs_h *g, const char *caller)
5726 {
5727   if (!guestfs__is_ready (g)) {
5728     if (guestfs__is_config (g) || guestfs__is_launching (g))
5729       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5730         caller);
5731     else
5732       error (g, \"%%s called from the wrong state, %%d != READY\",
5733         caller, guestfs__get_state (g));
5734     return -1;
5735   }
5736   return 0;
5737 }
5738
5739 ";
5740
5741   (* Generate code to generate guestfish call traces. *)
5742   let trace_call shortname style =
5743     pr "  if (guestfs__get_trace (g)) {\n";
5744
5745     let needs_i =
5746       List.exists (function
5747                    | StringList _ | DeviceList _ -> true
5748                    | _ -> false) (snd style) in
5749     if needs_i then (
5750       pr "    int i;\n";
5751       pr "\n"
5752     );
5753
5754     pr "    printf (\"%s\");\n" shortname;
5755     List.iter (
5756       function
5757       | String n                        (* strings *)
5758       | Device n
5759       | Pathname n
5760       | Dev_or_Path n
5761       | FileIn n
5762       | FileOut n ->
5763           (* guestfish doesn't support string escaping, so neither do we *)
5764           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5765       | OptString n ->                  (* string option *)
5766           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5767           pr "    else printf (\" null\");\n"
5768       | StringList n
5769       | DeviceList n ->                 (* string list *)
5770           pr "    putchar (' ');\n";
5771           pr "    putchar ('\"');\n";
5772           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5773           pr "      if (i > 0) putchar (' ');\n";
5774           pr "      fputs (%s[i], stdout);\n" n;
5775           pr "    }\n";
5776           pr "    putchar ('\"');\n";
5777       | Bool n ->                       (* boolean *)
5778           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5779       | Int n ->                        (* int *)
5780           pr "    printf (\" %%d\", %s);\n" n
5781       | Int64 n ->
5782           pr "    printf (\" %%\" PRIi64, %s);\n" n
5783     ) (snd style);
5784     pr "    putchar ('\\n');\n";
5785     pr "  }\n";
5786     pr "\n";
5787   in
5788
5789   (* For non-daemon functions, generate a wrapper around each function. *)
5790   List.iter (
5791     fun (shortname, style, _, _, _, _, _) ->
5792       let name = "guestfs_" ^ shortname in
5793
5794       generate_prototype ~extern:false ~semicolon:false ~newline:true
5795         ~handle:"g" name style;
5796       pr "{\n";
5797       trace_call shortname style;
5798       pr "  return guestfs__%s " shortname;
5799       generate_c_call_args ~handle:"g" style;
5800       pr ";\n";
5801       pr "}\n";
5802       pr "\n"
5803   ) non_daemon_functions;
5804
5805   (* Client-side stubs for each function. *)
5806   List.iter (
5807     fun (shortname, style, _, _, _, _, _) ->
5808       let name = "guestfs_" ^ shortname in
5809
5810       (* Generate the action stub. *)
5811       generate_prototype ~extern:false ~semicolon:false ~newline:true
5812         ~handle:"g" name style;
5813
5814       let error_code =
5815         match fst style with
5816         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5817         | RConstString _ | RConstOptString _ ->
5818             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5819         | RString _ | RStringList _
5820         | RStruct _ | RStructList _
5821         | RHashtable _ | RBufferOut _ ->
5822             "NULL" in
5823
5824       pr "{\n";
5825
5826       (match snd style with
5827        | [] -> ()
5828        | _ -> pr "  struct %s_args args;\n" name
5829       );
5830
5831       pr "  guestfs_message_header hdr;\n";
5832       pr "  guestfs_message_error err;\n";
5833       let has_ret =
5834         match fst style with
5835         | RErr -> false
5836         | RConstString _ | RConstOptString _ ->
5837             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5838         | RInt _ | RInt64 _
5839         | RBool _ | RString _ | RStringList _
5840         | RStruct _ | RStructList _
5841         | RHashtable _ | RBufferOut _ ->
5842             pr "  struct %s_ret ret;\n" name;
5843             true in
5844
5845       pr "  int serial;\n";
5846       pr "  int r;\n";
5847       pr "\n";
5848       trace_call shortname style;
5849       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5850         shortname error_code;
5851       pr "  guestfs___set_busy (g);\n";
5852       pr "\n";
5853
5854       (* Send the main header and arguments. *)
5855       (match snd style with
5856        | [] ->
5857            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5858              (String.uppercase shortname)
5859        | args ->
5860            List.iter (
5861              function
5862              | Pathname n | Device n | Dev_or_Path n | String n ->
5863                  pr "  args.%s = (char *) %s;\n" n n
5864              | OptString n ->
5865                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5866              | StringList n | DeviceList n ->
5867                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5868                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5869              | Bool n ->
5870                  pr "  args.%s = %s;\n" n n
5871              | Int n ->
5872                  pr "  args.%s = %s;\n" n n
5873              | Int64 n ->
5874                  pr "  args.%s = %s;\n" n n
5875              | FileIn _ | FileOut _ -> ()
5876            ) args;
5877            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5878              (String.uppercase shortname);
5879            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5880              name;
5881       );
5882       pr "  if (serial == -1) {\n";
5883       pr "    guestfs___end_busy (g);\n";
5884       pr "    return %s;\n" error_code;
5885       pr "  }\n";
5886       pr "\n";
5887
5888       (* Send any additional files (FileIn) requested. *)
5889       let need_read_reply_label = ref false in
5890       List.iter (
5891         function
5892         | FileIn n ->
5893             pr "  r = guestfs___send_file (g, %s);\n" n;
5894             pr "  if (r == -1) {\n";
5895             pr "    guestfs___end_busy (g);\n";
5896             pr "    return %s;\n" error_code;
5897             pr "  }\n";
5898             pr "  if (r == -2) /* daemon cancelled */\n";
5899             pr "    goto read_reply;\n";
5900             need_read_reply_label := true;
5901             pr "\n";
5902         | _ -> ()
5903       ) (snd style);
5904
5905       (* Wait for the reply from the remote end. *)
5906       if !need_read_reply_label then pr " read_reply:\n";
5907       pr "  memset (&hdr, 0, sizeof hdr);\n";
5908       pr "  memset (&err, 0, sizeof err);\n";
5909       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5910       pr "\n";
5911       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5912       if not has_ret then
5913         pr "NULL, NULL"
5914       else
5915         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5916       pr ");\n";
5917
5918       pr "  if (r == -1) {\n";
5919       pr "    guestfs___end_busy (g);\n";
5920       pr "    return %s;\n" error_code;
5921       pr "  }\n";
5922       pr "\n";
5923
5924       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5925         (String.uppercase shortname);
5926       pr "    guestfs___end_busy (g);\n";
5927       pr "    return %s;\n" error_code;
5928       pr "  }\n";
5929       pr "\n";
5930
5931       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5932       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5933       pr "    free (err.error_message);\n";
5934       pr "    guestfs___end_busy (g);\n";
5935       pr "    return %s;\n" error_code;
5936       pr "  }\n";
5937       pr "\n";
5938
5939       (* Expecting to receive further files (FileOut)? *)
5940       List.iter (
5941         function
5942         | FileOut n ->
5943             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5944             pr "    guestfs___end_busy (g);\n";
5945             pr "    return %s;\n" error_code;
5946             pr "  }\n";
5947             pr "\n";
5948         | _ -> ()
5949       ) (snd style);
5950
5951       pr "  guestfs___end_busy (g);\n";
5952
5953       (match fst style with
5954        | RErr -> pr "  return 0;\n"
5955        | RInt n | RInt64 n | RBool n ->
5956            pr "  return ret.%s;\n" n
5957        | RConstString _ | RConstOptString _ ->
5958            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5959        | RString n ->
5960            pr "  return ret.%s; /* caller will free */\n" n
5961        | RStringList n | RHashtable n ->
5962            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5963            pr "  ret.%s.%s_val =\n" n n;
5964            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5965            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5966              n n;
5967            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5968            pr "  return ret.%s.%s_val;\n" n n
5969        | RStruct (n, _) ->
5970            pr "  /* caller will free this */\n";
5971            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5972        | RStructList (n, _) ->
5973            pr "  /* caller will free this */\n";
5974            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5975        | RBufferOut n ->
5976            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5977            pr "   * _val might be NULL here.  To make the API saner for\n";
5978            pr "   * callers, we turn this case into a unique pointer (using\n";
5979            pr "   * malloc(1)).\n";
5980            pr "   */\n";
5981            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5982            pr "    *size_r = ret.%s.%s_len;\n" n n;
5983            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5984            pr "  } else {\n";
5985            pr "    free (ret.%s.%s_val);\n" n n;
5986            pr "    char *p = safe_malloc (g, 1);\n";
5987            pr "    *size_r = ret.%s.%s_len;\n" n n;
5988            pr "    return p;\n";
5989            pr "  }\n";
5990       );
5991
5992       pr "}\n\n"
5993   ) daemon_functions;
5994
5995   (* Functions to free structures. *)
5996   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5997   pr " * structure format is identical to the XDR format.  See note in\n";
5998   pr " * generator.ml.\n";
5999   pr " */\n";
6000   pr "\n";
6001
6002   List.iter (
6003     fun (typ, _) ->
6004       pr "void\n";
6005       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6006       pr "{\n";
6007       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6008       pr "  free (x);\n";
6009       pr "}\n";
6010       pr "\n";
6011
6012       pr "void\n";
6013       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6014       pr "{\n";
6015       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6016       pr "  free (x);\n";
6017       pr "}\n";
6018       pr "\n";
6019
6020   ) structs;
6021
6022 (* Generate daemon/actions.h. *)
6023 and generate_daemon_actions_h () =
6024   generate_header CStyle GPLv2plus;
6025
6026   pr "#include \"../src/guestfs_protocol.h\"\n";
6027   pr "\n";
6028
6029   List.iter (
6030     fun (name, style, _, _, _, _, _) ->
6031       generate_prototype
6032         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6033         name style;
6034   ) daemon_functions
6035
6036 (* Generate the linker script which controls the visibility of
6037  * symbols in the public ABI and ensures no other symbols get
6038  * exported accidentally.
6039  *)
6040 and generate_linker_script () =
6041   generate_header HashStyle GPLv2plus;
6042
6043   let globals = [
6044     "guestfs_create";
6045     "guestfs_close";
6046     "guestfs_get_error_handler";
6047     "guestfs_get_out_of_memory_handler";
6048     "guestfs_last_error";
6049     "guestfs_set_error_handler";
6050     "guestfs_set_launch_done_callback";
6051     "guestfs_set_log_message_callback";
6052     "guestfs_set_out_of_memory_handler";
6053     "guestfs_set_subprocess_quit_callback";
6054
6055     (* Unofficial parts of the API: the bindings code use these
6056      * functions, so it is useful to export them.
6057      *)
6058     "guestfs_safe_calloc";
6059     "guestfs_safe_malloc";
6060   ] in
6061   let functions =
6062     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6063       all_functions in
6064   let structs =
6065     List.concat (
6066       List.map (fun (typ, _) ->
6067                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6068         structs
6069     ) in
6070   let globals = List.sort compare (globals @ functions @ structs) in
6071
6072   pr "{\n";
6073   pr "    global:\n";
6074   List.iter (pr "        %s;\n") globals;
6075   pr "\n";
6076
6077   pr "    local:\n";
6078   pr "        *;\n";
6079   pr "};\n"
6080
6081 (* Generate the server-side stubs. *)
6082 and generate_daemon_actions () =
6083   generate_header CStyle GPLv2plus;
6084
6085   pr "#include <config.h>\n";
6086   pr "\n";
6087   pr "#include <stdio.h>\n";
6088   pr "#include <stdlib.h>\n";
6089   pr "#include <string.h>\n";
6090   pr "#include <inttypes.h>\n";
6091   pr "#include <rpc/types.h>\n";
6092   pr "#include <rpc/xdr.h>\n";
6093   pr "\n";
6094   pr "#include \"daemon.h\"\n";
6095   pr "#include \"c-ctype.h\"\n";
6096   pr "#include \"../src/guestfs_protocol.h\"\n";
6097   pr "#include \"actions.h\"\n";
6098   pr "\n";
6099
6100   List.iter (
6101     fun (name, style, _, _, _, _, _) ->
6102       (* Generate server-side stubs. *)
6103       pr "static void %s_stub (XDR *xdr_in)\n" name;
6104       pr "{\n";
6105       let error_code =
6106         match fst style with
6107         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6108         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6109         | RBool _ -> pr "  int r;\n"; "-1"
6110         | RConstString _ | RConstOptString _ ->
6111             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6112         | RString _ -> pr "  char *r;\n"; "NULL"
6113         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6114         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6115         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6116         | RBufferOut _ ->
6117             pr "  size_t size = 1;\n";
6118             pr "  char *r;\n";
6119             "NULL" in
6120
6121       (match snd style with
6122        | [] -> ()
6123        | args ->
6124            pr "  struct guestfs_%s_args args;\n" name;
6125            List.iter (
6126              function
6127              | Device n | Dev_or_Path n
6128              | Pathname n
6129              | String n -> ()
6130              | OptString n -> pr "  char *%s;\n" n
6131              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6132              | Bool n -> pr "  int %s;\n" n
6133              | Int n -> pr "  int %s;\n" n
6134              | Int64 n -> pr "  int64_t %s;\n" n
6135              | FileIn _ | FileOut _ -> ()
6136            ) args
6137       );
6138       pr "\n";
6139
6140       let is_filein =
6141         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6142
6143       (match snd style with
6144        | [] -> ()
6145        | args ->
6146            pr "  memset (&args, 0, sizeof args);\n";
6147            pr "\n";
6148            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6149            if is_filein then
6150              pr "    cancel_receive ();\n";
6151            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6152            pr "    goto done;\n";
6153            pr "  }\n";
6154            let pr_args n =
6155              pr "  char *%s = args.%s;\n" n n
6156            in
6157            let pr_list_handling_code n =
6158              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6159              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6160              pr "  if (%s == NULL) {\n" n;
6161              if is_filein then
6162                pr "    cancel_receive ();\n";
6163              pr "    reply_with_perror (\"realloc\");\n";
6164              pr "    goto done;\n";
6165              pr "  }\n";
6166              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6167              pr "  args.%s.%s_val = %s;\n" n n n;
6168            in
6169            List.iter (
6170              function
6171              | Pathname n ->
6172                  pr_args n;
6173                  pr "  ABS_PATH (%s, %s, goto done);\n"
6174                    n (if is_filein then "cancel_receive ()" else "");
6175              | Device n ->
6176                  pr_args n;
6177                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6178                    n (if is_filein then "cancel_receive ()" else "");
6179              | Dev_or_Path n ->
6180                  pr_args n;
6181                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6182                    n (if is_filein then "cancel_receive ()" else "");
6183              | String n -> pr_args n
6184              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6185              | StringList n ->
6186                  pr_list_handling_code n;
6187              | DeviceList n ->
6188                  pr_list_handling_code n;
6189                  pr "  /* Ensure that each is a device,\n";
6190                  pr "   * and perform device name translation. */\n";
6191                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6192                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6193                    (if is_filein then "cancel_receive ()" else "");
6194                  pr "  }\n";
6195              | Bool n -> pr "  %s = args.%s;\n" n n
6196              | Int n -> pr "  %s = args.%s;\n" n n
6197              | Int64 n -> pr "  %s = args.%s;\n" n n
6198              | FileIn _ | FileOut _ -> ()
6199            ) args;
6200            pr "\n"
6201       );
6202
6203
6204       (* this is used at least for do_equal *)
6205       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6206         (* Emit NEED_ROOT just once, even when there are two or
6207            more Pathname args *)
6208         pr "  NEED_ROOT (%s, goto done);\n"
6209           (if is_filein then "cancel_receive ()" else "");
6210       );
6211
6212       (* Don't want to call the impl with any FileIn or FileOut
6213        * parameters, since these go "outside" the RPC protocol.
6214        *)
6215       let args' =
6216         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6217           (snd style) in
6218       pr "  r = do_%s " name;
6219       generate_c_call_args (fst style, args');
6220       pr ";\n";
6221
6222       (match fst style with
6223        | RErr | RInt _ | RInt64 _ | RBool _
6224        | RConstString _ | RConstOptString _
6225        | RString _ | RStringList _ | RHashtable _
6226        | RStruct (_, _) | RStructList (_, _) ->
6227            pr "  if (r == %s)\n" error_code;
6228            pr "    /* do_%s has already called reply_with_error */\n" name;
6229            pr "    goto done;\n";
6230            pr "\n"
6231        | RBufferOut _ ->
6232            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6233            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6234            pr "   */\n";
6235            pr "  if (size == 1 && r == %s)\n" error_code;
6236            pr "    /* do_%s has already called reply_with_error */\n" name;
6237            pr "    goto done;\n";
6238            pr "\n"
6239       );
6240
6241       (* If there are any FileOut parameters, then the impl must
6242        * send its own reply.
6243        *)
6244       let no_reply =
6245         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6246       if no_reply then
6247         pr "  /* do_%s has already sent a reply */\n" name
6248       else (
6249         match fst style with
6250         | RErr -> pr "  reply (NULL, NULL);\n"
6251         | RInt n | RInt64 n | RBool n ->
6252             pr "  struct guestfs_%s_ret ret;\n" name;
6253             pr "  ret.%s = r;\n" n;
6254             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6255               name
6256         | RConstString _ | RConstOptString _ ->
6257             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6258         | RString n ->
6259             pr "  struct guestfs_%s_ret ret;\n" name;
6260             pr "  ret.%s = r;\n" n;
6261             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6262               name;
6263             pr "  free (r);\n"
6264         | RStringList n | RHashtable n ->
6265             pr "  struct guestfs_%s_ret ret;\n" name;
6266             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6267             pr "  ret.%s.%s_val = r;\n" n n;
6268             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6269               name;
6270             pr "  free_strings (r);\n"
6271         | RStruct (n, _) ->
6272             pr "  struct guestfs_%s_ret ret;\n" name;
6273             pr "  ret.%s = *r;\n" n;
6274             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6275               name;
6276             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6277               name
6278         | RStructList (n, _) ->
6279             pr "  struct guestfs_%s_ret ret;\n" name;
6280             pr "  ret.%s = *r;\n" n;
6281             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6282               name;
6283             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6284               name
6285         | RBufferOut n ->
6286             pr "  struct guestfs_%s_ret ret;\n" name;
6287             pr "  ret.%s.%s_val = r;\n" n n;
6288             pr "  ret.%s.%s_len = size;\n" n n;
6289             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6290               name;
6291             pr "  free (r);\n"
6292       );
6293
6294       (* Free the args. *)
6295       pr "done:\n";
6296       (match snd style with
6297        | [] -> ()
6298        | _ ->
6299            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6300              name
6301       );
6302       pr "  return;\n";
6303       pr "}\n\n";
6304   ) daemon_functions;
6305
6306   (* Dispatch function. *)
6307   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6308   pr "{\n";
6309   pr "  switch (proc_nr) {\n";
6310
6311   List.iter (
6312     fun (name, style, _, _, _, _, _) ->
6313       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6314       pr "      %s_stub (xdr_in);\n" name;
6315       pr "      break;\n"
6316   ) daemon_functions;
6317
6318   pr "    default:\n";
6319   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";
6320   pr "  }\n";
6321   pr "}\n";
6322   pr "\n";
6323
6324   (* LVM columns and tokenization functions. *)
6325   (* XXX This generates crap code.  We should rethink how we
6326    * do this parsing.
6327    *)
6328   List.iter (
6329     function
6330     | typ, cols ->
6331         pr "static const char *lvm_%s_cols = \"%s\";\n"
6332           typ (String.concat "," (List.map fst cols));
6333         pr "\n";
6334
6335         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6336         pr "{\n";
6337         pr "  char *tok, *p, *next;\n";
6338         pr "  int i, j;\n";
6339         pr "\n";
6340         (*
6341           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6342           pr "\n";
6343         *)
6344         pr "  if (!str) {\n";
6345         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6346         pr "    return -1;\n";
6347         pr "  }\n";
6348         pr "  if (!*str || c_isspace (*str)) {\n";
6349         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6350         pr "    return -1;\n";
6351         pr "  }\n";
6352         pr "  tok = str;\n";
6353         List.iter (
6354           fun (name, coltype) ->
6355             pr "  if (!tok) {\n";
6356             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6357             pr "    return -1;\n";
6358             pr "  }\n";
6359             pr "  p = strchrnul (tok, ',');\n";
6360             pr "  if (*p) next = p+1; else next = NULL;\n";
6361             pr "  *p = '\\0';\n";
6362             (match coltype with
6363              | FString ->
6364                  pr "  r->%s = strdup (tok);\n" name;
6365                  pr "  if (r->%s == NULL) {\n" name;
6366                  pr "    perror (\"strdup\");\n";
6367                  pr "    return -1;\n";
6368                  pr "  }\n"
6369              | FUUID ->
6370                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6371                  pr "    if (tok[j] == '\\0') {\n";
6372                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6373                  pr "      return -1;\n";
6374                  pr "    } else if (tok[j] != '-')\n";
6375                  pr "      r->%s[i++] = tok[j];\n" name;
6376                  pr "  }\n";
6377              | FBytes ->
6378                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6379                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6380                  pr "    return -1;\n";
6381                  pr "  }\n";
6382              | FInt64 ->
6383                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6384                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6385                  pr "    return -1;\n";
6386                  pr "  }\n";
6387              | FOptPercent ->
6388                  pr "  if (tok[0] == '\\0')\n";
6389                  pr "    r->%s = -1;\n" name;
6390                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6391                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6392                  pr "    return -1;\n";
6393                  pr "  }\n";
6394              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6395                  assert false (* can never be an LVM column *)
6396             );
6397             pr "  tok = next;\n";
6398         ) cols;
6399
6400         pr "  if (tok != NULL) {\n";
6401         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6402         pr "    return -1;\n";
6403         pr "  }\n";
6404         pr "  return 0;\n";
6405         pr "}\n";
6406         pr "\n";
6407
6408         pr "guestfs_int_lvm_%s_list *\n" typ;
6409         pr "parse_command_line_%ss (void)\n" typ;
6410         pr "{\n";
6411         pr "  char *out, *err;\n";
6412         pr "  char *p, *pend;\n";
6413         pr "  int r, i;\n";
6414         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6415         pr "  void *newp;\n";
6416         pr "\n";
6417         pr "  ret = malloc (sizeof *ret);\n";
6418         pr "  if (!ret) {\n";
6419         pr "    reply_with_perror (\"malloc\");\n";
6420         pr "    return NULL;\n";
6421         pr "  }\n";
6422         pr "\n";
6423         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6424         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6425         pr "\n";
6426         pr "  r = command (&out, &err,\n";
6427         pr "           \"lvm\", \"%ss\",\n" typ;
6428         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6429         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6430         pr "  if (r == -1) {\n";
6431         pr "    reply_with_error (\"%%s\", err);\n";
6432         pr "    free (out);\n";
6433         pr "    free (err);\n";
6434         pr "    free (ret);\n";
6435         pr "    return NULL;\n";
6436         pr "  }\n";
6437         pr "\n";
6438         pr "  free (err);\n";
6439         pr "\n";
6440         pr "  /* Tokenize each line of the output. */\n";
6441         pr "  p = out;\n";
6442         pr "  i = 0;\n";
6443         pr "  while (p) {\n";
6444         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6445         pr "    if (pend) {\n";
6446         pr "      *pend = '\\0';\n";
6447         pr "      pend++;\n";
6448         pr "    }\n";
6449         pr "\n";
6450         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6451         pr "      p++;\n";
6452         pr "\n";
6453         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6454         pr "      p = pend;\n";
6455         pr "      continue;\n";
6456         pr "    }\n";
6457         pr "\n";
6458         pr "    /* Allocate some space to store this next entry. */\n";
6459         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6460         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6461         pr "    if (newp == NULL) {\n";
6462         pr "      reply_with_perror (\"realloc\");\n";
6463         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6464         pr "      free (ret);\n";
6465         pr "      free (out);\n";
6466         pr "      return NULL;\n";
6467         pr "    }\n";
6468         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6469         pr "\n";
6470         pr "    /* Tokenize the next entry. */\n";
6471         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6472         pr "    if (r == -1) {\n";
6473         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6474         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6475         pr "      free (ret);\n";
6476         pr "      free (out);\n";
6477         pr "      return NULL;\n";
6478         pr "    }\n";
6479         pr "\n";
6480         pr "    ++i;\n";
6481         pr "    p = pend;\n";
6482         pr "  }\n";
6483         pr "\n";
6484         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6485         pr "\n";
6486         pr "  free (out);\n";
6487         pr "  return ret;\n";
6488         pr "}\n"
6489
6490   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6491
6492 (* Generate a list of function names, for debugging in the daemon.. *)
6493 and generate_daemon_names () =
6494   generate_header CStyle GPLv2plus;
6495
6496   pr "#include <config.h>\n";
6497   pr "\n";
6498   pr "#include \"daemon.h\"\n";
6499   pr "\n";
6500
6501   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6502   pr "const char *function_names[] = {\n";
6503   List.iter (
6504     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6505   ) daemon_functions;
6506   pr "};\n";
6507
6508 (* Generate the optional groups for the daemon to implement
6509  * guestfs_available.
6510  *)
6511 and generate_daemon_optgroups_c () =
6512   generate_header CStyle GPLv2plus;
6513
6514   pr "#include <config.h>\n";
6515   pr "\n";
6516   pr "#include \"daemon.h\"\n";
6517   pr "#include \"optgroups.h\"\n";
6518   pr "\n";
6519
6520   pr "struct optgroup optgroups[] = {\n";
6521   List.iter (
6522     fun (group, _) ->
6523       pr "  { \"%s\", optgroup_%s_available },\n" group group
6524   ) optgroups;
6525   pr "  { NULL, NULL }\n";
6526   pr "};\n"
6527
6528 and generate_daemon_optgroups_h () =
6529   generate_header CStyle GPLv2plus;
6530
6531   List.iter (
6532     fun (group, _) ->
6533       pr "extern int optgroup_%s_available (void);\n" group
6534   ) optgroups
6535
6536 (* Generate the tests. *)
6537 and generate_tests () =
6538   generate_header CStyle GPLv2plus;
6539
6540   pr "\
6541 #include <stdio.h>
6542 #include <stdlib.h>
6543 #include <string.h>
6544 #include <unistd.h>
6545 #include <sys/types.h>
6546 #include <fcntl.h>
6547
6548 #include \"guestfs.h\"
6549 #include \"guestfs-internal.h\"
6550
6551 static guestfs_h *g;
6552 static int suppress_error = 0;
6553
6554 static void print_error (guestfs_h *g, void *data, const char *msg)
6555 {
6556   if (!suppress_error)
6557     fprintf (stderr, \"%%s\\n\", msg);
6558 }
6559
6560 /* FIXME: nearly identical code appears in fish.c */
6561 static void print_strings (char *const *argv)
6562 {
6563   int argc;
6564
6565   for (argc = 0; argv[argc] != NULL; ++argc)
6566     printf (\"\\t%%s\\n\", argv[argc]);
6567 }
6568
6569 /*
6570 static void print_table (char const *const *argv)
6571 {
6572   int i;
6573
6574   for (i = 0; argv[i] != NULL; i += 2)
6575     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6576 }
6577 */
6578
6579 ";
6580
6581   (* Generate a list of commands which are not tested anywhere. *)
6582   pr "static void no_test_warnings (void)\n";
6583   pr "{\n";
6584
6585   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6586   List.iter (
6587     fun (_, _, _, _, tests, _, _) ->
6588       let tests = filter_map (
6589         function
6590         | (_, (Always|If _|Unless _), test) -> Some test
6591         | (_, Disabled, _) -> None
6592       ) tests in
6593       let seq = List.concat (List.map seq_of_test tests) in
6594       let cmds_tested = List.map List.hd seq in
6595       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6596   ) all_functions;
6597
6598   List.iter (
6599     fun (name, _, _, _, _, _, _) ->
6600       if not (Hashtbl.mem hash name) then
6601         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6602   ) all_functions;
6603
6604   pr "}\n";
6605   pr "\n";
6606
6607   (* Generate the actual tests.  Note that we generate the tests
6608    * in reverse order, deliberately, so that (in general) the
6609    * newest tests run first.  This makes it quicker and easier to
6610    * debug them.
6611    *)
6612   let test_names =
6613     List.map (
6614       fun (name, _, _, flags, tests, _, _) ->
6615         mapi (generate_one_test name flags) tests
6616     ) (List.rev all_functions) in
6617   let test_names = List.concat test_names in
6618   let nr_tests = List.length test_names in
6619
6620   pr "\
6621 int main (int argc, char *argv[])
6622 {
6623   char c = 0;
6624   unsigned long int n_failed = 0;
6625   const char *filename;
6626   int fd;
6627   int nr_tests, test_num = 0;
6628
6629   setbuf (stdout, NULL);
6630
6631   no_test_warnings ();
6632
6633   g = guestfs_create ();
6634   if (g == NULL) {
6635     printf (\"guestfs_create FAILED\\n\");
6636     exit (EXIT_FAILURE);
6637   }
6638
6639   guestfs_set_error_handler (g, print_error, NULL);
6640
6641   guestfs_set_path (g, \"../appliance\");
6642
6643   filename = \"test1.img\";
6644   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6645   if (fd == -1) {
6646     perror (filename);
6647     exit (EXIT_FAILURE);
6648   }
6649   if (lseek (fd, %d, SEEK_SET) == -1) {
6650     perror (\"lseek\");
6651     close (fd);
6652     unlink (filename);
6653     exit (EXIT_FAILURE);
6654   }
6655   if (write (fd, &c, 1) == -1) {
6656     perror (\"write\");
6657     close (fd);
6658     unlink (filename);
6659     exit (EXIT_FAILURE);
6660   }
6661   if (close (fd) == -1) {
6662     perror (filename);
6663     unlink (filename);
6664     exit (EXIT_FAILURE);
6665   }
6666   if (guestfs_add_drive (g, filename) == -1) {
6667     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6668     exit (EXIT_FAILURE);
6669   }
6670
6671   filename = \"test2.img\";
6672   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6673   if (fd == -1) {
6674     perror (filename);
6675     exit (EXIT_FAILURE);
6676   }
6677   if (lseek (fd, %d, SEEK_SET) == -1) {
6678     perror (\"lseek\");
6679     close (fd);
6680     unlink (filename);
6681     exit (EXIT_FAILURE);
6682   }
6683   if (write (fd, &c, 1) == -1) {
6684     perror (\"write\");
6685     close (fd);
6686     unlink (filename);
6687     exit (EXIT_FAILURE);
6688   }
6689   if (close (fd) == -1) {
6690     perror (filename);
6691     unlink (filename);
6692     exit (EXIT_FAILURE);
6693   }
6694   if (guestfs_add_drive (g, filename) == -1) {
6695     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6696     exit (EXIT_FAILURE);
6697   }
6698
6699   filename = \"test3.img\";
6700   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6701   if (fd == -1) {
6702     perror (filename);
6703     exit (EXIT_FAILURE);
6704   }
6705   if (lseek (fd, %d, SEEK_SET) == -1) {
6706     perror (\"lseek\");
6707     close (fd);
6708     unlink (filename);
6709     exit (EXIT_FAILURE);
6710   }
6711   if (write (fd, &c, 1) == -1) {
6712     perror (\"write\");
6713     close (fd);
6714     unlink (filename);
6715     exit (EXIT_FAILURE);
6716   }
6717   if (close (fd) == -1) {
6718     perror (filename);
6719     unlink (filename);
6720     exit (EXIT_FAILURE);
6721   }
6722   if (guestfs_add_drive (g, filename) == -1) {
6723     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6724     exit (EXIT_FAILURE);
6725   }
6726
6727   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6728     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6729     exit (EXIT_FAILURE);
6730   }
6731
6732   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6733   alarm (600);
6734
6735   if (guestfs_launch (g) == -1) {
6736     printf (\"guestfs_launch FAILED\\n\");
6737     exit (EXIT_FAILURE);
6738   }
6739
6740   /* Cancel previous alarm. */
6741   alarm (0);
6742
6743   nr_tests = %d;
6744
6745 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6746
6747   iteri (
6748     fun i test_name ->
6749       pr "  test_num++;\n";
6750       pr "  if (guestfs_get_verbose (g))\n";
6751       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6752       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6753       pr "  if (%s () == -1) {\n" test_name;
6754       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6755       pr "    n_failed++;\n";
6756       pr "  }\n";
6757   ) test_names;
6758   pr "\n";
6759
6760   pr "  guestfs_close (g);\n";
6761   pr "  unlink (\"test1.img\");\n";
6762   pr "  unlink (\"test2.img\");\n";
6763   pr "  unlink (\"test3.img\");\n";
6764   pr "\n";
6765
6766   pr "  if (n_failed > 0) {\n";
6767   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6768   pr "    exit (EXIT_FAILURE);\n";
6769   pr "  }\n";
6770   pr "\n";
6771
6772   pr "  exit (EXIT_SUCCESS);\n";
6773   pr "}\n"
6774
6775 and generate_one_test name flags i (init, prereq, test) =
6776   let test_name = sprintf "test_%s_%d" name i in
6777
6778   pr "\
6779 static int %s_skip (void)
6780 {
6781   const char *str;
6782
6783   str = getenv (\"TEST_ONLY\");
6784   if (str)
6785     return strstr (str, \"%s\") == NULL;
6786   str = getenv (\"SKIP_%s\");
6787   if (str && STREQ (str, \"1\")) return 1;
6788   str = getenv (\"SKIP_TEST_%s\");
6789   if (str && STREQ (str, \"1\")) return 1;
6790   return 0;
6791 }
6792
6793 " test_name name (String.uppercase test_name) (String.uppercase name);
6794
6795   (match prereq with
6796    | Disabled | Always -> ()
6797    | If code | Unless code ->
6798        pr "static int %s_prereq (void)\n" test_name;
6799        pr "{\n";
6800        pr "  %s\n" code;
6801        pr "}\n";
6802        pr "\n";
6803   );
6804
6805   pr "\
6806 static int %s (void)
6807 {
6808   if (%s_skip ()) {
6809     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6810     return 0;
6811   }
6812
6813 " test_name test_name test_name;
6814
6815   (* Optional functions should only be tested if the relevant
6816    * support is available in the daemon.
6817    *)
6818   List.iter (
6819     function
6820     | Optional group ->
6821         pr "  {\n";
6822         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6823         pr "    int r;\n";
6824         pr "    suppress_error = 1;\n";
6825         pr "    r = guestfs_available (g, (char **) groups);\n";
6826         pr "    suppress_error = 0;\n";
6827         pr "    if (r == -1) {\n";
6828         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6829         pr "      return 0;\n";
6830         pr "    }\n";
6831         pr "  }\n";
6832     | _ -> ()
6833   ) flags;
6834
6835   (match prereq with
6836    | Disabled ->
6837        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6838    | If _ ->
6839        pr "  if (! %s_prereq ()) {\n" test_name;
6840        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6841        pr "    return 0;\n";
6842        pr "  }\n";
6843        pr "\n";
6844        generate_one_test_body name i test_name init test;
6845    | Unless _ ->
6846        pr "  if (%s_prereq ()) {\n" test_name;
6847        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6848        pr "    return 0;\n";
6849        pr "  }\n";
6850        pr "\n";
6851        generate_one_test_body name i test_name init test;
6852    | Always ->
6853        generate_one_test_body name i test_name init test
6854   );
6855
6856   pr "  return 0;\n";
6857   pr "}\n";
6858   pr "\n";
6859   test_name
6860
6861 and generate_one_test_body name i test_name init test =
6862   (match init with
6863    | InitNone (* XXX at some point, InitNone and InitEmpty became
6864                * folded together as the same thing.  Really we should
6865                * make InitNone do nothing at all, but the tests may
6866                * need to be checked to make sure this is OK.
6867                *)
6868    | InitEmpty ->
6869        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6870        List.iter (generate_test_command_call test_name)
6871          [["blockdev_setrw"; "/dev/sda"];
6872           ["umount_all"];
6873           ["lvm_remove_all"]]
6874    | InitPartition ->
6875        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6876        List.iter (generate_test_command_call test_name)
6877          [["blockdev_setrw"; "/dev/sda"];
6878           ["umount_all"];
6879           ["lvm_remove_all"];
6880           ["part_disk"; "/dev/sda"; "mbr"]]
6881    | InitBasicFS ->
6882        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6883        List.iter (generate_test_command_call test_name)
6884          [["blockdev_setrw"; "/dev/sda"];
6885           ["umount_all"];
6886           ["lvm_remove_all"];
6887           ["part_disk"; "/dev/sda"; "mbr"];
6888           ["mkfs"; "ext2"; "/dev/sda1"];
6889           ["mount_options"; ""; "/dev/sda1"; "/"]]
6890    | InitBasicFSonLVM ->
6891        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6892          test_name;
6893        List.iter (generate_test_command_call test_name)
6894          [["blockdev_setrw"; "/dev/sda"];
6895           ["umount_all"];
6896           ["lvm_remove_all"];
6897           ["part_disk"; "/dev/sda"; "mbr"];
6898           ["pvcreate"; "/dev/sda1"];
6899           ["vgcreate"; "VG"; "/dev/sda1"];
6900           ["lvcreate"; "LV"; "VG"; "8"];
6901           ["mkfs"; "ext2"; "/dev/VG/LV"];
6902           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6903    | InitISOFS ->
6904        pr "  /* InitISOFS for %s */\n" test_name;
6905        List.iter (generate_test_command_call test_name)
6906          [["blockdev_setrw"; "/dev/sda"];
6907           ["umount_all"];
6908           ["lvm_remove_all"];
6909           ["mount_ro"; "/dev/sdd"; "/"]]
6910   );
6911
6912   let get_seq_last = function
6913     | [] ->
6914         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6915           test_name
6916     | seq ->
6917         let seq = List.rev seq in
6918         List.rev (List.tl seq), List.hd seq
6919   in
6920
6921   match test with
6922   | TestRun seq ->
6923       pr "  /* TestRun for %s (%d) */\n" name i;
6924       List.iter (generate_test_command_call test_name) seq
6925   | TestOutput (seq, expected) ->
6926       pr "  /* TestOutput for %s (%d) */\n" name i;
6927       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6928       let seq, last = get_seq_last seq in
6929       let test () =
6930         pr "    if (STRNEQ (r, expected)) {\n";
6931         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6932         pr "      return -1;\n";
6933         pr "    }\n"
6934       in
6935       List.iter (generate_test_command_call test_name) seq;
6936       generate_test_command_call ~test test_name last
6937   | TestOutputList (seq, expected) ->
6938       pr "  /* TestOutputList for %s (%d) */\n" name i;
6939       let seq, last = get_seq_last seq in
6940       let test () =
6941         iteri (
6942           fun i str ->
6943             pr "    if (!r[%d]) {\n" i;
6944             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6945             pr "      print_strings (r);\n";
6946             pr "      return -1;\n";
6947             pr "    }\n";
6948             pr "    {\n";
6949             pr "      const char *expected = \"%s\";\n" (c_quote str);
6950             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6951             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6952             pr "        return -1;\n";
6953             pr "      }\n";
6954             pr "    }\n"
6955         ) expected;
6956         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6957         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6958           test_name;
6959         pr "      print_strings (r);\n";
6960         pr "      return -1;\n";
6961         pr "    }\n"
6962       in
6963       List.iter (generate_test_command_call test_name) seq;
6964       generate_test_command_call ~test test_name last
6965   | TestOutputListOfDevices (seq, expected) ->
6966       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6967       let seq, last = get_seq_last seq in
6968       let test () =
6969         iteri (
6970           fun i str ->
6971             pr "    if (!r[%d]) {\n" i;
6972             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6973             pr "      print_strings (r);\n";
6974             pr "      return -1;\n";
6975             pr "    }\n";
6976             pr "    {\n";
6977             pr "      const char *expected = \"%s\";\n" (c_quote str);
6978             pr "      r[%d][5] = 's';\n" i;
6979             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6980             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6981             pr "        return -1;\n";
6982             pr "      }\n";
6983             pr "    }\n"
6984         ) expected;
6985         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6986         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6987           test_name;
6988         pr "      print_strings (r);\n";
6989         pr "      return -1;\n";
6990         pr "    }\n"
6991       in
6992       List.iter (generate_test_command_call test_name) seq;
6993       generate_test_command_call ~test test_name last
6994   | TestOutputInt (seq, expected) ->
6995       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6996       let seq, last = get_seq_last seq in
6997       let test () =
6998         pr "    if (r != %d) {\n" expected;
6999         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7000           test_name expected;
7001         pr "               (int) r);\n";
7002         pr "      return -1;\n";
7003         pr "    }\n"
7004       in
7005       List.iter (generate_test_command_call test_name) seq;
7006       generate_test_command_call ~test test_name last
7007   | TestOutputIntOp (seq, op, expected) ->
7008       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7009       let seq, last = get_seq_last seq in
7010       let test () =
7011         pr "    if (! (r %s %d)) {\n" op expected;
7012         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7013           test_name op expected;
7014         pr "               (int) r);\n";
7015         pr "      return -1;\n";
7016         pr "    }\n"
7017       in
7018       List.iter (generate_test_command_call test_name) seq;
7019       generate_test_command_call ~test test_name last
7020   | TestOutputTrue seq ->
7021       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7022       let seq, last = get_seq_last seq in
7023       let test () =
7024         pr "    if (!r) {\n";
7025         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7026           test_name;
7027         pr "      return -1;\n";
7028         pr "    }\n"
7029       in
7030       List.iter (generate_test_command_call test_name) seq;
7031       generate_test_command_call ~test test_name last
7032   | TestOutputFalse seq ->
7033       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7034       let seq, last = get_seq_last seq in
7035       let test () =
7036         pr "    if (r) {\n";
7037         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7038           test_name;
7039         pr "      return -1;\n";
7040         pr "    }\n"
7041       in
7042       List.iter (generate_test_command_call test_name) seq;
7043       generate_test_command_call ~test test_name last
7044   | TestOutputLength (seq, expected) ->
7045       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7046       let seq, last = get_seq_last seq in
7047       let test () =
7048         pr "    int j;\n";
7049         pr "    for (j = 0; j < %d; ++j)\n" expected;
7050         pr "      if (r[j] == NULL) {\n";
7051         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7052           test_name;
7053         pr "        print_strings (r);\n";
7054         pr "        return -1;\n";
7055         pr "      }\n";
7056         pr "    if (r[j] != NULL) {\n";
7057         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7058           test_name;
7059         pr "      print_strings (r);\n";
7060         pr "      return -1;\n";
7061         pr "    }\n"
7062       in
7063       List.iter (generate_test_command_call test_name) seq;
7064       generate_test_command_call ~test test_name last
7065   | TestOutputBuffer (seq, expected) ->
7066       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7067       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7068       let seq, last = get_seq_last seq in
7069       let len = String.length expected in
7070       let test () =
7071         pr "    if (size != %d) {\n" len;
7072         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7073         pr "      return -1;\n";
7074         pr "    }\n";
7075         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7076         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7077         pr "      return -1;\n";
7078         pr "    }\n"
7079       in
7080       List.iter (generate_test_command_call test_name) seq;
7081       generate_test_command_call ~test test_name last
7082   | TestOutputStruct (seq, checks) ->
7083       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7084       let seq, last = get_seq_last seq in
7085       let test () =
7086         List.iter (
7087           function
7088           | CompareWithInt (field, expected) ->
7089               pr "    if (r->%s != %d) {\n" field expected;
7090               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7091                 test_name field expected;
7092               pr "               (int) r->%s);\n" field;
7093               pr "      return -1;\n";
7094               pr "    }\n"
7095           | CompareWithIntOp (field, op, expected) ->
7096               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7097               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7098                 test_name field op expected;
7099               pr "               (int) r->%s);\n" field;
7100               pr "      return -1;\n";
7101               pr "    }\n"
7102           | CompareWithString (field, expected) ->
7103               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7104               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7105                 test_name field expected;
7106               pr "               r->%s);\n" field;
7107               pr "      return -1;\n";
7108               pr "    }\n"
7109           | CompareFieldsIntEq (field1, field2) ->
7110               pr "    if (r->%s != r->%s) {\n" field1 field2;
7111               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7112                 test_name field1 field2;
7113               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7114               pr "      return -1;\n";
7115               pr "    }\n"
7116           | CompareFieldsStrEq (field1, field2) ->
7117               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7118               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7119                 test_name field1 field2;
7120               pr "               r->%s, r->%s);\n" field1 field2;
7121               pr "      return -1;\n";
7122               pr "    }\n"
7123         ) checks
7124       in
7125       List.iter (generate_test_command_call test_name) seq;
7126       generate_test_command_call ~test test_name last
7127   | TestLastFail seq ->
7128       pr "  /* TestLastFail for %s (%d) */\n" name i;
7129       let seq, last = get_seq_last seq in
7130       List.iter (generate_test_command_call test_name) seq;
7131       generate_test_command_call test_name ~expect_error:true last
7132
7133 (* Generate the code to run a command, leaving the result in 'r'.
7134  * If you expect to get an error then you should set expect_error:true.
7135  *)
7136 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7137   match cmd with
7138   | [] -> assert false
7139   | name :: args ->
7140       (* Look up the command to find out what args/ret it has. *)
7141       let style =
7142         try
7143           let _, style, _, _, _, _, _ =
7144             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7145           style
7146         with Not_found ->
7147           failwithf "%s: in test, command %s was not found" test_name name in
7148
7149       if List.length (snd style) <> List.length args then
7150         failwithf "%s: in test, wrong number of args given to %s"
7151           test_name name;
7152
7153       pr "  {\n";
7154
7155       List.iter (
7156         function
7157         | OptString n, "NULL" -> ()
7158         | Pathname n, arg
7159         | Device n, arg
7160         | Dev_or_Path n, arg
7161         | String n, arg
7162         | OptString n, arg ->
7163             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7164         | Int _, _
7165         | Int64 _, _
7166         | Bool _, _
7167         | FileIn _, _ | FileOut _, _ -> ()
7168         | StringList n, "" | DeviceList n, "" ->
7169             pr "    const char *const %s[1] = { NULL };\n" n
7170         | StringList n, arg | DeviceList n, arg ->
7171             let strs = string_split " " arg in
7172             iteri (
7173               fun i str ->
7174                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7175             ) strs;
7176             pr "    const char *const %s[] = {\n" n;
7177             iteri (
7178               fun i _ -> pr "      %s_%d,\n" n i
7179             ) strs;
7180             pr "      NULL\n";
7181             pr "    };\n";
7182       ) (List.combine (snd style) args);
7183
7184       let error_code =
7185         match fst style with
7186         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7187         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7188         | RConstString _ | RConstOptString _ ->
7189             pr "    const char *r;\n"; "NULL"
7190         | RString _ -> pr "    char *r;\n"; "NULL"
7191         | RStringList _ | RHashtable _ ->
7192             pr "    char **r;\n";
7193             pr "    int i;\n";
7194             "NULL"
7195         | RStruct (_, typ) ->
7196             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7197         | RStructList (_, typ) ->
7198             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7199         | RBufferOut _ ->
7200             pr "    char *r;\n";
7201             pr "    size_t size;\n";
7202             "NULL" in
7203
7204       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7205       pr "    r = guestfs_%s (g" name;
7206
7207       (* Generate the parameters. *)
7208       List.iter (
7209         function
7210         | OptString _, "NULL" -> pr ", NULL"
7211         | Pathname n, _
7212         | Device n, _ | Dev_or_Path n, _
7213         | String n, _
7214         | OptString n, _ ->
7215             pr ", %s" n
7216         | FileIn _, arg | FileOut _, arg ->
7217             pr ", \"%s\"" (c_quote arg)
7218         | StringList n, _ | DeviceList n, _ ->
7219             pr ", (char **) %s" n
7220         | Int _, arg ->
7221             let i =
7222               try int_of_string arg
7223               with Failure "int_of_string" ->
7224                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7225             pr ", %d" i
7226         | Int64 _, arg ->
7227             let i =
7228               try Int64.of_string arg
7229               with Failure "int_of_string" ->
7230                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7231             pr ", %Ld" i
7232         | Bool _, arg ->
7233             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7234       ) (List.combine (snd style) args);
7235
7236       (match fst style with
7237        | RBufferOut _ -> pr ", &size"
7238        | _ -> ()
7239       );
7240
7241       pr ");\n";
7242
7243       if not expect_error then
7244         pr "    if (r == %s)\n" error_code
7245       else
7246         pr "    if (r != %s)\n" error_code;
7247       pr "      return -1;\n";
7248
7249       (* Insert the test code. *)
7250       (match test with
7251        | None -> ()
7252        | Some f -> f ()
7253       );
7254
7255       (match fst style with
7256        | RErr | RInt _ | RInt64 _ | RBool _
7257        | RConstString _ | RConstOptString _ -> ()
7258        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7259        | RStringList _ | RHashtable _ ->
7260            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7261            pr "      free (r[i]);\n";
7262            pr "    free (r);\n"
7263        | RStruct (_, typ) ->
7264            pr "    guestfs_free_%s (r);\n" typ
7265        | RStructList (_, typ) ->
7266            pr "    guestfs_free_%s_list (r);\n" typ
7267       );
7268
7269       pr "  }\n"
7270
7271 and c_quote str =
7272   let str = replace_str str "\r" "\\r" in
7273   let str = replace_str str "\n" "\\n" in
7274   let str = replace_str str "\t" "\\t" in
7275   let str = replace_str str "\000" "\\0" in
7276   str
7277
7278 (* Generate a lot of different functions for guestfish. *)
7279 and generate_fish_cmds () =
7280   generate_header CStyle GPLv2plus;
7281
7282   let all_functions =
7283     List.filter (
7284       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7285     ) all_functions in
7286   let all_functions_sorted =
7287     List.filter (
7288       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7289     ) all_functions_sorted in
7290
7291   pr "#include <config.h>\n";
7292   pr "\n";
7293   pr "#include <stdio.h>\n";
7294   pr "#include <stdlib.h>\n";
7295   pr "#include <string.h>\n";
7296   pr "#include <inttypes.h>\n";
7297   pr "\n";
7298   pr "#include <guestfs.h>\n";
7299   pr "#include \"c-ctype.h\"\n";
7300   pr "#include \"full-write.h\"\n";
7301   pr "#include \"xstrtol.h\"\n";
7302   pr "#include \"fish.h\"\n";
7303   pr "\n";
7304
7305   (* list_commands function, which implements guestfish -h *)
7306   pr "void list_commands (void)\n";
7307   pr "{\n";
7308   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7309   pr "  list_builtin_commands ();\n";
7310   List.iter (
7311     fun (name, _, _, flags, _, shortdesc, _) ->
7312       let name = replace_char name '_' '-' in
7313       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7314         name shortdesc
7315   ) all_functions_sorted;
7316   pr "  printf (\"    %%s\\n\",";
7317   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7318   pr "}\n";
7319   pr "\n";
7320
7321   (* display_command function, which implements guestfish -h cmd *)
7322   pr "void display_command (const char *cmd)\n";
7323   pr "{\n";
7324   List.iter (
7325     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7326       let name2 = replace_char name '_' '-' in
7327       let alias =
7328         try find_map (function FishAlias n -> Some n | _ -> None) flags
7329         with Not_found -> name in
7330       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7331       let synopsis =
7332         match snd style with
7333         | [] -> name2
7334         | args ->
7335             sprintf "%s %s"
7336               name2 (String.concat " " (List.map name_of_argt args)) in
7337
7338       let warnings =
7339         if List.mem ProtocolLimitWarning flags then
7340           ("\n\n" ^ protocol_limit_warning)
7341         else "" in
7342
7343       (* For DangerWillRobinson commands, we should probably have
7344        * guestfish prompt before allowing you to use them (especially
7345        * in interactive mode). XXX
7346        *)
7347       let warnings =
7348         warnings ^
7349           if List.mem DangerWillRobinson flags then
7350             ("\n\n" ^ danger_will_robinson)
7351           else "" in
7352
7353       let warnings =
7354         warnings ^
7355           match deprecation_notice flags with
7356           | None -> ""
7357           | Some txt -> "\n\n" ^ txt in
7358
7359       let describe_alias =
7360         if name <> alias then
7361           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7362         else "" in
7363
7364       pr "  if (";
7365       pr "STRCASEEQ (cmd, \"%s\")" name;
7366       if name <> name2 then
7367         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7368       if name <> alias then
7369         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7370       pr ")\n";
7371       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7372         name2 shortdesc
7373         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7374          "=head1 DESCRIPTION\n\n" ^
7375          longdesc ^ warnings ^ describe_alias);
7376       pr "  else\n"
7377   ) all_functions;
7378   pr "    display_builtin_command (cmd);\n";
7379   pr "}\n";
7380   pr "\n";
7381
7382   let emit_print_list_function typ =
7383     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7384       typ typ typ;
7385     pr "{\n";
7386     pr "  unsigned int i;\n";
7387     pr "\n";
7388     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7389     pr "    printf (\"[%%d] = {\\n\", i);\n";
7390     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7391     pr "    printf (\"}\\n\");\n";
7392     pr "  }\n";
7393     pr "}\n";
7394     pr "\n";
7395   in
7396
7397   (* print_* functions *)
7398   List.iter (
7399     fun (typ, cols) ->
7400       let needs_i =
7401         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7402
7403       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7404       pr "{\n";
7405       if needs_i then (
7406         pr "  unsigned int i;\n";
7407         pr "\n"
7408       );
7409       List.iter (
7410         function
7411         | name, FString ->
7412             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7413         | name, FUUID ->
7414             pr "  printf (\"%%s%s: \", indent);\n" name;
7415             pr "  for (i = 0; i < 32; ++i)\n";
7416             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7417             pr "  printf (\"\\n\");\n"
7418         | name, FBuffer ->
7419             pr "  printf (\"%%s%s: \", indent);\n" name;
7420             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7421             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7422             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7423             pr "    else\n";
7424             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7425             pr "  printf (\"\\n\");\n"
7426         | name, (FUInt64|FBytes) ->
7427             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7428               name typ name
7429         | name, FInt64 ->
7430             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7431               name typ name
7432         | name, FUInt32 ->
7433             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7434               name typ name
7435         | name, FInt32 ->
7436             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7437               name typ name
7438         | name, FChar ->
7439             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7440               name typ name
7441         | name, FOptPercent ->
7442             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7443               typ name name typ name;
7444             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7445       ) cols;
7446       pr "}\n";
7447       pr "\n";
7448   ) structs;
7449
7450   (* Emit a print_TYPE_list function definition only if that function is used. *)
7451   List.iter (
7452     function
7453     | typ, (RStructListOnly | RStructAndList) ->
7454         (* generate the function for typ *)
7455         emit_print_list_function typ
7456     | typ, _ -> () (* empty *)
7457   ) (rstructs_used_by all_functions);
7458
7459   (* Emit a print_TYPE function definition only if that function is used. *)
7460   List.iter (
7461     function
7462     | typ, (RStructOnly | RStructAndList) ->
7463         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7464         pr "{\n";
7465         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7466         pr "}\n";
7467         pr "\n";
7468     | typ, _ -> () (* empty *)
7469   ) (rstructs_used_by all_functions);
7470
7471   (* run_<action> actions *)
7472   List.iter (
7473     fun (name, style, _, flags, _, _, _) ->
7474       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7475       pr "{\n";
7476       (match fst style with
7477        | RErr
7478        | RInt _
7479        | RBool _ -> pr "  int r;\n"
7480        | RInt64 _ -> pr "  int64_t r;\n"
7481        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7482        | RString _ -> pr "  char *r;\n"
7483        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7484        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7485        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7486        | RBufferOut _ ->
7487            pr "  char *r;\n";
7488            pr "  size_t size;\n";
7489       );
7490       List.iter (
7491         function
7492         | Device n
7493         | String n
7494         | OptString n -> pr "  const char *%s;\n" n
7495         | Pathname n
7496         | Dev_or_Path n
7497         | FileIn n
7498         | FileOut n -> pr "  char *%s;\n" n
7499         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7500         | Bool n -> pr "  int %s;\n" n
7501         | Int n -> pr "  int %s;\n" n
7502         | Int64 n -> pr "  int64_t %s;\n" n
7503       ) (snd style);
7504
7505       (* Check and convert parameters. *)
7506       let argc_expected = List.length (snd style) in
7507       pr "  if (argc != %d) {\n" argc_expected;
7508       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7509         argc_expected;
7510       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7511       pr "    return -1;\n";
7512       pr "  }\n";
7513
7514       let parse_integer fn fntyp rtyp range name i =
7515         pr "  {\n";
7516         pr "    strtol_error xerr;\n";
7517         pr "    %s r;\n" fntyp;
7518         pr "\n";
7519         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7520         pr "    if (xerr != LONGINT_OK) {\n";
7521         pr "      fprintf (stderr,\n";
7522         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7523         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7524         pr "      return -1;\n";
7525         pr "    }\n";
7526         (match range with
7527          | None -> ()
7528          | Some (min, max, comment) ->
7529              pr "    /* %s */\n" comment;
7530              pr "    if (r < %s || r > %s) {\n" min max;
7531              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7532                name;
7533              pr "      return -1;\n";
7534              pr "    }\n";
7535              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7536         );
7537         pr "    %s = r;\n" name;
7538         pr "  }\n";
7539       in
7540
7541       iteri (
7542         fun i ->
7543           function
7544           | Device name
7545           | String name ->
7546               pr "  %s = argv[%d];\n" name i
7547           | Pathname name
7548           | Dev_or_Path name ->
7549               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7550               pr "  if (%s == NULL) return -1;\n" name
7551           | OptString name ->
7552               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7553                 name i i
7554           | FileIn name ->
7555               pr "  %s = file_in (argv[%d]);\n" name i;
7556               pr "  if (%s == NULL) return -1;\n" name
7557           | FileOut name ->
7558               pr "  %s = file_out (argv[%d]);\n" name i;
7559               pr "  if (%s == NULL) return -1;\n" name
7560           | StringList name | DeviceList name ->
7561               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7562               pr "  if (%s == NULL) return -1;\n" name;
7563           | Bool name ->
7564               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7565           | Int name ->
7566               let range =
7567                 let min = "(-(2LL<<30))"
7568                 and max = "((2LL<<30)-1)"
7569                 and comment =
7570                   "The Int type in the generator is a signed 31 bit int." in
7571                 Some (min, max, comment) in
7572               parse_integer "xstrtoll" "long long" "int" range name i
7573           | Int64 name ->
7574               parse_integer "xstrtoll" "long long" "int64_t" None name i
7575       ) (snd style);
7576
7577       (* Call C API function. *)
7578       let fn =
7579         try find_map (function FishAction n -> Some n | _ -> None) flags
7580         with Not_found -> sprintf "guestfs_%s" name in
7581       pr "  r = %s " fn;
7582       generate_c_call_args ~handle:"g" style;
7583       pr ";\n";
7584
7585       List.iter (
7586         function
7587         | Device name | String name
7588         | OptString name | Bool name
7589         | Int name | Int64 name -> ()
7590         | Pathname name | Dev_or_Path name | FileOut name ->
7591             pr "  free (%s);\n" name
7592         | FileIn name ->
7593             pr "  free_file_in (%s);\n" name
7594         | StringList name | DeviceList name ->
7595             pr "  free_strings (%s);\n" name
7596       ) (snd style);
7597
7598       (* Any output flags? *)
7599       let fish_output =
7600         let flags = filter_map (
7601           function FishOutput flag -> Some flag | _ -> None
7602         ) flags in
7603         match flags with
7604         | [] -> None
7605         | [f] -> Some f
7606         | _ ->
7607             failwithf "%s: more than one FishOutput flag is not allowed" name in
7608
7609       (* Check return value for errors and display command results. *)
7610       (match fst style with
7611        | RErr -> pr "  return r;\n"
7612        | RInt _ ->
7613            pr "  if (r == -1) return -1;\n";
7614            (match fish_output with
7615             | None ->
7616                 pr "  printf (\"%%d\\n\", r);\n";
7617             | Some FishOutputOctal ->
7618                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7619             | Some FishOutputHexadecimal ->
7620                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7621            pr "  return 0;\n"
7622        | RInt64 _ ->
7623            pr "  if (r == -1) return -1;\n";
7624            (match fish_output with
7625             | None ->
7626                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7627             | Some FishOutputOctal ->
7628                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7629             | Some FishOutputHexadecimal ->
7630                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7631            pr "  return 0;\n"
7632        | RBool _ ->
7633            pr "  if (r == -1) return -1;\n";
7634            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7635            pr "  return 0;\n"
7636        | RConstString _ ->
7637            pr "  if (r == NULL) return -1;\n";
7638            pr "  printf (\"%%s\\n\", r);\n";
7639            pr "  return 0;\n"
7640        | RConstOptString _ ->
7641            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7642            pr "  return 0;\n"
7643        | RString _ ->
7644            pr "  if (r == NULL) return -1;\n";
7645            pr "  printf (\"%%s\\n\", r);\n";
7646            pr "  free (r);\n";
7647            pr "  return 0;\n"
7648        | RStringList _ ->
7649            pr "  if (r == NULL) return -1;\n";
7650            pr "  print_strings (r);\n";
7651            pr "  free_strings (r);\n";
7652            pr "  return 0;\n"
7653        | RStruct (_, typ) ->
7654            pr "  if (r == NULL) return -1;\n";
7655            pr "  print_%s (r);\n" typ;
7656            pr "  guestfs_free_%s (r);\n" typ;
7657            pr "  return 0;\n"
7658        | RStructList (_, typ) ->
7659            pr "  if (r == NULL) return -1;\n";
7660            pr "  print_%s_list (r);\n" typ;
7661            pr "  guestfs_free_%s_list (r);\n" typ;
7662            pr "  return 0;\n"
7663        | RHashtable _ ->
7664            pr "  if (r == NULL) return -1;\n";
7665            pr "  print_table (r);\n";
7666            pr "  free_strings (r);\n";
7667            pr "  return 0;\n"
7668        | RBufferOut _ ->
7669            pr "  if (r == NULL) return -1;\n";
7670            pr "  if (full_write (1, r, size) != size) {\n";
7671            pr "    perror (\"write\");\n";
7672            pr "    free (r);\n";
7673            pr "    return -1;\n";
7674            pr "  }\n";
7675            pr "  free (r);\n";
7676            pr "  return 0;\n"
7677       );
7678       pr "}\n";
7679       pr "\n"
7680   ) all_functions;
7681
7682   (* run_action function *)
7683   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7684   pr "{\n";
7685   List.iter (
7686     fun (name, _, _, flags, _, _, _) ->
7687       let name2 = replace_char name '_' '-' in
7688       let alias =
7689         try find_map (function FishAlias n -> Some n | _ -> None) flags
7690         with Not_found -> name in
7691       pr "  if (";
7692       pr "STRCASEEQ (cmd, \"%s\")" name;
7693       if name <> name2 then
7694         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7695       if name <> alias then
7696         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7697       pr ")\n";
7698       pr "    return run_%s (cmd, argc, argv);\n" name;
7699       pr "  else\n";
7700   ) all_functions;
7701   pr "    {\n";
7702   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7703   pr "      if (command_num == 1)\n";
7704   pr "        extended_help_message ();\n";
7705   pr "      return -1;\n";
7706   pr "    }\n";
7707   pr "  return 0;\n";
7708   pr "}\n";
7709   pr "\n"
7710
7711 (* Readline completion for guestfish. *)
7712 and generate_fish_completion () =
7713   generate_header CStyle GPLv2plus;
7714
7715   let all_functions =
7716     List.filter (
7717       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7718     ) all_functions in
7719
7720   pr "\
7721 #include <config.h>
7722
7723 #include <stdio.h>
7724 #include <stdlib.h>
7725 #include <string.h>
7726
7727 #ifdef HAVE_LIBREADLINE
7728 #include <readline/readline.h>
7729 #endif
7730
7731 #include \"fish.h\"
7732
7733 #ifdef HAVE_LIBREADLINE
7734
7735 static const char *const commands[] = {
7736   BUILTIN_COMMANDS_FOR_COMPLETION,
7737 ";
7738
7739   (* Get the commands, including the aliases.  They don't need to be
7740    * sorted - the generator() function just does a dumb linear search.
7741    *)
7742   let commands =
7743     List.map (
7744       fun (name, _, _, flags, _, _, _) ->
7745         let name2 = replace_char name '_' '-' in
7746         let alias =
7747           try find_map (function FishAlias n -> Some n | _ -> None) flags
7748           with Not_found -> name in
7749
7750         if name <> alias then [name2; alias] else [name2]
7751     ) all_functions in
7752   let commands = List.flatten commands in
7753
7754   List.iter (pr "  \"%s\",\n") commands;
7755
7756   pr "  NULL
7757 };
7758
7759 static char *
7760 generator (const char *text, int state)
7761 {
7762   static int index, len;
7763   const char *name;
7764
7765   if (!state) {
7766     index = 0;
7767     len = strlen (text);
7768   }
7769
7770   rl_attempted_completion_over = 1;
7771
7772   while ((name = commands[index]) != NULL) {
7773     index++;
7774     if (STRCASEEQLEN (name, text, len))
7775       return strdup (name);
7776   }
7777
7778   return NULL;
7779 }
7780
7781 #endif /* HAVE_LIBREADLINE */
7782
7783 #ifdef HAVE_RL_COMPLETION_MATCHES
7784 #define RL_COMPLETION_MATCHES rl_completion_matches
7785 #else
7786 #ifdef HAVE_COMPLETION_MATCHES
7787 #define RL_COMPLETION_MATCHES completion_matches
7788 #endif
7789 #endif /* else just fail if we don't have either symbol */
7790
7791 char **
7792 do_completion (const char *text, int start, int end)
7793 {
7794   char **matches = NULL;
7795
7796 #ifdef HAVE_LIBREADLINE
7797   rl_completion_append_character = ' ';
7798
7799   if (start == 0)
7800     matches = RL_COMPLETION_MATCHES (text, generator);
7801   else if (complete_dest_paths)
7802     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7803 #endif
7804
7805   return matches;
7806 }
7807 ";
7808
7809 (* Generate the POD documentation for guestfish. *)
7810 and generate_fish_actions_pod () =
7811   let all_functions_sorted =
7812     List.filter (
7813       fun (_, _, _, flags, _, _, _) ->
7814         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7815     ) all_functions_sorted in
7816
7817   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7818
7819   List.iter (
7820     fun (name, style, _, flags, _, _, longdesc) ->
7821       let longdesc =
7822         Str.global_substitute rex (
7823           fun s ->
7824             let sub =
7825               try Str.matched_group 1 s
7826               with Not_found ->
7827                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7828             "C<" ^ replace_char sub '_' '-' ^ ">"
7829         ) longdesc in
7830       let name = replace_char name '_' '-' in
7831       let alias =
7832         try find_map (function FishAlias n -> Some n | _ -> None) flags
7833         with Not_found -> name in
7834
7835       pr "=head2 %s" name;
7836       if name <> alias then
7837         pr " | %s" alias;
7838       pr "\n";
7839       pr "\n";
7840       pr " %s" name;
7841       List.iter (
7842         function
7843         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7844         | OptString n -> pr " %s" n
7845         | StringList n | DeviceList n -> pr " '%s ...'" n
7846         | Bool _ -> pr " true|false"
7847         | Int n -> pr " %s" n
7848         | Int64 n -> pr " %s" n
7849         | FileIn n | FileOut n -> pr " (%s|-)" n
7850       ) (snd style);
7851       pr "\n";
7852       pr "\n";
7853       pr "%s\n\n" longdesc;
7854
7855       if List.exists (function FileIn _ | FileOut _ -> true
7856                       | _ -> false) (snd style) then
7857         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7858
7859       if List.mem ProtocolLimitWarning flags then
7860         pr "%s\n\n" protocol_limit_warning;
7861
7862       if List.mem DangerWillRobinson flags then
7863         pr "%s\n\n" danger_will_robinson;
7864
7865       match deprecation_notice flags with
7866       | None -> ()
7867       | Some txt -> pr "%s\n\n" txt
7868   ) all_functions_sorted
7869
7870 (* Generate a C function prototype. *)
7871 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7872     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7873     ?(prefix = "")
7874     ?handle name style =
7875   if extern then pr "extern ";
7876   if static then pr "static ";
7877   (match fst style with
7878    | RErr -> pr "int "
7879    | RInt _ -> pr "int "
7880    | RInt64 _ -> pr "int64_t "
7881    | RBool _ -> pr "int "
7882    | RConstString _ | RConstOptString _ -> pr "const char *"
7883    | RString _ | RBufferOut _ -> pr "char *"
7884    | RStringList _ | RHashtable _ -> pr "char **"
7885    | RStruct (_, typ) ->
7886        if not in_daemon then pr "struct guestfs_%s *" typ
7887        else pr "guestfs_int_%s *" typ
7888    | RStructList (_, typ) ->
7889        if not in_daemon then pr "struct guestfs_%s_list *" typ
7890        else pr "guestfs_int_%s_list *" typ
7891   );
7892   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7893   pr "%s%s (" prefix name;
7894   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7895     pr "void"
7896   else (
7897     let comma = ref false in
7898     (match handle with
7899      | None -> ()
7900      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7901     );
7902     let next () =
7903       if !comma then (
7904         if single_line then pr ", " else pr ",\n\t\t"
7905       );
7906       comma := true
7907     in
7908     List.iter (
7909       function
7910       | Pathname n
7911       | Device n | Dev_or_Path n
7912       | String n
7913       | OptString n ->
7914           next ();
7915           pr "const char *%s" n
7916       | StringList n | DeviceList n ->
7917           next ();
7918           pr "char *const *%s" n
7919       | Bool n -> next (); pr "int %s" n
7920       | Int n -> next (); pr "int %s" n
7921       | Int64 n -> next (); pr "int64_t %s" n
7922       | FileIn n
7923       | FileOut n ->
7924           if not in_daemon then (next (); pr "const char *%s" n)
7925     ) (snd style);
7926     if is_RBufferOut then (next (); pr "size_t *size_r");
7927   );
7928   pr ")";
7929   if semicolon then pr ";";
7930   if newline then pr "\n"
7931
7932 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7933 and generate_c_call_args ?handle ?(decl = false) style =
7934   pr "(";
7935   let comma = ref false in
7936   let next () =
7937     if !comma then pr ", ";
7938     comma := true
7939   in
7940   (match handle with
7941    | None -> ()
7942    | Some handle -> pr "%s" handle; comma := true
7943   );
7944   List.iter (
7945     fun arg ->
7946       next ();
7947       pr "%s" (name_of_argt arg)
7948   ) (snd style);
7949   (* For RBufferOut calls, add implicit &size parameter. *)
7950   if not decl then (
7951     match fst style with
7952     | RBufferOut _ ->
7953         next ();
7954         pr "&size"
7955     | _ -> ()
7956   );
7957   pr ")"
7958
7959 (* Generate the OCaml bindings interface. *)
7960 and generate_ocaml_mli () =
7961   generate_header OCamlStyle LGPLv2plus;
7962
7963   pr "\
7964 (** For API documentation you should refer to the C API
7965     in the guestfs(3) manual page.  The OCaml API uses almost
7966     exactly the same calls. *)
7967
7968 type t
7969 (** A [guestfs_h] handle. *)
7970
7971 exception Error of string
7972 (** This exception is raised when there is an error. *)
7973
7974 exception Handle_closed of string
7975 (** This exception is raised if you use a {!Guestfs.t} handle
7976     after calling {!close} on it.  The string is the name of
7977     the function. *)
7978
7979 val create : unit -> t
7980 (** Create a {!Guestfs.t} handle. *)
7981
7982 val close : t -> unit
7983 (** Close the {!Guestfs.t} handle and free up all resources used
7984     by it immediately.
7985
7986     Handles are closed by the garbage collector when they become
7987     unreferenced, but callers can call this in order to provide
7988     predictable cleanup. *)
7989
7990 ";
7991   generate_ocaml_structure_decls ();
7992
7993   (* The actions. *)
7994   List.iter (
7995     fun (name, style, _, _, _, shortdesc, _) ->
7996       generate_ocaml_prototype name style;
7997       pr "(** %s *)\n" shortdesc;
7998       pr "\n"
7999   ) all_functions_sorted
8000
8001 (* Generate the OCaml bindings implementation. *)
8002 and generate_ocaml_ml () =
8003   generate_header OCamlStyle LGPLv2plus;
8004
8005   pr "\
8006 type t
8007
8008 exception Error of string
8009 exception Handle_closed of string
8010
8011 external create : unit -> t = \"ocaml_guestfs_create\"
8012 external close : t -> unit = \"ocaml_guestfs_close\"
8013
8014 (* Give the exceptions names, so they can be raised from the C code. *)
8015 let () =
8016   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8017   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8018
8019 ";
8020
8021   generate_ocaml_structure_decls ();
8022
8023   (* The actions. *)
8024   List.iter (
8025     fun (name, style, _, _, _, shortdesc, _) ->
8026       generate_ocaml_prototype ~is_external:true name style;
8027   ) all_functions_sorted
8028
8029 (* Generate the OCaml bindings C implementation. *)
8030 and generate_ocaml_c () =
8031   generate_header CStyle LGPLv2plus;
8032
8033   pr "\
8034 #include <stdio.h>
8035 #include <stdlib.h>
8036 #include <string.h>
8037
8038 #include <caml/config.h>
8039 #include <caml/alloc.h>
8040 #include <caml/callback.h>
8041 #include <caml/fail.h>
8042 #include <caml/memory.h>
8043 #include <caml/mlvalues.h>
8044 #include <caml/signals.h>
8045
8046 #include <guestfs.h>
8047
8048 #include \"guestfs_c.h\"
8049
8050 /* Copy a hashtable of string pairs into an assoc-list.  We return
8051  * the list in reverse order, but hashtables aren't supposed to be
8052  * ordered anyway.
8053  */
8054 static CAMLprim value
8055 copy_table (char * const * argv)
8056 {
8057   CAMLparam0 ();
8058   CAMLlocal5 (rv, pairv, kv, vv, cons);
8059   int i;
8060
8061   rv = Val_int (0);
8062   for (i = 0; argv[i] != NULL; i += 2) {
8063     kv = caml_copy_string (argv[i]);
8064     vv = caml_copy_string (argv[i+1]);
8065     pairv = caml_alloc (2, 0);
8066     Store_field (pairv, 0, kv);
8067     Store_field (pairv, 1, vv);
8068     cons = caml_alloc (2, 0);
8069     Store_field (cons, 1, rv);
8070     rv = cons;
8071     Store_field (cons, 0, pairv);
8072   }
8073
8074   CAMLreturn (rv);
8075 }
8076
8077 ";
8078
8079   (* Struct copy functions. *)
8080
8081   let emit_ocaml_copy_list_function typ =
8082     pr "static CAMLprim value\n";
8083     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8084     pr "{\n";
8085     pr "  CAMLparam0 ();\n";
8086     pr "  CAMLlocal2 (rv, v);\n";
8087     pr "  unsigned int i;\n";
8088     pr "\n";
8089     pr "  if (%ss->len == 0)\n" typ;
8090     pr "    CAMLreturn (Atom (0));\n";
8091     pr "  else {\n";
8092     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8093     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8094     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8095     pr "      caml_modify (&Field (rv, i), v);\n";
8096     pr "    }\n";
8097     pr "    CAMLreturn (rv);\n";
8098     pr "  }\n";
8099     pr "}\n";
8100     pr "\n";
8101   in
8102
8103   List.iter (
8104     fun (typ, cols) ->
8105       let has_optpercent_col =
8106         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8107
8108       pr "static CAMLprim value\n";
8109       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8110       pr "{\n";
8111       pr "  CAMLparam0 ();\n";
8112       if has_optpercent_col then
8113         pr "  CAMLlocal3 (rv, v, v2);\n"
8114       else
8115         pr "  CAMLlocal2 (rv, v);\n";
8116       pr "\n";
8117       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8118       iteri (
8119         fun i col ->
8120           (match col with
8121            | name, FString ->
8122                pr "  v = caml_copy_string (%s->%s);\n" typ name
8123            | name, FBuffer ->
8124                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8125                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8126                  typ name typ name
8127            | name, FUUID ->
8128                pr "  v = caml_alloc_string (32);\n";
8129                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8130            | name, (FBytes|FInt64|FUInt64) ->
8131                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8132            | name, (FInt32|FUInt32) ->
8133                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8134            | name, FOptPercent ->
8135                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8136                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8137                pr "    v = caml_alloc (1, 0);\n";
8138                pr "    Store_field (v, 0, v2);\n";
8139                pr "  } else /* None */\n";
8140                pr "    v = Val_int (0);\n";
8141            | name, FChar ->
8142                pr "  v = Val_int (%s->%s);\n" typ name
8143           );
8144           pr "  Store_field (rv, %d, v);\n" i
8145       ) cols;
8146       pr "  CAMLreturn (rv);\n";
8147       pr "}\n";
8148       pr "\n";
8149   ) structs;
8150
8151   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8152   List.iter (
8153     function
8154     | typ, (RStructListOnly | RStructAndList) ->
8155         (* generate the function for typ *)
8156         emit_ocaml_copy_list_function typ
8157     | typ, _ -> () (* empty *)
8158   ) (rstructs_used_by all_functions);
8159
8160   (* The wrappers. *)
8161   List.iter (
8162     fun (name, style, _, _, _, _, _) ->
8163       pr "/* Automatically generated wrapper for function\n";
8164       pr " * ";
8165       generate_ocaml_prototype name style;
8166       pr " */\n";
8167       pr "\n";
8168
8169       let params =
8170         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8171
8172       let needs_extra_vs =
8173         match fst style with RConstOptString _ -> true | _ -> false in
8174
8175       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8176       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8177       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8178       pr "\n";
8179
8180       pr "CAMLprim value\n";
8181       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8182       List.iter (pr ", value %s") (List.tl params);
8183       pr ")\n";
8184       pr "{\n";
8185
8186       (match params with
8187        | [p1; p2; p3; p4; p5] ->
8188            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8189        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8190            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8191            pr "  CAMLxparam%d (%s);\n"
8192              (List.length rest) (String.concat ", " rest)
8193        | ps ->
8194            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8195       );
8196       if not needs_extra_vs then
8197         pr "  CAMLlocal1 (rv);\n"
8198       else
8199         pr "  CAMLlocal3 (rv, v, v2);\n";
8200       pr "\n";
8201
8202       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8203       pr "  if (g == NULL)\n";
8204       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8205       pr "\n";
8206
8207       List.iter (
8208         function
8209         | Pathname n
8210         | Device n | Dev_or_Path n
8211         | String n
8212         | FileIn n
8213         | FileOut n ->
8214             pr "  const char *%s = String_val (%sv);\n" n n
8215         | OptString n ->
8216             pr "  const char *%s =\n" n;
8217             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8218               n n
8219         | StringList n | DeviceList n ->
8220             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8221         | Bool n ->
8222             pr "  int %s = Bool_val (%sv);\n" n n
8223         | Int n ->
8224             pr "  int %s = Int_val (%sv);\n" n n
8225         | Int64 n ->
8226             pr "  int64_t %s = Int64_val (%sv);\n" n n
8227       ) (snd style);
8228       let error_code =
8229         match fst style with
8230         | RErr -> pr "  int r;\n"; "-1"
8231         | RInt _ -> pr "  int r;\n"; "-1"
8232         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8233         | RBool _ -> pr "  int r;\n"; "-1"
8234         | RConstString _ | RConstOptString _ ->
8235             pr "  const char *r;\n"; "NULL"
8236         | RString _ -> pr "  char *r;\n"; "NULL"
8237         | RStringList _ ->
8238             pr "  int i;\n";
8239             pr "  char **r;\n";
8240             "NULL"
8241         | RStruct (_, typ) ->
8242             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8243         | RStructList (_, typ) ->
8244             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8245         | RHashtable _ ->
8246             pr "  int i;\n";
8247             pr "  char **r;\n";
8248             "NULL"
8249         | RBufferOut _ ->
8250             pr "  char *r;\n";
8251             pr "  size_t size;\n";
8252             "NULL" in
8253       pr "\n";
8254
8255       pr "  caml_enter_blocking_section ();\n";
8256       pr "  r = guestfs_%s " name;
8257       generate_c_call_args ~handle:"g" style;
8258       pr ";\n";
8259       pr "  caml_leave_blocking_section ();\n";
8260
8261       List.iter (
8262         function
8263         | StringList n | DeviceList n ->
8264             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8265         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8266         | Bool _ | Int _ | Int64 _
8267         | FileIn _ | FileOut _ -> ()
8268       ) (snd style);
8269
8270       pr "  if (r == %s)\n" error_code;
8271       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8272       pr "\n";
8273
8274       (match fst style with
8275        | RErr -> pr "  rv = Val_unit;\n"
8276        | RInt _ -> pr "  rv = Val_int (r);\n"
8277        | RInt64 _ ->
8278            pr "  rv = caml_copy_int64 (r);\n"
8279        | RBool _ -> pr "  rv = Val_bool (r);\n"
8280        | RConstString _ ->
8281            pr "  rv = caml_copy_string (r);\n"
8282        | RConstOptString _ ->
8283            pr "  if (r) { /* Some string */\n";
8284            pr "    v = caml_alloc (1, 0);\n";
8285            pr "    v2 = caml_copy_string (r);\n";
8286            pr "    Store_field (v, 0, v2);\n";
8287            pr "  } else /* None */\n";
8288            pr "    v = Val_int (0);\n";
8289        | RString _ ->
8290            pr "  rv = caml_copy_string (r);\n";
8291            pr "  free (r);\n"
8292        | RStringList _ ->
8293            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8294            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8295            pr "  free (r);\n"
8296        | RStruct (_, typ) ->
8297            pr "  rv = copy_%s (r);\n" typ;
8298            pr "  guestfs_free_%s (r);\n" typ;
8299        | RStructList (_, typ) ->
8300            pr "  rv = copy_%s_list (r);\n" typ;
8301            pr "  guestfs_free_%s_list (r);\n" typ;
8302        | RHashtable _ ->
8303            pr "  rv = copy_table (r);\n";
8304            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8305            pr "  free (r);\n";
8306        | RBufferOut _ ->
8307            pr "  rv = caml_alloc_string (size);\n";
8308            pr "  memcpy (String_val (rv), r, size);\n";
8309       );
8310
8311       pr "  CAMLreturn (rv);\n";
8312       pr "}\n";
8313       pr "\n";
8314
8315       if List.length params > 5 then (
8316         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8317         pr "CAMLprim value ";
8318         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8319         pr "CAMLprim value\n";
8320         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8321         pr "{\n";
8322         pr "  return ocaml_guestfs_%s (argv[0]" name;
8323         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8324         pr ");\n";
8325         pr "}\n";
8326         pr "\n"
8327       )
8328   ) all_functions_sorted
8329
8330 and generate_ocaml_structure_decls () =
8331   List.iter (
8332     fun (typ, cols) ->
8333       pr "type %s = {\n" typ;
8334       List.iter (
8335         function
8336         | name, FString -> pr "  %s : string;\n" name
8337         | name, FBuffer -> pr "  %s : string;\n" name
8338         | name, FUUID -> pr "  %s : string;\n" name
8339         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8340         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8341         | name, FChar -> pr "  %s : char;\n" name
8342         | name, FOptPercent -> pr "  %s : float option;\n" name
8343       ) cols;
8344       pr "}\n";
8345       pr "\n"
8346   ) structs
8347
8348 and generate_ocaml_prototype ?(is_external = false) name style =
8349   if is_external then pr "external " else pr "val ";
8350   pr "%s : t -> " name;
8351   List.iter (
8352     function
8353     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8354     | OptString _ -> pr "string option -> "
8355     | StringList _ | DeviceList _ -> pr "string array -> "
8356     | Bool _ -> pr "bool -> "
8357     | Int _ -> pr "int -> "
8358     | Int64 _ -> pr "int64 -> "
8359   ) (snd style);
8360   (match fst style with
8361    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8362    | RInt _ -> pr "int"
8363    | RInt64 _ -> pr "int64"
8364    | RBool _ -> pr "bool"
8365    | RConstString _ -> pr "string"
8366    | RConstOptString _ -> pr "string option"
8367    | RString _ | RBufferOut _ -> pr "string"
8368    | RStringList _ -> pr "string array"
8369    | RStruct (_, typ) -> pr "%s" typ
8370    | RStructList (_, typ) -> pr "%s array" typ
8371    | RHashtable _ -> pr "(string * string) list"
8372   );
8373   if is_external then (
8374     pr " = ";
8375     if List.length (snd style) + 1 > 5 then
8376       pr "\"ocaml_guestfs_%s_byte\" " name;
8377     pr "\"ocaml_guestfs_%s\"" name
8378   );
8379   pr "\n"
8380
8381 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8382 and generate_perl_xs () =
8383   generate_header CStyle LGPLv2plus;
8384
8385   pr "\
8386 #include \"EXTERN.h\"
8387 #include \"perl.h\"
8388 #include \"XSUB.h\"
8389
8390 #include <guestfs.h>
8391
8392 #ifndef PRId64
8393 #define PRId64 \"lld\"
8394 #endif
8395
8396 static SV *
8397 my_newSVll(long long val) {
8398 #ifdef USE_64_BIT_ALL
8399   return newSViv(val);
8400 #else
8401   char buf[100];
8402   int len;
8403   len = snprintf(buf, 100, \"%%\" PRId64, val);
8404   return newSVpv(buf, len);
8405 #endif
8406 }
8407
8408 #ifndef PRIu64
8409 #define PRIu64 \"llu\"
8410 #endif
8411
8412 static SV *
8413 my_newSVull(unsigned long long val) {
8414 #ifdef USE_64_BIT_ALL
8415   return newSVuv(val);
8416 #else
8417   char buf[100];
8418   int len;
8419   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8420   return newSVpv(buf, len);
8421 #endif
8422 }
8423
8424 /* http://www.perlmonks.org/?node_id=680842 */
8425 static char **
8426 XS_unpack_charPtrPtr (SV *arg) {
8427   char **ret;
8428   AV *av;
8429   I32 i;
8430
8431   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8432     croak (\"array reference expected\");
8433
8434   av = (AV *)SvRV (arg);
8435   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8436   if (!ret)
8437     croak (\"malloc failed\");
8438
8439   for (i = 0; i <= av_len (av); i++) {
8440     SV **elem = av_fetch (av, i, 0);
8441
8442     if (!elem || !*elem)
8443       croak (\"missing element in list\");
8444
8445     ret[i] = SvPV_nolen (*elem);
8446   }
8447
8448   ret[i] = NULL;
8449
8450   return ret;
8451 }
8452
8453 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8454
8455 PROTOTYPES: ENABLE
8456
8457 guestfs_h *
8458 _create ()
8459    CODE:
8460       RETVAL = guestfs_create ();
8461       if (!RETVAL)
8462         croak (\"could not create guestfs handle\");
8463       guestfs_set_error_handler (RETVAL, NULL, NULL);
8464  OUTPUT:
8465       RETVAL
8466
8467 void
8468 DESTROY (g)
8469       guestfs_h *g;
8470  PPCODE:
8471       guestfs_close (g);
8472
8473 ";
8474
8475   List.iter (
8476     fun (name, style, _, _, _, _, _) ->
8477       (match fst style with
8478        | RErr -> pr "void\n"
8479        | RInt _ -> pr "SV *\n"
8480        | RInt64 _ -> pr "SV *\n"
8481        | RBool _ -> pr "SV *\n"
8482        | RConstString _ -> pr "SV *\n"
8483        | RConstOptString _ -> pr "SV *\n"
8484        | RString _ -> pr "SV *\n"
8485        | RBufferOut _ -> pr "SV *\n"
8486        | RStringList _
8487        | RStruct _ | RStructList _
8488        | RHashtable _ ->
8489            pr "void\n" (* all lists returned implictly on the stack *)
8490       );
8491       (* Call and arguments. *)
8492       pr "%s " name;
8493       generate_c_call_args ~handle:"g" ~decl:true style;
8494       pr "\n";
8495       pr "      guestfs_h *g;\n";
8496       iteri (
8497         fun i ->
8498           function
8499           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8500               pr "      char *%s;\n" n
8501           | OptString n ->
8502               (* http://www.perlmonks.org/?node_id=554277
8503                * Note that the implicit handle argument means we have
8504                * to add 1 to the ST(x) operator.
8505                *)
8506               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8507           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8508           | Bool n -> pr "      int %s;\n" n
8509           | Int n -> pr "      int %s;\n" n
8510           | Int64 n -> pr "      int64_t %s;\n" n
8511       ) (snd style);
8512
8513       let do_cleanups () =
8514         List.iter (
8515           function
8516           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8517           | Bool _ | Int _ | Int64 _
8518           | FileIn _ | FileOut _ -> ()
8519           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8520         ) (snd style)
8521       in
8522
8523       (* Code. *)
8524       (match fst style with
8525        | RErr ->
8526            pr "PREINIT:\n";
8527            pr "      int r;\n";
8528            pr " PPCODE:\n";
8529            pr "      r = guestfs_%s " name;
8530            generate_c_call_args ~handle:"g" style;
8531            pr ";\n";
8532            do_cleanups ();
8533            pr "      if (r == -1)\n";
8534            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8535        | RInt n
8536        | RBool n ->
8537            pr "PREINIT:\n";
8538            pr "      int %s;\n" n;
8539            pr "   CODE:\n";
8540            pr "      %s = guestfs_%s " n name;
8541            generate_c_call_args ~handle:"g" style;
8542            pr ";\n";
8543            do_cleanups ();
8544            pr "      if (%s == -1)\n" n;
8545            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8546            pr "      RETVAL = newSViv (%s);\n" n;
8547            pr " OUTPUT:\n";
8548            pr "      RETVAL\n"
8549        | RInt64 n ->
8550            pr "PREINIT:\n";
8551            pr "      int64_t %s;\n" n;
8552            pr "   CODE:\n";
8553            pr "      %s = guestfs_%s " n name;
8554            generate_c_call_args ~handle:"g" style;
8555            pr ";\n";
8556            do_cleanups ();
8557            pr "      if (%s == -1)\n" n;
8558            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8559            pr "      RETVAL = my_newSVll (%s);\n" n;
8560            pr " OUTPUT:\n";
8561            pr "      RETVAL\n"
8562        | RConstString n ->
8563            pr "PREINIT:\n";
8564            pr "      const char *%s;\n" n;
8565            pr "   CODE:\n";
8566            pr "      %s = guestfs_%s " n name;
8567            generate_c_call_args ~handle:"g" style;
8568            pr ";\n";
8569            do_cleanups ();
8570            pr "      if (%s == NULL)\n" n;
8571            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8572            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8573            pr " OUTPUT:\n";
8574            pr "      RETVAL\n"
8575        | RConstOptString n ->
8576            pr "PREINIT:\n";
8577            pr "      const char *%s;\n" n;
8578            pr "   CODE:\n";
8579            pr "      %s = guestfs_%s " n name;
8580            generate_c_call_args ~handle:"g" style;
8581            pr ";\n";
8582            do_cleanups ();
8583            pr "      if (%s == NULL)\n" n;
8584            pr "        RETVAL = &PL_sv_undef;\n";
8585            pr "      else\n";
8586            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8587            pr " OUTPUT:\n";
8588            pr "      RETVAL\n"
8589        | RString n ->
8590            pr "PREINIT:\n";
8591            pr "      char *%s;\n" n;
8592            pr "   CODE:\n";
8593            pr "      %s = guestfs_%s " n name;
8594            generate_c_call_args ~handle:"g" style;
8595            pr ";\n";
8596            do_cleanups ();
8597            pr "      if (%s == NULL)\n" n;
8598            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8599            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8600            pr "      free (%s);\n" n;
8601            pr " OUTPUT:\n";
8602            pr "      RETVAL\n"
8603        | RStringList n | RHashtable n ->
8604            pr "PREINIT:\n";
8605            pr "      char **%s;\n" n;
8606            pr "      int i, n;\n";
8607            pr " PPCODE:\n";
8608            pr "      %s = guestfs_%s " n name;
8609            generate_c_call_args ~handle:"g" style;
8610            pr ";\n";
8611            do_cleanups ();
8612            pr "      if (%s == NULL)\n" n;
8613            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8614            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8615            pr "      EXTEND (SP, n);\n";
8616            pr "      for (i = 0; i < n; ++i) {\n";
8617            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8618            pr "        free (%s[i]);\n" n;
8619            pr "      }\n";
8620            pr "      free (%s);\n" n;
8621        | RStruct (n, typ) ->
8622            let cols = cols_of_struct typ in
8623            generate_perl_struct_code typ cols name style n do_cleanups
8624        | RStructList (n, typ) ->
8625            let cols = cols_of_struct typ in
8626            generate_perl_struct_list_code typ cols name style n do_cleanups
8627        | RBufferOut n ->
8628            pr "PREINIT:\n";
8629            pr "      char *%s;\n" n;
8630            pr "      size_t size;\n";
8631            pr "   CODE:\n";
8632            pr "      %s = guestfs_%s " n name;
8633            generate_c_call_args ~handle:"g" style;
8634            pr ";\n";
8635            do_cleanups ();
8636            pr "      if (%s == NULL)\n" n;
8637            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8638            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8639            pr "      free (%s);\n" n;
8640            pr " OUTPUT:\n";
8641            pr "      RETVAL\n"
8642       );
8643
8644       pr "\n"
8645   ) all_functions
8646
8647 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8648   pr "PREINIT:\n";
8649   pr "      struct guestfs_%s_list *%s;\n" typ n;
8650   pr "      int i;\n";
8651   pr "      HV *hv;\n";
8652   pr " PPCODE:\n";
8653   pr "      %s = guestfs_%s " n name;
8654   generate_c_call_args ~handle:"g" style;
8655   pr ";\n";
8656   do_cleanups ();
8657   pr "      if (%s == NULL)\n" n;
8658   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8659   pr "      EXTEND (SP, %s->len);\n" n;
8660   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8661   pr "        hv = newHV ();\n";
8662   List.iter (
8663     function
8664     | name, FString ->
8665         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8666           name (String.length name) n name
8667     | name, FUUID ->
8668         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8669           name (String.length name) n name
8670     | name, FBuffer ->
8671         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8672           name (String.length name) n name n name
8673     | name, (FBytes|FUInt64) ->
8674         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8675           name (String.length name) n name
8676     | name, FInt64 ->
8677         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8678           name (String.length name) n name
8679     | name, (FInt32|FUInt32) ->
8680         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8681           name (String.length name) n name
8682     | name, FChar ->
8683         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8684           name (String.length name) n name
8685     | name, FOptPercent ->
8686         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8687           name (String.length name) n name
8688   ) cols;
8689   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8690   pr "      }\n";
8691   pr "      guestfs_free_%s_list (%s);\n" typ n
8692
8693 and generate_perl_struct_code typ cols name style n do_cleanups =
8694   pr "PREINIT:\n";
8695   pr "      struct guestfs_%s *%s;\n" typ n;
8696   pr " PPCODE:\n";
8697   pr "      %s = guestfs_%s " n name;
8698   generate_c_call_args ~handle:"g" style;
8699   pr ";\n";
8700   do_cleanups ();
8701   pr "      if (%s == NULL)\n" n;
8702   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8703   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8704   List.iter (
8705     fun ((name, _) as col) ->
8706       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8707
8708       match col with
8709       | name, FString ->
8710           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8711             n name
8712       | name, FBuffer ->
8713           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8714             n name n name
8715       | name, FUUID ->
8716           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8717             n name
8718       | name, (FBytes|FUInt64) ->
8719           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8720             n name
8721       | name, FInt64 ->
8722           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8723             n name
8724       | name, (FInt32|FUInt32) ->
8725           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8726             n name
8727       | name, FChar ->
8728           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8729             n name
8730       | name, FOptPercent ->
8731           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8732             n name
8733   ) cols;
8734   pr "      free (%s);\n" n
8735
8736 (* Generate Sys/Guestfs.pm. *)
8737 and generate_perl_pm () =
8738   generate_header HashStyle LGPLv2plus;
8739
8740   pr "\
8741 =pod
8742
8743 =head1 NAME
8744
8745 Sys::Guestfs - Perl bindings for libguestfs
8746
8747 =head1 SYNOPSIS
8748
8749  use Sys::Guestfs;
8750
8751  my $h = Sys::Guestfs->new ();
8752  $h->add_drive ('guest.img');
8753  $h->launch ();
8754  $h->mount ('/dev/sda1', '/');
8755  $h->touch ('/hello');
8756  $h->sync ();
8757
8758 =head1 DESCRIPTION
8759
8760 The C<Sys::Guestfs> module provides a Perl XS binding to the
8761 libguestfs API for examining and modifying virtual machine
8762 disk images.
8763
8764 Amongst the things this is good for: making batch configuration
8765 changes to guests, getting disk used/free statistics (see also:
8766 virt-df), migrating between virtualization systems (see also:
8767 virt-p2v), performing partial backups, performing partial guest
8768 clones, cloning guests and changing registry/UUID/hostname info, and
8769 much else besides.
8770
8771 Libguestfs uses Linux kernel and qemu code, and can access any type of
8772 guest filesystem that Linux and qemu can, including but not limited
8773 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8774 schemes, qcow, qcow2, vmdk.
8775
8776 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8777 LVs, what filesystem is in each LV, etc.).  It can also run commands
8778 in the context of the guest.  Also you can access filesystems over
8779 FUSE.
8780
8781 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8782 functions for using libguestfs from Perl, including integration
8783 with libvirt.
8784
8785 =head1 ERRORS
8786
8787 All errors turn into calls to C<croak> (see L<Carp(3)>).
8788
8789 =head1 METHODS
8790
8791 =over 4
8792
8793 =cut
8794
8795 package Sys::Guestfs;
8796
8797 use strict;
8798 use warnings;
8799
8800 require XSLoader;
8801 XSLoader::load ('Sys::Guestfs');
8802
8803 =item $h = Sys::Guestfs->new ();
8804
8805 Create a new guestfs handle.
8806
8807 =cut
8808
8809 sub new {
8810   my $proto = shift;
8811   my $class = ref ($proto) || $proto;
8812
8813   my $self = Sys::Guestfs::_create ();
8814   bless $self, $class;
8815   return $self;
8816 }
8817
8818 ";
8819
8820   (* Actions.  We only need to print documentation for these as
8821    * they are pulled in from the XS code automatically.
8822    *)
8823   List.iter (
8824     fun (name, style, _, flags, _, _, longdesc) ->
8825       if not (List.mem NotInDocs flags) then (
8826         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8827         pr "=item ";
8828         generate_perl_prototype name style;
8829         pr "\n\n";
8830         pr "%s\n\n" longdesc;
8831         if List.mem ProtocolLimitWarning flags then
8832           pr "%s\n\n" protocol_limit_warning;
8833         if List.mem DangerWillRobinson flags then
8834           pr "%s\n\n" danger_will_robinson;
8835         match deprecation_notice flags with
8836         | None -> ()
8837         | Some txt -> pr "%s\n\n" txt
8838       )
8839   ) all_functions_sorted;
8840
8841   (* End of file. *)
8842   pr "\
8843 =cut
8844
8845 1;
8846
8847 =back
8848
8849 =head1 COPYRIGHT
8850
8851 Copyright (C) %s Red Hat Inc.
8852
8853 =head1 LICENSE
8854
8855 Please see the file COPYING.LIB for the full license.
8856
8857 =head1 SEE ALSO
8858
8859 L<guestfs(3)>,
8860 L<guestfish(1)>,
8861 L<http://libguestfs.org>,
8862 L<Sys::Guestfs::Lib(3)>.
8863
8864 =cut
8865 " copyright_years
8866
8867 and generate_perl_prototype name style =
8868   (match fst style with
8869    | RErr -> ()
8870    | RBool n
8871    | RInt n
8872    | RInt64 n
8873    | RConstString n
8874    | RConstOptString n
8875    | RString n
8876    | RBufferOut n -> pr "$%s = " n
8877    | RStruct (n,_)
8878    | RHashtable n -> pr "%%%s = " n
8879    | RStringList n
8880    | RStructList (n,_) -> pr "@%s = " n
8881   );
8882   pr "$h->%s (" name;
8883   let comma = ref false in
8884   List.iter (
8885     fun arg ->
8886       if !comma then pr ", ";
8887       comma := true;
8888       match arg with
8889       | Pathname n | Device n | Dev_or_Path n | String n
8890       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8891           pr "$%s" n
8892       | StringList n | DeviceList n ->
8893           pr "\\@%s" n
8894   ) (snd style);
8895   pr ");"
8896
8897 (* Generate Python C module. *)
8898 and generate_python_c () =
8899   generate_header CStyle LGPLv2plus;
8900
8901   pr "\
8902 #include <Python.h>
8903
8904 #include <stdio.h>
8905 #include <stdlib.h>
8906 #include <assert.h>
8907
8908 #include \"guestfs.h\"
8909
8910 typedef struct {
8911   PyObject_HEAD
8912   guestfs_h *g;
8913 } Pyguestfs_Object;
8914
8915 static guestfs_h *
8916 get_handle (PyObject *obj)
8917 {
8918   assert (obj);
8919   assert (obj != Py_None);
8920   return ((Pyguestfs_Object *) obj)->g;
8921 }
8922
8923 static PyObject *
8924 put_handle (guestfs_h *g)
8925 {
8926   assert (g);
8927   return
8928     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8929 }
8930
8931 /* This list should be freed (but not the strings) after use. */
8932 static char **
8933 get_string_list (PyObject *obj)
8934 {
8935   int i, len;
8936   char **r;
8937
8938   assert (obj);
8939
8940   if (!PyList_Check (obj)) {
8941     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8942     return NULL;
8943   }
8944
8945   len = PyList_Size (obj);
8946   r = malloc (sizeof (char *) * (len+1));
8947   if (r == NULL) {
8948     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8949     return NULL;
8950   }
8951
8952   for (i = 0; i < len; ++i)
8953     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8954   r[len] = NULL;
8955
8956   return r;
8957 }
8958
8959 static PyObject *
8960 put_string_list (char * const * const argv)
8961 {
8962   PyObject *list;
8963   int argc, i;
8964
8965   for (argc = 0; argv[argc] != NULL; ++argc)
8966     ;
8967
8968   list = PyList_New (argc);
8969   for (i = 0; i < argc; ++i)
8970     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8971
8972   return list;
8973 }
8974
8975 static PyObject *
8976 put_table (char * const * const argv)
8977 {
8978   PyObject *list, *item;
8979   int argc, i;
8980
8981   for (argc = 0; argv[argc] != NULL; ++argc)
8982     ;
8983
8984   list = PyList_New (argc >> 1);
8985   for (i = 0; i < argc; i += 2) {
8986     item = PyTuple_New (2);
8987     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8988     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8989     PyList_SetItem (list, i >> 1, item);
8990   }
8991
8992   return list;
8993 }
8994
8995 static void
8996 free_strings (char **argv)
8997 {
8998   int argc;
8999
9000   for (argc = 0; argv[argc] != NULL; ++argc)
9001     free (argv[argc]);
9002   free (argv);
9003 }
9004
9005 static PyObject *
9006 py_guestfs_create (PyObject *self, PyObject *args)
9007 {
9008   guestfs_h *g;
9009
9010   g = guestfs_create ();
9011   if (g == NULL) {
9012     PyErr_SetString (PyExc_RuntimeError,
9013                      \"guestfs.create: failed to allocate handle\");
9014     return NULL;
9015   }
9016   guestfs_set_error_handler (g, NULL, NULL);
9017   return put_handle (g);
9018 }
9019
9020 static PyObject *
9021 py_guestfs_close (PyObject *self, PyObject *args)
9022 {
9023   PyObject *py_g;
9024   guestfs_h *g;
9025
9026   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9027     return NULL;
9028   g = get_handle (py_g);
9029
9030   guestfs_close (g);
9031
9032   Py_INCREF (Py_None);
9033   return Py_None;
9034 }
9035
9036 ";
9037
9038   let emit_put_list_function typ =
9039     pr "static PyObject *\n";
9040     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9041     pr "{\n";
9042     pr "  PyObject *list;\n";
9043     pr "  int i;\n";
9044     pr "\n";
9045     pr "  list = PyList_New (%ss->len);\n" typ;
9046     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9047     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9048     pr "  return list;\n";
9049     pr "};\n";
9050     pr "\n"
9051   in
9052
9053   (* Structures, turned into Python dictionaries. *)
9054   List.iter (
9055     fun (typ, cols) ->
9056       pr "static PyObject *\n";
9057       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9058       pr "{\n";
9059       pr "  PyObject *dict;\n";
9060       pr "\n";
9061       pr "  dict = PyDict_New ();\n";
9062       List.iter (
9063         function
9064         | name, FString ->
9065             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9066             pr "                        PyString_FromString (%s->%s));\n"
9067               typ name
9068         | name, FBuffer ->
9069             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9070             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9071               typ name typ name
9072         | name, FUUID ->
9073             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9074             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9075               typ name
9076         | name, (FBytes|FUInt64) ->
9077             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9078             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9079               typ name
9080         | name, FInt64 ->
9081             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9082             pr "                        PyLong_FromLongLong (%s->%s));\n"
9083               typ name
9084         | name, FUInt32 ->
9085             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9086             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9087               typ name
9088         | name, FInt32 ->
9089             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9090             pr "                        PyLong_FromLong (%s->%s));\n"
9091               typ name
9092         | name, FOptPercent ->
9093             pr "  if (%s->%s >= 0)\n" typ name;
9094             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9095             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9096               typ name;
9097             pr "  else {\n";
9098             pr "    Py_INCREF (Py_None);\n";
9099             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9100             pr "  }\n"
9101         | name, FChar ->
9102             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9103             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9104       ) cols;
9105       pr "  return dict;\n";
9106       pr "};\n";
9107       pr "\n";
9108
9109   ) structs;
9110
9111   (* Emit a put_TYPE_list function definition only if that function is used. *)
9112   List.iter (
9113     function
9114     | typ, (RStructListOnly | RStructAndList) ->
9115         (* generate the function for typ *)
9116         emit_put_list_function typ
9117     | typ, _ -> () (* empty *)
9118   ) (rstructs_used_by all_functions);
9119
9120   (* Python wrapper functions. *)
9121   List.iter (
9122     fun (name, style, _, _, _, _, _) ->
9123       pr "static PyObject *\n";
9124       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9125       pr "{\n";
9126
9127       pr "  PyObject *py_g;\n";
9128       pr "  guestfs_h *g;\n";
9129       pr "  PyObject *py_r;\n";
9130
9131       let error_code =
9132         match fst style with
9133         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9134         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9135         | RConstString _ | RConstOptString _ ->
9136             pr "  const char *r;\n"; "NULL"
9137         | RString _ -> pr "  char *r;\n"; "NULL"
9138         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9139         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9140         | RStructList (_, typ) ->
9141             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9142         | RBufferOut _ ->
9143             pr "  char *r;\n";
9144             pr "  size_t size;\n";
9145             "NULL" in
9146
9147       List.iter (
9148         function
9149         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9150             pr "  const char *%s;\n" n
9151         | OptString n -> pr "  const char *%s;\n" n
9152         | StringList n | DeviceList n ->
9153             pr "  PyObject *py_%s;\n" n;
9154             pr "  char **%s;\n" n
9155         | Bool n -> pr "  int %s;\n" n
9156         | Int n -> pr "  int %s;\n" n
9157         | Int64 n -> pr "  long long %s;\n" n
9158       ) (snd style);
9159
9160       pr "\n";
9161
9162       (* Convert the parameters. *)
9163       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9164       List.iter (
9165         function
9166         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9167         | OptString _ -> pr "z"
9168         | StringList _ | DeviceList _ -> pr "O"
9169         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9170         | Int _ -> pr "i"
9171         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9172                              * emulate C's int/long/long long in Python?
9173                              *)
9174       ) (snd style);
9175       pr ":guestfs_%s\",\n" name;
9176       pr "                         &py_g";
9177       List.iter (
9178         function
9179         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9180         | OptString n -> pr ", &%s" n
9181         | StringList n | DeviceList n -> pr ", &py_%s" n
9182         | Bool n -> pr ", &%s" n
9183         | Int n -> pr ", &%s" n
9184         | Int64 n -> pr ", &%s" n
9185       ) (snd style);
9186
9187       pr "))\n";
9188       pr "    return NULL;\n";
9189
9190       pr "  g = get_handle (py_g);\n";
9191       List.iter (
9192         function
9193         | Pathname _ | Device _ | Dev_or_Path _ | String _
9194         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9195         | StringList n | DeviceList n ->
9196             pr "  %s = get_string_list (py_%s);\n" n n;
9197             pr "  if (!%s) return NULL;\n" n
9198       ) (snd style);
9199
9200       pr "\n";
9201
9202       pr "  r = guestfs_%s " name;
9203       generate_c_call_args ~handle:"g" style;
9204       pr ";\n";
9205
9206       List.iter (
9207         function
9208         | Pathname _ | Device _ | Dev_or_Path _ | String _
9209         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9210         | StringList n | DeviceList n ->
9211             pr "  free (%s);\n" n
9212       ) (snd style);
9213
9214       pr "  if (r == %s) {\n" error_code;
9215       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9216       pr "    return NULL;\n";
9217       pr "  }\n";
9218       pr "\n";
9219
9220       (match fst style with
9221        | RErr ->
9222            pr "  Py_INCREF (Py_None);\n";
9223            pr "  py_r = Py_None;\n"
9224        | RInt _
9225        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9226        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9227        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9228        | RConstOptString _ ->
9229            pr "  if (r)\n";
9230            pr "    py_r = PyString_FromString (r);\n";
9231            pr "  else {\n";
9232            pr "    Py_INCREF (Py_None);\n";
9233            pr "    py_r = Py_None;\n";
9234            pr "  }\n"
9235        | RString _ ->
9236            pr "  py_r = PyString_FromString (r);\n";
9237            pr "  free (r);\n"
9238        | RStringList _ ->
9239            pr "  py_r = put_string_list (r);\n";
9240            pr "  free_strings (r);\n"
9241        | RStruct (_, typ) ->
9242            pr "  py_r = put_%s (r);\n" typ;
9243            pr "  guestfs_free_%s (r);\n" typ
9244        | RStructList (_, typ) ->
9245            pr "  py_r = put_%s_list (r);\n" typ;
9246            pr "  guestfs_free_%s_list (r);\n" typ
9247        | RHashtable n ->
9248            pr "  py_r = put_table (r);\n";
9249            pr "  free_strings (r);\n"
9250        | RBufferOut _ ->
9251            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9252            pr "  free (r);\n"
9253       );
9254
9255       pr "  return py_r;\n";
9256       pr "}\n";
9257       pr "\n"
9258   ) all_functions;
9259
9260   (* Table of functions. *)
9261   pr "static PyMethodDef methods[] = {\n";
9262   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9263   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9264   List.iter (
9265     fun (name, _, _, _, _, _, _) ->
9266       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9267         name name
9268   ) all_functions;
9269   pr "  { NULL, NULL, 0, NULL }\n";
9270   pr "};\n";
9271   pr "\n";
9272
9273   (* Init function. *)
9274   pr "\
9275 void
9276 initlibguestfsmod (void)
9277 {
9278   static int initialized = 0;
9279
9280   if (initialized) return;
9281   Py_InitModule ((char *) \"libguestfsmod\", methods);
9282   initialized = 1;
9283 }
9284 "
9285
9286 (* Generate Python module. *)
9287 and generate_python_py () =
9288   generate_header HashStyle LGPLv2plus;
9289
9290   pr "\
9291 u\"\"\"Python bindings for libguestfs
9292
9293 import guestfs
9294 g = guestfs.GuestFS ()
9295 g.add_drive (\"guest.img\")
9296 g.launch ()
9297 parts = g.list_partitions ()
9298
9299 The guestfs module provides a Python binding to the libguestfs API
9300 for examining and modifying virtual machine disk images.
9301
9302 Amongst the things this is good for: making batch configuration
9303 changes to guests, getting disk used/free statistics (see also:
9304 virt-df), migrating between virtualization systems (see also:
9305 virt-p2v), performing partial backups, performing partial guest
9306 clones, cloning guests and changing registry/UUID/hostname info, and
9307 much else besides.
9308
9309 Libguestfs uses Linux kernel and qemu code, and can access any type of
9310 guest filesystem that Linux and qemu can, including but not limited
9311 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9312 schemes, qcow, qcow2, vmdk.
9313
9314 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9315 LVs, what filesystem is in each LV, etc.).  It can also run commands
9316 in the context of the guest.  Also you can access filesystems over
9317 FUSE.
9318
9319 Errors which happen while using the API are turned into Python
9320 RuntimeError exceptions.
9321
9322 To create a guestfs handle you usually have to perform the following
9323 sequence of calls:
9324
9325 # Create the handle, call add_drive at least once, and possibly
9326 # several times if the guest has multiple block devices:
9327 g = guestfs.GuestFS ()
9328 g.add_drive (\"guest.img\")
9329
9330 # Launch the qemu subprocess and wait for it to become ready:
9331 g.launch ()
9332
9333 # Now you can issue commands, for example:
9334 logvols = g.lvs ()
9335
9336 \"\"\"
9337
9338 import libguestfsmod
9339
9340 class GuestFS:
9341     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9342
9343     def __init__ (self):
9344         \"\"\"Create a new libguestfs handle.\"\"\"
9345         self._o = libguestfsmod.create ()
9346
9347     def __del__ (self):
9348         libguestfsmod.close (self._o)
9349
9350 ";
9351
9352   List.iter (
9353     fun (name, style, _, flags, _, _, longdesc) ->
9354       pr "    def %s " name;
9355       generate_py_call_args ~handle:"self" (snd style);
9356       pr ":\n";
9357
9358       if not (List.mem NotInDocs flags) then (
9359         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9360         let doc =
9361           match fst style with
9362           | RErr | RInt _ | RInt64 _ | RBool _
9363           | RConstOptString _ | RConstString _
9364           | RString _ | RBufferOut _ -> doc
9365           | RStringList _ ->
9366               doc ^ "\n\nThis function returns a list of strings."
9367           | RStruct (_, typ) ->
9368               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9369           | RStructList (_, typ) ->
9370               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9371           | RHashtable _ ->
9372               doc ^ "\n\nThis function returns a dictionary." in
9373         let doc =
9374           if List.mem ProtocolLimitWarning flags then
9375             doc ^ "\n\n" ^ protocol_limit_warning
9376           else doc in
9377         let doc =
9378           if List.mem DangerWillRobinson flags then
9379             doc ^ "\n\n" ^ danger_will_robinson
9380           else doc in
9381         let doc =
9382           match deprecation_notice flags with
9383           | None -> doc
9384           | Some txt -> doc ^ "\n\n" ^ txt in
9385         let doc = pod2text ~width:60 name doc in
9386         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9387         let doc = String.concat "\n        " doc in
9388         pr "        u\"\"\"%s\"\"\"\n" doc;
9389       );
9390       pr "        return libguestfsmod.%s " name;
9391       generate_py_call_args ~handle:"self._o" (snd style);
9392       pr "\n";
9393       pr "\n";
9394   ) all_functions
9395
9396 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9397 and generate_py_call_args ~handle args =
9398   pr "(%s" handle;
9399   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9400   pr ")"
9401
9402 (* Useful if you need the longdesc POD text as plain text.  Returns a
9403  * list of lines.
9404  *
9405  * Because this is very slow (the slowest part of autogeneration),
9406  * we memoize the results.
9407  *)
9408 and pod2text ~width name longdesc =
9409   let key = width, name, longdesc in
9410   try Hashtbl.find pod2text_memo key
9411   with Not_found ->
9412     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9413     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9414     close_out chan;
9415     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9416     let chan = open_process_in cmd in
9417     let lines = ref [] in
9418     let rec loop i =
9419       let line = input_line chan in
9420       if i = 1 then             (* discard the first line of output *)
9421         loop (i+1)
9422       else (
9423         let line = triml line in
9424         lines := line :: !lines;
9425         loop (i+1)
9426       ) in
9427     let lines = try loop 1 with End_of_file -> List.rev !lines in
9428     unlink filename;
9429     (match close_process_in chan with
9430      | WEXITED 0 -> ()
9431      | WEXITED i ->
9432          failwithf "pod2text: process exited with non-zero status (%d)" i
9433      | WSIGNALED i | WSTOPPED i ->
9434          failwithf "pod2text: process signalled or stopped by signal %d" i
9435     );
9436     Hashtbl.add pod2text_memo key lines;
9437     pod2text_memo_updated ();
9438     lines
9439
9440 (* Generate ruby bindings. *)
9441 and generate_ruby_c () =
9442   generate_header CStyle LGPLv2plus;
9443
9444   pr "\
9445 #include <stdio.h>
9446 #include <stdlib.h>
9447
9448 #include <ruby.h>
9449
9450 #include \"guestfs.h\"
9451
9452 #include \"extconf.h\"
9453
9454 /* For Ruby < 1.9 */
9455 #ifndef RARRAY_LEN
9456 #define RARRAY_LEN(r) (RARRAY((r))->len)
9457 #endif
9458
9459 static VALUE m_guestfs;                 /* guestfs module */
9460 static VALUE c_guestfs;                 /* guestfs_h handle */
9461 static VALUE e_Error;                   /* used for all errors */
9462
9463 static void ruby_guestfs_free (void *p)
9464 {
9465   if (!p) return;
9466   guestfs_close ((guestfs_h *) p);
9467 }
9468
9469 static VALUE ruby_guestfs_create (VALUE m)
9470 {
9471   guestfs_h *g;
9472
9473   g = guestfs_create ();
9474   if (!g)
9475     rb_raise (e_Error, \"failed to create guestfs handle\");
9476
9477   /* Don't print error messages to stderr by default. */
9478   guestfs_set_error_handler (g, NULL, NULL);
9479
9480   /* Wrap it, and make sure the close function is called when the
9481    * handle goes away.
9482    */
9483   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9484 }
9485
9486 static VALUE ruby_guestfs_close (VALUE gv)
9487 {
9488   guestfs_h *g;
9489   Data_Get_Struct (gv, guestfs_h, g);
9490
9491   ruby_guestfs_free (g);
9492   DATA_PTR (gv) = NULL;
9493
9494   return Qnil;
9495 }
9496
9497 ";
9498
9499   List.iter (
9500     fun (name, style, _, _, _, _, _) ->
9501       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9502       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9503       pr ")\n";
9504       pr "{\n";
9505       pr "  guestfs_h *g;\n";
9506       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9507       pr "  if (!g)\n";
9508       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9509         name;
9510       pr "\n";
9511
9512       List.iter (
9513         function
9514         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9515             pr "  Check_Type (%sv, T_STRING);\n" n;
9516             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9517             pr "  if (!%s)\n" n;
9518             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9519             pr "              \"%s\", \"%s\");\n" n name
9520         | OptString n ->
9521             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9522         | StringList n | DeviceList n ->
9523             pr "  char **%s;\n" n;
9524             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9525             pr "  {\n";
9526             pr "    int i, len;\n";
9527             pr "    len = RARRAY_LEN (%sv);\n" n;
9528             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9529               n;
9530             pr "    for (i = 0; i < len; ++i) {\n";
9531             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9532             pr "      %s[i] = StringValueCStr (v);\n" n;
9533             pr "    }\n";
9534             pr "    %s[len] = NULL;\n" n;
9535             pr "  }\n";
9536         | Bool n ->
9537             pr "  int %s = RTEST (%sv);\n" n n
9538         | Int n ->
9539             pr "  int %s = NUM2INT (%sv);\n" n n
9540         | Int64 n ->
9541             pr "  long long %s = NUM2LL (%sv);\n" n n
9542       ) (snd style);
9543       pr "\n";
9544
9545       let error_code =
9546         match fst style with
9547         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9548         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9549         | RConstString _ | RConstOptString _ ->
9550             pr "  const char *r;\n"; "NULL"
9551         | RString _ -> pr "  char *r;\n"; "NULL"
9552         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9553         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9554         | RStructList (_, typ) ->
9555             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9556         | RBufferOut _ ->
9557             pr "  char *r;\n";
9558             pr "  size_t size;\n";
9559             "NULL" in
9560       pr "\n";
9561
9562       pr "  r = guestfs_%s " name;
9563       generate_c_call_args ~handle:"g" style;
9564       pr ";\n";
9565
9566       List.iter (
9567         function
9568         | Pathname _ | Device _ | Dev_or_Path _ | String _
9569         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9570         | StringList n | DeviceList n ->
9571             pr "  free (%s);\n" n
9572       ) (snd style);
9573
9574       pr "  if (r == %s)\n" error_code;
9575       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9576       pr "\n";
9577
9578       (match fst style with
9579        | RErr ->
9580            pr "  return Qnil;\n"
9581        | RInt _ | RBool _ ->
9582            pr "  return INT2NUM (r);\n"
9583        | RInt64 _ ->
9584            pr "  return ULL2NUM (r);\n"
9585        | RConstString _ ->
9586            pr "  return rb_str_new2 (r);\n";
9587        | RConstOptString _ ->
9588            pr "  if (r)\n";
9589            pr "    return rb_str_new2 (r);\n";
9590            pr "  else\n";
9591            pr "    return Qnil;\n";
9592        | RString _ ->
9593            pr "  VALUE rv = rb_str_new2 (r);\n";
9594            pr "  free (r);\n";
9595            pr "  return rv;\n";
9596        | RStringList _ ->
9597            pr "  int i, len = 0;\n";
9598            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9599            pr "  VALUE rv = rb_ary_new2 (len);\n";
9600            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9601            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9602            pr "    free (r[i]);\n";
9603            pr "  }\n";
9604            pr "  free (r);\n";
9605            pr "  return rv;\n"
9606        | RStruct (_, typ) ->
9607            let cols = cols_of_struct typ in
9608            generate_ruby_struct_code typ cols
9609        | RStructList (_, typ) ->
9610            let cols = cols_of_struct typ in
9611            generate_ruby_struct_list_code typ cols
9612        | RHashtable _ ->
9613            pr "  VALUE rv = rb_hash_new ();\n";
9614            pr "  int i;\n";
9615            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9616            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9617            pr "    free (r[i]);\n";
9618            pr "    free (r[i+1]);\n";
9619            pr "  }\n";
9620            pr "  free (r);\n";
9621            pr "  return rv;\n"
9622        | RBufferOut _ ->
9623            pr "  VALUE rv = rb_str_new (r, size);\n";
9624            pr "  free (r);\n";
9625            pr "  return rv;\n";
9626       );
9627
9628       pr "}\n";
9629       pr "\n"
9630   ) all_functions;
9631
9632   pr "\
9633 /* Initialize the module. */
9634 void Init__guestfs ()
9635 {
9636   m_guestfs = rb_define_module (\"Guestfs\");
9637   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9638   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9639
9640   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9641   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9642
9643 ";
9644   (* Define the rest of the methods. *)
9645   List.iter (
9646     fun (name, style, _, _, _, _, _) ->
9647       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9648       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9649   ) all_functions;
9650
9651   pr "}\n"
9652
9653 (* Ruby code to return a struct. *)
9654 and generate_ruby_struct_code typ cols =
9655   pr "  VALUE rv = rb_hash_new ();\n";
9656   List.iter (
9657     function
9658     | name, FString ->
9659         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9660     | name, FBuffer ->
9661         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9662     | name, FUUID ->
9663         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9664     | name, (FBytes|FUInt64) ->
9665         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9666     | name, FInt64 ->
9667         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9668     | name, FUInt32 ->
9669         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9670     | name, FInt32 ->
9671         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9672     | name, FOptPercent ->
9673         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9674     | name, FChar -> (* XXX wrong? *)
9675         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9676   ) cols;
9677   pr "  guestfs_free_%s (r);\n" typ;
9678   pr "  return rv;\n"
9679
9680 (* Ruby code to return a struct list. *)
9681 and generate_ruby_struct_list_code typ cols =
9682   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9683   pr "  int i;\n";
9684   pr "  for (i = 0; i < r->len; ++i) {\n";
9685   pr "    VALUE hv = rb_hash_new ();\n";
9686   List.iter (
9687     function
9688     | name, FString ->
9689         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9690     | name, FBuffer ->
9691         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
9692     | name, FUUID ->
9693         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9694     | name, (FBytes|FUInt64) ->
9695         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9696     | name, FInt64 ->
9697         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9698     | name, FUInt32 ->
9699         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9700     | name, FInt32 ->
9701         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9702     | name, FOptPercent ->
9703         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9704     | name, FChar -> (* XXX wrong? *)
9705         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9706   ) cols;
9707   pr "    rb_ary_push (rv, hv);\n";
9708   pr "  }\n";
9709   pr "  guestfs_free_%s_list (r);\n" typ;
9710   pr "  return rv;\n"
9711
9712 (* Generate Java bindings GuestFS.java file. *)
9713 and generate_java_java () =
9714   generate_header CStyle LGPLv2plus;
9715
9716   pr "\
9717 package com.redhat.et.libguestfs;
9718
9719 import java.util.HashMap;
9720 import com.redhat.et.libguestfs.LibGuestFSException;
9721 import com.redhat.et.libguestfs.PV;
9722 import com.redhat.et.libguestfs.VG;
9723 import com.redhat.et.libguestfs.LV;
9724 import com.redhat.et.libguestfs.Stat;
9725 import com.redhat.et.libguestfs.StatVFS;
9726 import com.redhat.et.libguestfs.IntBool;
9727 import com.redhat.et.libguestfs.Dirent;
9728
9729 /**
9730  * The GuestFS object is a libguestfs handle.
9731  *
9732  * @author rjones
9733  */
9734 public class GuestFS {
9735   // Load the native code.
9736   static {
9737     System.loadLibrary (\"guestfs_jni\");
9738   }
9739
9740   /**
9741    * The native guestfs_h pointer.
9742    */
9743   long g;
9744
9745   /**
9746    * Create a libguestfs handle.
9747    *
9748    * @throws LibGuestFSException
9749    */
9750   public GuestFS () throws LibGuestFSException
9751   {
9752     g = _create ();
9753   }
9754   private native long _create () throws LibGuestFSException;
9755
9756   /**
9757    * Close a libguestfs handle.
9758    *
9759    * You can also leave handles to be collected by the garbage
9760    * collector, but this method ensures that the resources used
9761    * by the handle are freed up immediately.  If you call any
9762    * other methods after closing the handle, you will get an
9763    * exception.
9764    *
9765    * @throws LibGuestFSException
9766    */
9767   public void close () throws LibGuestFSException
9768   {
9769     if (g != 0)
9770       _close (g);
9771     g = 0;
9772   }
9773   private native void _close (long g) throws LibGuestFSException;
9774
9775   public void finalize () throws LibGuestFSException
9776   {
9777     close ();
9778   }
9779
9780 ";
9781
9782   List.iter (
9783     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9784       if not (List.mem NotInDocs flags); then (
9785         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9786         let doc =
9787           if List.mem ProtocolLimitWarning flags then
9788             doc ^ "\n\n" ^ protocol_limit_warning
9789           else doc in
9790         let doc =
9791           if List.mem DangerWillRobinson flags then
9792             doc ^ "\n\n" ^ danger_will_robinson
9793           else doc in
9794         let doc =
9795           match deprecation_notice flags with
9796           | None -> doc
9797           | Some txt -> doc ^ "\n\n" ^ txt in
9798         let doc = pod2text ~width:60 name doc in
9799         let doc = List.map (            (* RHBZ#501883 *)
9800           function
9801           | "" -> "<p>"
9802           | nonempty -> nonempty
9803         ) doc in
9804         let doc = String.concat "\n   * " doc in
9805
9806         pr "  /**\n";
9807         pr "   * %s\n" shortdesc;
9808         pr "   * <p>\n";
9809         pr "   * %s\n" doc;
9810         pr "   * @throws LibGuestFSException\n";
9811         pr "   */\n";
9812         pr "  ";
9813       );
9814       generate_java_prototype ~public:true ~semicolon:false name style;
9815       pr "\n";
9816       pr "  {\n";
9817       pr "    if (g == 0)\n";
9818       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9819         name;
9820       pr "    ";
9821       if fst style <> RErr then pr "return ";
9822       pr "_%s " name;
9823       generate_java_call_args ~handle:"g" (snd style);
9824       pr ";\n";
9825       pr "  }\n";
9826       pr "  ";
9827       generate_java_prototype ~privat:true ~native:true name style;
9828       pr "\n";
9829       pr "\n";
9830   ) all_functions;
9831
9832   pr "}\n"
9833
9834 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9835 and generate_java_call_args ~handle args =
9836   pr "(%s" handle;
9837   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9838   pr ")"
9839
9840 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9841     ?(semicolon=true) name style =
9842   if privat then pr "private ";
9843   if public then pr "public ";
9844   if native then pr "native ";
9845
9846   (* return type *)
9847   (match fst style with
9848    | RErr -> pr "void ";
9849    | RInt _ -> pr "int ";
9850    | RInt64 _ -> pr "long ";
9851    | RBool _ -> pr "boolean ";
9852    | RConstString _ | RConstOptString _ | RString _
9853    | RBufferOut _ -> pr "String ";
9854    | RStringList _ -> pr "String[] ";
9855    | RStruct (_, typ) ->
9856        let name = java_name_of_struct typ in
9857        pr "%s " name;
9858    | RStructList (_, typ) ->
9859        let name = java_name_of_struct typ in
9860        pr "%s[] " name;
9861    | RHashtable _ -> pr "HashMap<String,String> ";
9862   );
9863
9864   if native then pr "_%s " name else pr "%s " name;
9865   pr "(";
9866   let needs_comma = ref false in
9867   if native then (
9868     pr "long g";
9869     needs_comma := true
9870   );
9871
9872   (* args *)
9873   List.iter (
9874     fun arg ->
9875       if !needs_comma then pr ", ";
9876       needs_comma := true;
9877
9878       match arg with
9879       | Pathname n
9880       | Device n | Dev_or_Path n
9881       | String n
9882       | OptString n
9883       | FileIn n
9884       | FileOut n ->
9885           pr "String %s" n
9886       | StringList n | DeviceList n ->
9887           pr "String[] %s" n
9888       | Bool n ->
9889           pr "boolean %s" n
9890       | Int n ->
9891           pr "int %s" n
9892       | Int64 n ->
9893           pr "long %s" n
9894   ) (snd style);
9895
9896   pr ")\n";
9897   pr "    throws LibGuestFSException";
9898   if semicolon then pr ";"
9899
9900 and generate_java_struct jtyp cols () =
9901   generate_header CStyle LGPLv2plus;
9902
9903   pr "\
9904 package com.redhat.et.libguestfs;
9905
9906 /**
9907  * Libguestfs %s structure.
9908  *
9909  * @author rjones
9910  * @see GuestFS
9911  */
9912 public class %s {
9913 " jtyp jtyp;
9914
9915   List.iter (
9916     function
9917     | name, FString
9918     | name, FUUID
9919     | name, FBuffer -> pr "  public String %s;\n" name
9920     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9921     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9922     | name, FChar -> pr "  public char %s;\n" name
9923     | name, FOptPercent ->
9924         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9925         pr "  public float %s;\n" name
9926   ) cols;
9927
9928   pr "}\n"
9929
9930 and generate_java_c () =
9931   generate_header CStyle LGPLv2plus;
9932
9933   pr "\
9934 #include <stdio.h>
9935 #include <stdlib.h>
9936 #include <string.h>
9937
9938 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9939 #include \"guestfs.h\"
9940
9941 /* Note that this function returns.  The exception is not thrown
9942  * until after the wrapper function returns.
9943  */
9944 static void
9945 throw_exception (JNIEnv *env, const char *msg)
9946 {
9947   jclass cl;
9948   cl = (*env)->FindClass (env,
9949                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9950   (*env)->ThrowNew (env, cl, msg);
9951 }
9952
9953 JNIEXPORT jlong JNICALL
9954 Java_com_redhat_et_libguestfs_GuestFS__1create
9955   (JNIEnv *env, jobject obj)
9956 {
9957   guestfs_h *g;
9958
9959   g = guestfs_create ();
9960   if (g == NULL) {
9961     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9962     return 0;
9963   }
9964   guestfs_set_error_handler (g, NULL, NULL);
9965   return (jlong) (long) g;
9966 }
9967
9968 JNIEXPORT void JNICALL
9969 Java_com_redhat_et_libguestfs_GuestFS__1close
9970   (JNIEnv *env, jobject obj, jlong jg)
9971 {
9972   guestfs_h *g = (guestfs_h *) (long) jg;
9973   guestfs_close (g);
9974 }
9975
9976 ";
9977
9978   List.iter (
9979     fun (name, style, _, _, _, _, _) ->
9980       pr "JNIEXPORT ";
9981       (match fst style with
9982        | RErr -> pr "void ";
9983        | RInt _ -> pr "jint ";
9984        | RInt64 _ -> pr "jlong ";
9985        | RBool _ -> pr "jboolean ";
9986        | RConstString _ | RConstOptString _ | RString _
9987        | RBufferOut _ -> pr "jstring ";
9988        | RStruct _ | RHashtable _ ->
9989            pr "jobject ";
9990        | RStringList _ | RStructList _ ->
9991            pr "jobjectArray ";
9992       );
9993       pr "JNICALL\n";
9994       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9995       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9996       pr "\n";
9997       pr "  (JNIEnv *env, jobject obj, jlong jg";
9998       List.iter (
9999         function
10000         | Pathname n
10001         | Device n | Dev_or_Path n
10002         | String n
10003         | OptString n
10004         | FileIn n
10005         | FileOut n ->
10006             pr ", jstring j%s" n
10007         | StringList n | DeviceList n ->
10008             pr ", jobjectArray j%s" n
10009         | Bool n ->
10010             pr ", jboolean j%s" n
10011         | Int n ->
10012             pr ", jint j%s" n
10013         | Int64 n ->
10014             pr ", jlong j%s" n
10015       ) (snd style);
10016       pr ")\n";
10017       pr "{\n";
10018       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10019       let error_code, no_ret =
10020         match fst style with
10021         | RErr -> pr "  int r;\n"; "-1", ""
10022         | RBool _
10023         | RInt _ -> pr "  int r;\n"; "-1", "0"
10024         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10025         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10026         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10027         | RString _ ->
10028             pr "  jstring jr;\n";
10029             pr "  char *r;\n"; "NULL", "NULL"
10030         | RStringList _ ->
10031             pr "  jobjectArray jr;\n";
10032             pr "  int r_len;\n";
10033             pr "  jclass cl;\n";
10034             pr "  jstring jstr;\n";
10035             pr "  char **r;\n"; "NULL", "NULL"
10036         | RStruct (_, typ) ->
10037             pr "  jobject jr;\n";
10038             pr "  jclass cl;\n";
10039             pr "  jfieldID fl;\n";
10040             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10041         | RStructList (_, typ) ->
10042             pr "  jobjectArray jr;\n";
10043             pr "  jclass cl;\n";
10044             pr "  jfieldID fl;\n";
10045             pr "  jobject jfl;\n";
10046             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10047         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10048         | RBufferOut _ ->
10049             pr "  jstring jr;\n";
10050             pr "  char *r;\n";
10051             pr "  size_t size;\n";
10052             "NULL", "NULL" in
10053       List.iter (
10054         function
10055         | Pathname n
10056         | Device n | Dev_or_Path n
10057         | String n
10058         | OptString n
10059         | FileIn n
10060         | FileOut n ->
10061             pr "  const char *%s;\n" n
10062         | StringList n | DeviceList n ->
10063             pr "  int %s_len;\n" n;
10064             pr "  const char **%s;\n" n
10065         | Bool n
10066         | Int n ->
10067             pr "  int %s;\n" n
10068         | Int64 n ->
10069             pr "  int64_t %s;\n" n
10070       ) (snd style);
10071
10072       let needs_i =
10073         (match fst style with
10074          | RStringList _ | RStructList _ -> true
10075          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10076          | RConstOptString _
10077          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10078           List.exists (function
10079                        | StringList _ -> true
10080                        | DeviceList _ -> true
10081                        | _ -> false) (snd style) in
10082       if needs_i then
10083         pr "  int i;\n";
10084
10085       pr "\n";
10086
10087       (* Get the parameters. *)
10088       List.iter (
10089         function
10090         | Pathname n
10091         | Device n | Dev_or_Path n
10092         | String n
10093         | FileIn n
10094         | FileOut n ->
10095             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10096         | OptString n ->
10097             (* This is completely undocumented, but Java null becomes
10098              * a NULL parameter.
10099              *)
10100             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10101         | StringList n | DeviceList n ->
10102             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10103             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10104             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10105             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10106               n;
10107             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10108             pr "  }\n";
10109             pr "  %s[%s_len] = NULL;\n" n n;
10110         | Bool n
10111         | Int n
10112         | Int64 n ->
10113             pr "  %s = j%s;\n" n n
10114       ) (snd style);
10115
10116       (* Make the call. *)
10117       pr "  r = guestfs_%s " name;
10118       generate_c_call_args ~handle:"g" style;
10119       pr ";\n";
10120
10121       (* Release the parameters. *)
10122       List.iter (
10123         function
10124         | Pathname n
10125         | Device n | Dev_or_Path n
10126         | String n
10127         | FileIn n
10128         | FileOut n ->
10129             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10130         | OptString n ->
10131             pr "  if (j%s)\n" n;
10132             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10133         | StringList n | DeviceList n ->
10134             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10135             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10136               n;
10137             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10138             pr "  }\n";
10139             pr "  free (%s);\n" n
10140         | Bool n
10141         | Int n
10142         | Int64 n -> ()
10143       ) (snd style);
10144
10145       (* Check for errors. *)
10146       pr "  if (r == %s) {\n" error_code;
10147       pr "    throw_exception (env, guestfs_last_error (g));\n";
10148       pr "    return %s;\n" no_ret;
10149       pr "  }\n";
10150
10151       (* Return value. *)
10152       (match fst style with
10153        | RErr -> ()
10154        | RInt _ -> pr "  return (jint) r;\n"
10155        | RBool _ -> pr "  return (jboolean) r;\n"
10156        | RInt64 _ -> pr "  return (jlong) r;\n"
10157        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10158        | RConstOptString _ ->
10159            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10160        | RString _ ->
10161            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10162            pr "  free (r);\n";
10163            pr "  return jr;\n"
10164        | RStringList _ ->
10165            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10166            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10167            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10168            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10169            pr "  for (i = 0; i < r_len; ++i) {\n";
10170            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10171            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10172            pr "    free (r[i]);\n";
10173            pr "  }\n";
10174            pr "  free (r);\n";
10175            pr "  return jr;\n"
10176        | RStruct (_, typ) ->
10177            let jtyp = java_name_of_struct typ in
10178            let cols = cols_of_struct typ in
10179            generate_java_struct_return typ jtyp cols
10180        | RStructList (_, typ) ->
10181            let jtyp = java_name_of_struct typ in
10182            let cols = cols_of_struct typ in
10183            generate_java_struct_list_return typ jtyp cols
10184        | RHashtable _ ->
10185            (* XXX *)
10186            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10187            pr "  return NULL;\n"
10188        | RBufferOut _ ->
10189            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10190            pr "  free (r);\n";
10191            pr "  return jr;\n"
10192       );
10193
10194       pr "}\n";
10195       pr "\n"
10196   ) all_functions
10197
10198 and generate_java_struct_return typ jtyp cols =
10199   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10200   pr "  jr = (*env)->AllocObject (env, cl);\n";
10201   List.iter (
10202     function
10203     | name, FString ->
10204         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10205         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10206     | name, FUUID ->
10207         pr "  {\n";
10208         pr "    char s[33];\n";
10209         pr "    memcpy (s, r->%s, 32);\n" name;
10210         pr "    s[32] = 0;\n";
10211         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10212         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10213         pr "  }\n";
10214     | name, FBuffer ->
10215         pr "  {\n";
10216         pr "    int len = r->%s_len;\n" name;
10217         pr "    char s[len+1];\n";
10218         pr "    memcpy (s, r->%s, len);\n" name;
10219         pr "    s[len] = 0;\n";
10220         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10221         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10222         pr "  }\n";
10223     | name, (FBytes|FUInt64|FInt64) ->
10224         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10225         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10226     | name, (FUInt32|FInt32) ->
10227         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10228         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10229     | name, FOptPercent ->
10230         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10231         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10232     | name, FChar ->
10233         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10234         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10235   ) cols;
10236   pr "  free (r);\n";
10237   pr "  return jr;\n"
10238
10239 and generate_java_struct_list_return typ jtyp cols =
10240   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10241   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10242   pr "  for (i = 0; i < r->len; ++i) {\n";
10243   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10244   List.iter (
10245     function
10246     | name, FString ->
10247         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10248         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10249     | name, FUUID ->
10250         pr "    {\n";
10251         pr "      char s[33];\n";
10252         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10253         pr "      s[32] = 0;\n";
10254         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10255         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10256         pr "    }\n";
10257     | name, FBuffer ->
10258         pr "    {\n";
10259         pr "      int len = r->val[i].%s_len;\n" name;
10260         pr "      char s[len+1];\n";
10261         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10262         pr "      s[len] = 0;\n";
10263         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10264         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10265         pr "    }\n";
10266     | name, (FBytes|FUInt64|FInt64) ->
10267         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10268         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10269     | name, (FUInt32|FInt32) ->
10270         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10271         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10272     | name, FOptPercent ->
10273         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10274         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10275     | name, FChar ->
10276         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10277         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10278   ) cols;
10279   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10280   pr "  }\n";
10281   pr "  guestfs_free_%s_list (r);\n" typ;
10282   pr "  return jr;\n"
10283
10284 and generate_java_makefile_inc () =
10285   generate_header HashStyle GPLv2plus;
10286
10287   pr "java_built_sources = \\\n";
10288   List.iter (
10289     fun (typ, jtyp) ->
10290         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10291   ) java_structs;
10292   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10293
10294 and generate_haskell_hs () =
10295   generate_header HaskellStyle LGPLv2plus;
10296
10297   (* XXX We only know how to generate partial FFI for Haskell
10298    * at the moment.  Please help out!
10299    *)
10300   let can_generate style =
10301     match style with
10302     | RErr, _
10303     | RInt _, _
10304     | RInt64 _, _ -> true
10305     | RBool _, _
10306     | RConstString _, _
10307     | RConstOptString _, _
10308     | RString _, _
10309     | RStringList _, _
10310     | RStruct _, _
10311     | RStructList _, _
10312     | RHashtable _, _
10313     | RBufferOut _, _ -> false in
10314
10315   pr "\
10316 {-# INCLUDE <guestfs.h> #-}
10317 {-# LANGUAGE ForeignFunctionInterface #-}
10318
10319 module Guestfs (
10320   create";
10321
10322   (* List out the names of the actions we want to export. *)
10323   List.iter (
10324     fun (name, style, _, _, _, _, _) ->
10325       if can_generate style then pr ",\n  %s" name
10326   ) all_functions;
10327
10328   pr "
10329   ) where
10330
10331 -- Unfortunately some symbols duplicate ones already present
10332 -- in Prelude.  We don't know which, so we hard-code a list
10333 -- here.
10334 import Prelude hiding (truncate)
10335
10336 import Foreign
10337 import Foreign.C
10338 import Foreign.C.Types
10339 import IO
10340 import Control.Exception
10341 import Data.Typeable
10342
10343 data GuestfsS = GuestfsS            -- represents the opaque C struct
10344 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10345 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10346
10347 -- XXX define properly later XXX
10348 data PV = PV
10349 data VG = VG
10350 data LV = LV
10351 data IntBool = IntBool
10352 data Stat = Stat
10353 data StatVFS = StatVFS
10354 data Hashtable = Hashtable
10355
10356 foreign import ccall unsafe \"guestfs_create\" c_create
10357   :: IO GuestfsP
10358 foreign import ccall unsafe \"&guestfs_close\" c_close
10359   :: FunPtr (GuestfsP -> IO ())
10360 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10361   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10362
10363 create :: IO GuestfsH
10364 create = do
10365   p <- c_create
10366   c_set_error_handler p nullPtr nullPtr
10367   h <- newForeignPtr c_close p
10368   return h
10369
10370 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10371   :: GuestfsP -> IO CString
10372
10373 -- last_error :: GuestfsH -> IO (Maybe String)
10374 -- last_error h = do
10375 --   str <- withForeignPtr h (\\p -> c_last_error p)
10376 --   maybePeek peekCString str
10377
10378 last_error :: GuestfsH -> IO (String)
10379 last_error h = do
10380   str <- withForeignPtr h (\\p -> c_last_error p)
10381   if (str == nullPtr)
10382     then return \"no error\"
10383     else peekCString str
10384
10385 ";
10386
10387   (* Generate wrappers for each foreign function. *)
10388   List.iter (
10389     fun (name, style, _, _, _, _, _) ->
10390       if can_generate style then (
10391         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10392         pr "  :: ";
10393         generate_haskell_prototype ~handle:"GuestfsP" style;
10394         pr "\n";
10395         pr "\n";
10396         pr "%s :: " name;
10397         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10398         pr "\n";
10399         pr "%s %s = do\n" name
10400           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10401         pr "  r <- ";
10402         (* Convert pointer arguments using with* functions. *)
10403         List.iter (
10404           function
10405           | FileIn n
10406           | FileOut n
10407           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10408           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10409           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10410           | Bool _ | Int _ | Int64 _ -> ()
10411         ) (snd style);
10412         (* Convert integer arguments. *)
10413         let args =
10414           List.map (
10415             function
10416             | Bool n -> sprintf "(fromBool %s)" n
10417             | Int n -> sprintf "(fromIntegral %s)" n
10418             | Int64 n -> sprintf "(fromIntegral %s)" n
10419             | FileIn n | FileOut n
10420             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10421           ) (snd style) in
10422         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10423           (String.concat " " ("p" :: args));
10424         (match fst style with
10425          | RErr | RInt _ | RInt64 _ | RBool _ ->
10426              pr "  if (r == -1)\n";
10427              pr "    then do\n";
10428              pr "      err <- last_error h\n";
10429              pr "      fail err\n";
10430          | RConstString _ | RConstOptString _ | RString _
10431          | RStringList _ | RStruct _
10432          | RStructList _ | RHashtable _ | RBufferOut _ ->
10433              pr "  if (r == nullPtr)\n";
10434              pr "    then do\n";
10435              pr "      err <- last_error h\n";
10436              pr "      fail err\n";
10437         );
10438         (match fst style with
10439          | RErr ->
10440              pr "    else return ()\n"
10441          | RInt _ ->
10442              pr "    else return (fromIntegral r)\n"
10443          | RInt64 _ ->
10444              pr "    else return (fromIntegral r)\n"
10445          | RBool _ ->
10446              pr "    else return (toBool r)\n"
10447          | RConstString _
10448          | RConstOptString _
10449          | RString _
10450          | RStringList _
10451          | RStruct _
10452          | RStructList _
10453          | RHashtable _
10454          | RBufferOut _ ->
10455              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10456         );
10457         pr "\n";
10458       )
10459   ) all_functions
10460
10461 and generate_haskell_prototype ~handle ?(hs = false) style =
10462   pr "%s -> " handle;
10463   let string = if hs then "String" else "CString" in
10464   let int = if hs then "Int" else "CInt" in
10465   let bool = if hs then "Bool" else "CInt" in
10466   let int64 = if hs then "Integer" else "Int64" in
10467   List.iter (
10468     fun arg ->
10469       (match arg with
10470        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10471        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10472        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10473        | Bool _ -> pr "%s" bool
10474        | Int _ -> pr "%s" int
10475        | Int64 _ -> pr "%s" int
10476        | FileIn _ -> pr "%s" string
10477        | FileOut _ -> pr "%s" string
10478       );
10479       pr " -> ";
10480   ) (snd style);
10481   pr "IO (";
10482   (match fst style with
10483    | RErr -> if not hs then pr "CInt"
10484    | RInt _ -> pr "%s" int
10485    | RInt64 _ -> pr "%s" int64
10486    | RBool _ -> pr "%s" bool
10487    | RConstString _ -> pr "%s" string
10488    | RConstOptString _ -> pr "Maybe %s" string
10489    | RString _ -> pr "%s" string
10490    | RStringList _ -> pr "[%s]" string
10491    | RStruct (_, typ) ->
10492        let name = java_name_of_struct typ in
10493        pr "%s" name
10494    | RStructList (_, typ) ->
10495        let name = java_name_of_struct typ in
10496        pr "[%s]" name
10497    | RHashtable _ -> pr "Hashtable"
10498    | RBufferOut _ -> pr "%s" string
10499   );
10500   pr ")"
10501
10502 and generate_csharp () =
10503   generate_header CPlusPlusStyle LGPLv2plus;
10504
10505   (* XXX Make this configurable by the C# assembly users. *)
10506   let library = "libguestfs.so.0" in
10507
10508   pr "\
10509 // These C# bindings are highly experimental at present.
10510 //
10511 // Firstly they only work on Linux (ie. Mono).  In order to get them
10512 // to work on Windows (ie. .Net) you would need to port the library
10513 // itself to Windows first.
10514 //
10515 // The second issue is that some calls are known to be incorrect and
10516 // can cause Mono to segfault.  Particularly: calls which pass or
10517 // return string[], or return any structure value.  This is because
10518 // we haven't worked out the correct way to do this from C#.
10519 //
10520 // The third issue is that when compiling you get a lot of warnings.
10521 // We are not sure whether the warnings are important or not.
10522 //
10523 // Fourthly we do not routinely build or test these bindings as part
10524 // of the make && make check cycle, which means that regressions might
10525 // go unnoticed.
10526 //
10527 // Suggestions and patches are welcome.
10528
10529 // To compile:
10530 //
10531 // gmcs Libguestfs.cs
10532 // mono Libguestfs.exe
10533 //
10534 // (You'll probably want to add a Test class / static main function
10535 // otherwise this won't do anything useful).
10536
10537 using System;
10538 using System.IO;
10539 using System.Runtime.InteropServices;
10540 using System.Runtime.Serialization;
10541 using System.Collections;
10542
10543 namespace Guestfs
10544 {
10545   class Error : System.ApplicationException
10546   {
10547     public Error (string message) : base (message) {}
10548     protected Error (SerializationInfo info, StreamingContext context) {}
10549   }
10550
10551   class Guestfs
10552   {
10553     IntPtr _handle;
10554
10555     [DllImport (\"%s\")]
10556     static extern IntPtr guestfs_create ();
10557
10558     public Guestfs ()
10559     {
10560       _handle = guestfs_create ();
10561       if (_handle == IntPtr.Zero)
10562         throw new Error (\"could not create guestfs handle\");
10563     }
10564
10565     [DllImport (\"%s\")]
10566     static extern void guestfs_close (IntPtr h);
10567
10568     ~Guestfs ()
10569     {
10570       guestfs_close (_handle);
10571     }
10572
10573     [DllImport (\"%s\")]
10574     static extern string guestfs_last_error (IntPtr h);
10575
10576 " library library library;
10577
10578   (* Generate C# structure bindings.  We prefix struct names with
10579    * underscore because C# cannot have conflicting struct names and
10580    * method names (eg. "class stat" and "stat").
10581    *)
10582   List.iter (
10583     fun (typ, cols) ->
10584       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10585       pr "    public class _%s {\n" typ;
10586       List.iter (
10587         function
10588         | name, FChar -> pr "      char %s;\n" name
10589         | name, FString -> pr "      string %s;\n" name
10590         | name, FBuffer ->
10591             pr "      uint %s_len;\n" name;
10592             pr "      string %s;\n" name
10593         | name, FUUID ->
10594             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10595             pr "      string %s;\n" name
10596         | name, FUInt32 -> pr "      uint %s;\n" name
10597         | name, FInt32 -> pr "      int %s;\n" name
10598         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10599         | name, FInt64 -> pr "      long %s;\n" name
10600         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10601       ) cols;
10602       pr "    }\n";
10603       pr "\n"
10604   ) structs;
10605
10606   (* Generate C# function bindings. *)
10607   List.iter (
10608     fun (name, style, _, _, _, shortdesc, _) ->
10609       let rec csharp_return_type () =
10610         match fst style with
10611         | RErr -> "void"
10612         | RBool n -> "bool"
10613         | RInt n -> "int"
10614         | RInt64 n -> "long"
10615         | RConstString n
10616         | RConstOptString n
10617         | RString n
10618         | RBufferOut n -> "string"
10619         | RStruct (_,n) -> "_" ^ n
10620         | RHashtable n -> "Hashtable"
10621         | RStringList n -> "string[]"
10622         | RStructList (_,n) -> sprintf "_%s[]" n
10623
10624       and c_return_type () =
10625         match fst style with
10626         | RErr
10627         | RBool _
10628         | RInt _ -> "int"
10629         | RInt64 _ -> "long"
10630         | RConstString _
10631         | RConstOptString _
10632         | RString _
10633         | RBufferOut _ -> "string"
10634         | RStruct (_,n) -> "_" ^ n
10635         | RHashtable _
10636         | RStringList _ -> "string[]"
10637         | RStructList (_,n) -> sprintf "_%s[]" n
10638
10639       and c_error_comparison () =
10640         match fst style with
10641         | RErr
10642         | RBool _
10643         | RInt _
10644         | RInt64 _ -> "== -1"
10645         | RConstString _
10646         | RConstOptString _
10647         | RString _
10648         | RBufferOut _
10649         | RStruct (_,_)
10650         | RHashtable _
10651         | RStringList _
10652         | RStructList (_,_) -> "== null"
10653
10654       and generate_extern_prototype () =
10655         pr "    static extern %s guestfs_%s (IntPtr h"
10656           (c_return_type ()) name;
10657         List.iter (
10658           function
10659           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10660           | FileIn n | FileOut n ->
10661               pr ", [In] string %s" n
10662           | StringList n | DeviceList n ->
10663               pr ", [In] string[] %s" n
10664           | Bool n ->
10665               pr ", bool %s" n
10666           | Int n ->
10667               pr ", int %s" n
10668           | Int64 n ->
10669               pr ", long %s" n
10670         ) (snd style);
10671         pr ");\n"
10672
10673       and generate_public_prototype () =
10674         pr "    public %s %s (" (csharp_return_type ()) name;
10675         let comma = ref false in
10676         let next () =
10677           if !comma then pr ", ";
10678           comma := true
10679         in
10680         List.iter (
10681           function
10682           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10683           | FileIn n | FileOut n ->
10684               next (); pr "string %s" n
10685           | StringList n | DeviceList n ->
10686               next (); pr "string[] %s" n
10687           | Bool n ->
10688               next (); pr "bool %s" n
10689           | Int n ->
10690               next (); pr "int %s" n
10691           | Int64 n ->
10692               next (); pr "long %s" n
10693         ) (snd style);
10694         pr ")\n"
10695
10696       and generate_call () =
10697         pr "guestfs_%s (_handle" name;
10698         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10699         pr ");\n";
10700       in
10701
10702       pr "    [DllImport (\"%s\")]\n" library;
10703       generate_extern_prototype ();
10704       pr "\n";
10705       pr "    /// <summary>\n";
10706       pr "    /// %s\n" shortdesc;
10707       pr "    /// </summary>\n";
10708       generate_public_prototype ();
10709       pr "    {\n";
10710       pr "      %s r;\n" (c_return_type ());
10711       pr "      r = ";
10712       generate_call ();
10713       pr "      if (r %s)\n" (c_error_comparison ());
10714       pr "        throw new Error (guestfs_last_error (_handle));\n";
10715       (match fst style with
10716        | RErr -> ()
10717        | RBool _ ->
10718            pr "      return r != 0 ? true : false;\n"
10719        | RHashtable _ ->
10720            pr "      Hashtable rr = new Hashtable ();\n";
10721            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10722            pr "        rr.Add (r[i], r[i+1]);\n";
10723            pr "      return rr;\n"
10724        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10725        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10726        | RStructList _ ->
10727            pr "      return r;\n"
10728       );
10729       pr "    }\n";
10730       pr "\n";
10731   ) all_functions_sorted;
10732
10733   pr "  }
10734 }
10735 "
10736
10737 and generate_bindtests () =
10738   generate_header CStyle LGPLv2plus;
10739
10740   pr "\
10741 #include <stdio.h>
10742 #include <stdlib.h>
10743 #include <inttypes.h>
10744 #include <string.h>
10745
10746 #include \"guestfs.h\"
10747 #include \"guestfs-internal.h\"
10748 #include \"guestfs-internal-actions.h\"
10749 #include \"guestfs_protocol.h\"
10750
10751 #define error guestfs_error
10752 #define safe_calloc guestfs_safe_calloc
10753 #define safe_malloc guestfs_safe_malloc
10754
10755 static void
10756 print_strings (char *const *argv)
10757 {
10758   int argc;
10759
10760   printf (\"[\");
10761   for (argc = 0; argv[argc] != NULL; ++argc) {
10762     if (argc > 0) printf (\", \");
10763     printf (\"\\\"%%s\\\"\", argv[argc]);
10764   }
10765   printf (\"]\\n\");
10766 }
10767
10768 /* The test0 function prints its parameters to stdout. */
10769 ";
10770
10771   let test0, tests =
10772     match test_functions with
10773     | [] -> assert false
10774     | test0 :: tests -> test0, tests in
10775
10776   let () =
10777     let (name, style, _, _, _, _, _) = test0 in
10778     generate_prototype ~extern:false ~semicolon:false ~newline:true
10779       ~handle:"g" ~prefix:"guestfs__" name style;
10780     pr "{\n";
10781     List.iter (
10782       function
10783       | Pathname n
10784       | Device n | Dev_or_Path n
10785       | String n
10786       | FileIn n
10787       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10788       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10789       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10790       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10791       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10792       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10793     ) (snd style);
10794     pr "  /* Java changes stdout line buffering so we need this: */\n";
10795     pr "  fflush (stdout);\n";
10796     pr "  return 0;\n";
10797     pr "}\n";
10798     pr "\n" in
10799
10800   List.iter (
10801     fun (name, style, _, _, _, _, _) ->
10802       if String.sub name (String.length name - 3) 3 <> "err" then (
10803         pr "/* Test normal return. */\n";
10804         generate_prototype ~extern:false ~semicolon:false ~newline:true
10805           ~handle:"g" ~prefix:"guestfs__" name style;
10806         pr "{\n";
10807         (match fst style with
10808          | RErr ->
10809              pr "  return 0;\n"
10810          | RInt _ ->
10811              pr "  int r;\n";
10812              pr "  sscanf (val, \"%%d\", &r);\n";
10813              pr "  return r;\n"
10814          | RInt64 _ ->
10815              pr "  int64_t r;\n";
10816              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10817              pr "  return r;\n"
10818          | RBool _ ->
10819              pr "  return STREQ (val, \"true\");\n"
10820          | RConstString _
10821          | RConstOptString _ ->
10822              (* Can't return the input string here.  Return a static
10823               * string so we ensure we get a segfault if the caller
10824               * tries to free it.
10825               *)
10826              pr "  return \"static string\";\n"
10827          | RString _ ->
10828              pr "  return strdup (val);\n"
10829          | RStringList _ ->
10830              pr "  char **strs;\n";
10831              pr "  int n, i;\n";
10832              pr "  sscanf (val, \"%%d\", &n);\n";
10833              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10834              pr "  for (i = 0; i < n; ++i) {\n";
10835              pr "    strs[i] = safe_malloc (g, 16);\n";
10836              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10837              pr "  }\n";
10838              pr "  strs[n] = NULL;\n";
10839              pr "  return strs;\n"
10840          | RStruct (_, typ) ->
10841              pr "  struct guestfs_%s *r;\n" typ;
10842              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10843              pr "  return r;\n"
10844          | RStructList (_, typ) ->
10845              pr "  struct guestfs_%s_list *r;\n" typ;
10846              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10847              pr "  sscanf (val, \"%%d\", &r->len);\n";
10848              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10849              pr "  return r;\n"
10850          | RHashtable _ ->
10851              pr "  char **strs;\n";
10852              pr "  int n, i;\n";
10853              pr "  sscanf (val, \"%%d\", &n);\n";
10854              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10855              pr "  for (i = 0; i < n; ++i) {\n";
10856              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10857              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10858              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10859              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10860              pr "  }\n";
10861              pr "  strs[n*2] = NULL;\n";
10862              pr "  return strs;\n"
10863          | RBufferOut _ ->
10864              pr "  return strdup (val);\n"
10865         );
10866         pr "}\n";
10867         pr "\n"
10868       ) else (
10869         pr "/* Test error return. */\n";
10870         generate_prototype ~extern:false ~semicolon:false ~newline:true
10871           ~handle:"g" ~prefix:"guestfs__" name style;
10872         pr "{\n";
10873         pr "  error (g, \"error\");\n";
10874         (match fst style with
10875          | RErr | RInt _ | RInt64 _ | RBool _ ->
10876              pr "  return -1;\n"
10877          | RConstString _ | RConstOptString _
10878          | RString _ | RStringList _ | RStruct _
10879          | RStructList _
10880          | RHashtable _
10881          | RBufferOut _ ->
10882              pr "  return NULL;\n"
10883         );
10884         pr "}\n";
10885         pr "\n"
10886       )
10887   ) tests
10888
10889 and generate_ocaml_bindtests () =
10890   generate_header OCamlStyle GPLv2plus;
10891
10892   pr "\
10893 let () =
10894   let g = Guestfs.create () in
10895 ";
10896
10897   let mkargs args =
10898     String.concat " " (
10899       List.map (
10900         function
10901         | CallString s -> "\"" ^ s ^ "\""
10902         | CallOptString None -> "None"
10903         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10904         | CallStringList xs ->
10905             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10906         | CallInt i when i >= 0 -> string_of_int i
10907         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10908         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10909         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10910         | CallBool b -> string_of_bool b
10911       ) args
10912     )
10913   in
10914
10915   generate_lang_bindtests (
10916     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10917   );
10918
10919   pr "print_endline \"EOF\"\n"
10920
10921 and generate_perl_bindtests () =
10922   pr "#!/usr/bin/perl -w\n";
10923   generate_header HashStyle GPLv2plus;
10924
10925   pr "\
10926 use strict;
10927
10928 use Sys::Guestfs;
10929
10930 my $g = Sys::Guestfs->new ();
10931 ";
10932
10933   let mkargs args =
10934     String.concat ", " (
10935       List.map (
10936         function
10937         | CallString s -> "\"" ^ s ^ "\""
10938         | CallOptString None -> "undef"
10939         | CallOptString (Some s) -> sprintf "\"%s\"" s
10940         | CallStringList xs ->
10941             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10942         | CallInt i -> string_of_int i
10943         | CallInt64 i -> Int64.to_string i
10944         | CallBool b -> if b then "1" else "0"
10945       ) args
10946     )
10947   in
10948
10949   generate_lang_bindtests (
10950     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10951   );
10952
10953   pr "print \"EOF\\n\"\n"
10954
10955 and generate_python_bindtests () =
10956   generate_header HashStyle GPLv2plus;
10957
10958   pr "\
10959 import guestfs
10960
10961 g = guestfs.GuestFS ()
10962 ";
10963
10964   let mkargs args =
10965     String.concat ", " (
10966       List.map (
10967         function
10968         | CallString s -> "\"" ^ s ^ "\""
10969         | CallOptString None -> "None"
10970         | CallOptString (Some s) -> sprintf "\"%s\"" s
10971         | CallStringList xs ->
10972             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10973         | CallInt i -> string_of_int i
10974         | CallInt64 i -> Int64.to_string i
10975         | CallBool b -> if b then "1" else "0"
10976       ) args
10977     )
10978   in
10979
10980   generate_lang_bindtests (
10981     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10982   );
10983
10984   pr "print \"EOF\"\n"
10985
10986 and generate_ruby_bindtests () =
10987   generate_header HashStyle GPLv2plus;
10988
10989   pr "\
10990 require 'guestfs'
10991
10992 g = Guestfs::create()
10993 ";
10994
10995   let mkargs args =
10996     String.concat ", " (
10997       List.map (
10998         function
10999         | CallString s -> "\"" ^ s ^ "\""
11000         | CallOptString None -> "nil"
11001         | CallOptString (Some s) -> sprintf "\"%s\"" s
11002         | CallStringList xs ->
11003             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11004         | CallInt i -> string_of_int i
11005         | CallInt64 i -> Int64.to_string i
11006         | CallBool b -> string_of_bool b
11007       ) args
11008     )
11009   in
11010
11011   generate_lang_bindtests (
11012     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11013   );
11014
11015   pr "print \"EOF\\n\"\n"
11016
11017 and generate_java_bindtests () =
11018   generate_header CStyle GPLv2plus;
11019
11020   pr "\
11021 import com.redhat.et.libguestfs.*;
11022
11023 public class Bindtests {
11024     public static void main (String[] argv)
11025     {
11026         try {
11027             GuestFS g = new GuestFS ();
11028 ";
11029
11030   let mkargs args =
11031     String.concat ", " (
11032       List.map (
11033         function
11034         | CallString s -> "\"" ^ s ^ "\""
11035         | CallOptString None -> "null"
11036         | CallOptString (Some s) -> sprintf "\"%s\"" s
11037         | CallStringList xs ->
11038             "new String[]{" ^
11039               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11040         | CallInt i -> string_of_int i
11041         | CallInt64 i -> Int64.to_string i
11042         | CallBool b -> string_of_bool b
11043       ) args
11044     )
11045   in
11046
11047   generate_lang_bindtests (
11048     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11049   );
11050
11051   pr "
11052             System.out.println (\"EOF\");
11053         }
11054         catch (Exception exn) {
11055             System.err.println (exn);
11056             System.exit (1);
11057         }
11058     }
11059 }
11060 "
11061
11062 and generate_haskell_bindtests () =
11063   generate_header HaskellStyle GPLv2plus;
11064
11065   pr "\
11066 module Bindtests where
11067 import qualified Guestfs
11068
11069 main = do
11070   g <- Guestfs.create
11071 ";
11072
11073   let mkargs args =
11074     String.concat " " (
11075       List.map (
11076         function
11077         | CallString s -> "\"" ^ s ^ "\""
11078         | CallOptString None -> "Nothing"
11079         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11080         | CallStringList xs ->
11081             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11082         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11083         | CallInt i -> string_of_int i
11084         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11085         | CallInt64 i -> Int64.to_string i
11086         | CallBool true -> "True"
11087         | CallBool false -> "False"
11088       ) args
11089     )
11090   in
11091
11092   generate_lang_bindtests (
11093     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11094   );
11095
11096   pr "  putStrLn \"EOF\"\n"
11097
11098 (* Language-independent bindings tests - we do it this way to
11099  * ensure there is parity in testing bindings across all languages.
11100  *)
11101 and generate_lang_bindtests call =
11102   call "test0" [CallString "abc"; CallOptString (Some "def");
11103                 CallStringList []; CallBool false;
11104                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11105   call "test0" [CallString "abc"; CallOptString None;
11106                 CallStringList []; CallBool false;
11107                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11108   call "test0" [CallString ""; CallOptString (Some "def");
11109                 CallStringList []; CallBool false;
11110                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11111   call "test0" [CallString ""; CallOptString (Some "");
11112                 CallStringList []; CallBool false;
11113                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11114   call "test0" [CallString "abc"; CallOptString (Some "def");
11115                 CallStringList ["1"]; CallBool false;
11116                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11117   call "test0" [CallString "abc"; CallOptString (Some "def");
11118                 CallStringList ["1"; "2"]; CallBool false;
11119                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11120   call "test0" [CallString "abc"; CallOptString (Some "def");
11121                 CallStringList ["1"]; CallBool true;
11122                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11123   call "test0" [CallString "abc"; CallOptString (Some "def");
11124                 CallStringList ["1"]; CallBool false;
11125                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11126   call "test0" [CallString "abc"; CallOptString (Some "def");
11127                 CallStringList ["1"]; CallBool false;
11128                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11129   call "test0" [CallString "abc"; CallOptString (Some "def");
11130                 CallStringList ["1"]; CallBool false;
11131                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11132   call "test0" [CallString "abc"; CallOptString (Some "def");
11133                 CallStringList ["1"]; CallBool false;
11134                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11135   call "test0" [CallString "abc"; CallOptString (Some "def");
11136                 CallStringList ["1"]; CallBool false;
11137                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11138   call "test0" [CallString "abc"; CallOptString (Some "def");
11139                 CallStringList ["1"]; CallBool false;
11140                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11141
11142 (* XXX Add here tests of the return and error functions. *)
11143
11144 (* Code to generator bindings for virt-inspector.  Currently only
11145  * implemented for OCaml code (for virt-p2v 2.0).
11146  *)
11147 let rng_input = "inspector/virt-inspector.rng"
11148
11149 (* Read the input file and parse it into internal structures.  This is
11150  * by no means a complete RELAX NG parser, but is just enough to be
11151  * able to parse the specific input file.
11152  *)
11153 type rng =
11154   | Element of string * rng list        (* <element name=name/> *)
11155   | Attribute of string * rng list        (* <attribute name=name/> *)
11156   | Interleave of rng list                (* <interleave/> *)
11157   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11158   | OneOrMore of rng                        (* <oneOrMore/> *)
11159   | Optional of rng                        (* <optional/> *)
11160   | Choice of string list                (* <choice><value/>*</choice> *)
11161   | Value of string                        (* <value>str</value> *)
11162   | Text                                (* <text/> *)
11163
11164 let rec string_of_rng = function
11165   | Element (name, xs) ->
11166       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11167   | Attribute (name, xs) ->
11168       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11169   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11170   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11171   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11172   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11173   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11174   | Value value -> "Value \"" ^ value ^ "\""
11175   | Text -> "Text"
11176
11177 and string_of_rng_list xs =
11178   String.concat ", " (List.map string_of_rng xs)
11179
11180 let rec parse_rng ?defines context = function
11181   | [] -> []
11182   | Xml.Element ("element", ["name", name], children) :: rest ->
11183       Element (name, parse_rng ?defines context children)
11184       :: parse_rng ?defines context rest
11185   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11186       Attribute (name, parse_rng ?defines context children)
11187       :: parse_rng ?defines context rest
11188   | Xml.Element ("interleave", [], children) :: rest ->
11189       Interleave (parse_rng ?defines context children)
11190       :: parse_rng ?defines context rest
11191   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11192       let rng = parse_rng ?defines context [child] in
11193       (match rng with
11194        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11195        | _ ->
11196            failwithf "%s: <zeroOrMore> contains more than one child element"
11197              context
11198       )
11199   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11200       let rng = parse_rng ?defines context [child] in
11201       (match rng with
11202        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11203        | _ ->
11204            failwithf "%s: <oneOrMore> contains more than one child element"
11205              context
11206       )
11207   | Xml.Element ("optional", [], [child]) :: rest ->
11208       let rng = parse_rng ?defines context [child] in
11209       (match rng with
11210        | [child] -> Optional child :: parse_rng ?defines context rest
11211        | _ ->
11212            failwithf "%s: <optional> contains more than one child element"
11213              context
11214       )
11215   | Xml.Element ("choice", [], children) :: rest ->
11216       let values = List.map (
11217         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11218         | _ ->
11219             failwithf "%s: can't handle anything except <value> in <choice>"
11220               context
11221       ) children in
11222       Choice values
11223       :: parse_rng ?defines context rest
11224   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11225       Value value :: parse_rng ?defines context rest
11226   | Xml.Element ("text", [], []) :: rest ->
11227       Text :: parse_rng ?defines context rest
11228   | Xml.Element ("ref", ["name", name], []) :: rest ->
11229       (* Look up the reference.  Because of limitations in this parser,
11230        * we can't handle arbitrarily nested <ref> yet.  You can only
11231        * use <ref> from inside <start>.
11232        *)
11233       (match defines with
11234        | None ->
11235            failwithf "%s: contains <ref>, but no refs are defined yet" context
11236        | Some map ->
11237            let rng = StringMap.find name map in
11238            rng @ parse_rng ?defines context rest
11239       )
11240   | x :: _ ->
11241       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11242
11243 let grammar =
11244   let xml = Xml.parse_file rng_input in
11245   match xml with
11246   | Xml.Element ("grammar", _,
11247                  Xml.Element ("start", _, gram) :: defines) ->
11248       (* The <define/> elements are referenced in the <start> section,
11249        * so build a map of those first.
11250        *)
11251       let defines = List.fold_left (
11252         fun map ->
11253           function Xml.Element ("define", ["name", name], defn) ->
11254             StringMap.add name defn map
11255           | _ ->
11256               failwithf "%s: expected <define name=name/>" rng_input
11257       ) StringMap.empty defines in
11258       let defines = StringMap.mapi parse_rng defines in
11259
11260       (* Parse the <start> clause, passing the defines. *)
11261       parse_rng ~defines "<start>" gram
11262   | _ ->
11263       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11264         rng_input
11265
11266 let name_of_field = function
11267   | Element (name, _) | Attribute (name, _)
11268   | ZeroOrMore (Element (name, _))
11269   | OneOrMore (Element (name, _))
11270   | Optional (Element (name, _)) -> name
11271   | Optional (Attribute (name, _)) -> name
11272   | Text -> (* an unnamed field in an element *)
11273       "data"
11274   | rng ->
11275       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11276
11277 (* At the moment this function only generates OCaml types.  However we
11278  * should parameterize it later so it can generate types/structs in a
11279  * variety of languages.
11280  *)
11281 let generate_types xs =
11282   (* A simple type is one that can be printed out directly, eg.
11283    * "string option".  A complex type is one which has a name and has
11284    * to be defined via another toplevel definition, eg. a struct.
11285    *
11286    * generate_type generates code for either simple or complex types.
11287    * In the simple case, it returns the string ("string option").  In
11288    * the complex case, it returns the name ("mountpoint").  In the
11289    * complex case it has to print out the definition before returning,
11290    * so it should only be called when we are at the beginning of a
11291    * new line (BOL context).
11292    *)
11293   let rec generate_type = function
11294     | Text ->                                (* string *)
11295         "string", true
11296     | Choice values ->                        (* [`val1|`val2|...] *)
11297         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11298     | ZeroOrMore rng ->                        (* <rng> list *)
11299         let t, is_simple = generate_type rng in
11300         t ^ " list (* 0 or more *)", is_simple
11301     | OneOrMore rng ->                        (* <rng> list *)
11302         let t, is_simple = generate_type rng in
11303         t ^ " list (* 1 or more *)", is_simple
11304                                         (* virt-inspector hack: bool *)
11305     | Optional (Attribute (name, [Value "1"])) ->
11306         "bool", true
11307     | Optional rng ->                        (* <rng> list *)
11308         let t, is_simple = generate_type rng in
11309         t ^ " option", is_simple
11310                                         (* type name = { fields ... } *)
11311     | Element (name, fields) when is_attrs_interleave fields ->
11312         generate_type_struct name (get_attrs_interleave fields)
11313     | Element (name, [field])                (* type name = field *)
11314     | Attribute (name, [field]) ->
11315         let t, is_simple = generate_type field in
11316         if is_simple then (t, true)
11317         else (
11318           pr "type %s = %s\n" name t;
11319           name, false
11320         )
11321     | Element (name, fields) ->              (* type name = { fields ... } *)
11322         generate_type_struct name fields
11323     | rng ->
11324         failwithf "generate_type failed at: %s" (string_of_rng rng)
11325
11326   and is_attrs_interleave = function
11327     | [Interleave _] -> true
11328     | Attribute _ :: fields -> is_attrs_interleave fields
11329     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11330     | _ -> false
11331
11332   and get_attrs_interleave = function
11333     | [Interleave fields] -> fields
11334     | ((Attribute _) as field) :: fields
11335     | ((Optional (Attribute _)) as field) :: fields ->
11336         field :: get_attrs_interleave fields
11337     | _ -> assert false
11338
11339   and generate_types xs =
11340     List.iter (fun x -> ignore (generate_type x)) xs
11341
11342   and generate_type_struct name fields =
11343     (* Calculate the types of the fields first.  We have to do this
11344      * before printing anything so we are still in BOL context.
11345      *)
11346     let types = List.map fst (List.map generate_type fields) in
11347
11348     (* Special case of a struct containing just a string and another
11349      * field.  Turn it into an assoc list.
11350      *)
11351     match types with
11352     | ["string"; other] ->
11353         let fname1, fname2 =
11354           match fields with
11355           | [f1; f2] -> name_of_field f1, name_of_field f2
11356           | _ -> assert false in
11357         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11358         name, false
11359
11360     | types ->
11361         pr "type %s = {\n" name;
11362         List.iter (
11363           fun (field, ftype) ->
11364             let fname = name_of_field field in
11365             pr "  %s_%s : %s;\n" name fname ftype
11366         ) (List.combine fields types);
11367         pr "}\n";
11368         (* Return the name of this type, and
11369          * false because it's not a simple type.
11370          *)
11371         name, false
11372   in
11373
11374   generate_types xs
11375
11376 let generate_parsers xs =
11377   (* As for generate_type above, generate_parser makes a parser for
11378    * some type, and returns the name of the parser it has generated.
11379    * Because it (may) need to print something, it should always be
11380    * called in BOL context.
11381    *)
11382   let rec generate_parser = function
11383     | Text ->                                (* string *)
11384         "string_child_or_empty"
11385     | Choice values ->                        (* [`val1|`val2|...] *)
11386         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11387           (String.concat "|"
11388              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11389     | ZeroOrMore rng ->                        (* <rng> list *)
11390         let pa = generate_parser rng in
11391         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11392     | OneOrMore rng ->                        (* <rng> list *)
11393         let pa = generate_parser rng in
11394         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11395                                         (* virt-inspector hack: bool *)
11396     | Optional (Attribute (name, [Value "1"])) ->
11397         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11398     | Optional rng ->                        (* <rng> list *)
11399         let pa = generate_parser rng in
11400         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11401                                         (* type name = { fields ... } *)
11402     | Element (name, fields) when is_attrs_interleave fields ->
11403         generate_parser_struct name (get_attrs_interleave fields)
11404     | Element (name, [field]) ->        (* type name = field *)
11405         let pa = generate_parser field in
11406         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11407         pr "let %s =\n" parser_name;
11408         pr "  %s\n" pa;
11409         pr "let parse_%s = %s\n" name parser_name;
11410         parser_name
11411     | Attribute (name, [field]) ->
11412         let pa = generate_parser field in
11413         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11414         pr "let %s =\n" parser_name;
11415         pr "  %s\n" pa;
11416         pr "let parse_%s = %s\n" name parser_name;
11417         parser_name
11418     | Element (name, fields) ->              (* type name = { fields ... } *)
11419         generate_parser_struct name ([], fields)
11420     | rng ->
11421         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11422
11423   and is_attrs_interleave = function
11424     | [Interleave _] -> true
11425     | Attribute _ :: fields -> is_attrs_interleave fields
11426     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11427     | _ -> false
11428
11429   and get_attrs_interleave = function
11430     | [Interleave fields] -> [], fields
11431     | ((Attribute _) as field) :: fields
11432     | ((Optional (Attribute _)) as field) :: fields ->
11433         let attrs, interleaves = get_attrs_interleave fields in
11434         (field :: attrs), interleaves
11435     | _ -> assert false
11436
11437   and generate_parsers xs =
11438     List.iter (fun x -> ignore (generate_parser x)) xs
11439
11440   and generate_parser_struct name (attrs, interleaves) =
11441     (* Generate parsers for the fields first.  We have to do this
11442      * before printing anything so we are still in BOL context.
11443      *)
11444     let fields = attrs @ interleaves in
11445     let pas = List.map generate_parser fields in
11446
11447     (* Generate an intermediate tuple from all the fields first.
11448      * If the type is just a string + another field, then we will
11449      * return this directly, otherwise it is turned into a record.
11450      *
11451      * RELAX NG note: This code treats <interleave> and plain lists of
11452      * fields the same.  In other words, it doesn't bother enforcing
11453      * any ordering of fields in the XML.
11454      *)
11455     pr "let parse_%s x =\n" name;
11456     pr "  let t = (\n    ";
11457     let comma = ref false in
11458     List.iter (
11459       fun x ->
11460         if !comma then pr ",\n    ";
11461         comma := true;
11462         match x with
11463         | Optional (Attribute (fname, [field])), pa ->
11464             pr "%s x" pa
11465         | Optional (Element (fname, [field])), pa ->
11466             pr "%s (optional_child %S x)" pa fname
11467         | Attribute (fname, [Text]), _ ->
11468             pr "attribute %S x" fname
11469         | (ZeroOrMore _ | OneOrMore _), pa ->
11470             pr "%s x" pa
11471         | Text, pa ->
11472             pr "%s x" pa
11473         | (field, pa) ->
11474             let fname = name_of_field field in
11475             pr "%s (child %S x)" pa fname
11476     ) (List.combine fields pas);
11477     pr "\n  ) in\n";
11478
11479     (match fields with
11480      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11481          pr "  t\n"
11482
11483      | _ ->
11484          pr "  (Obj.magic t : %s)\n" name
11485 (*
11486          List.iter (
11487            function
11488            | (Optional (Attribute (fname, [field])), pa) ->
11489                pr "  %s_%s =\n" name fname;
11490                pr "    %s x;\n" pa
11491            | (Optional (Element (fname, [field])), pa) ->
11492                pr "  %s_%s =\n" name fname;
11493                pr "    (let x = optional_child %S x in\n" fname;
11494                pr "     %s x);\n" pa
11495            | (field, pa) ->
11496                let fname = name_of_field field in
11497                pr "  %s_%s =\n" name fname;
11498                pr "    (let x = child %S x in\n" fname;
11499                pr "     %s x);\n" pa
11500          ) (List.combine fields pas);
11501          pr "}\n"
11502 *)
11503     );
11504     sprintf "parse_%s" name
11505   in
11506
11507   generate_parsers xs
11508
11509 (* Generate ocaml/guestfs_inspector.mli. *)
11510 let generate_ocaml_inspector_mli () =
11511   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11512
11513   pr "\
11514 (** This is an OCaml language binding to the external [virt-inspector]
11515     program.
11516
11517     For more information, please read the man page [virt-inspector(1)].
11518 *)
11519
11520 ";
11521
11522   generate_types grammar;
11523   pr "(** The nested information returned from the {!inspect} function. *)\n";
11524   pr "\n";
11525
11526   pr "\
11527 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11528 (** To inspect a libvirt domain called [name], pass a singleton
11529     list: [inspect [name]].  When using libvirt only, you may
11530     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11531
11532     To inspect a disk image or images, pass a list of the filenames
11533     of the disk images: [inspect filenames]
11534
11535     This function inspects the given guest or disk images and
11536     returns a list of operating system(s) found and a large amount
11537     of information about them.  In the vast majority of cases,
11538     a virtual machine only contains a single operating system.
11539
11540     If the optional [~xml] parameter is given, then this function
11541     skips running the external virt-inspector program and just
11542     parses the given XML directly (which is expected to be XML
11543     produced from a previous run of virt-inspector).  The list of
11544     names and connect URI are ignored in this case.
11545
11546     This function can throw a wide variety of exceptions, for example
11547     if the external virt-inspector program cannot be found, or if
11548     it doesn't generate valid XML.
11549 *)
11550 "
11551
11552 (* Generate ocaml/guestfs_inspector.ml. *)
11553 let generate_ocaml_inspector_ml () =
11554   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11555
11556   pr "open Unix\n";
11557   pr "\n";
11558
11559   generate_types grammar;
11560   pr "\n";
11561
11562   pr "\
11563 (* Misc functions which are used by the parser code below. *)
11564 let first_child = function
11565   | Xml.Element (_, _, c::_) -> c
11566   | Xml.Element (name, _, []) ->
11567       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11568   | Xml.PCData str ->
11569       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11570
11571 let string_child_or_empty = function
11572   | Xml.Element (_, _, [Xml.PCData s]) -> s
11573   | Xml.Element (_, _, []) -> \"\"
11574   | Xml.Element (x, _, _) ->
11575       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11576                 x ^ \" instead\")
11577   | Xml.PCData str ->
11578       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11579
11580 let optional_child name xml =
11581   let children = Xml.children xml in
11582   try
11583     Some (List.find (function
11584                      | Xml.Element (n, _, _) when n = name -> true
11585                      | _ -> false) children)
11586   with
11587     Not_found -> None
11588
11589 let child name xml =
11590   match optional_child name xml with
11591   | Some c -> c
11592   | None ->
11593       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11594
11595 let attribute name xml =
11596   try Xml.attrib xml name
11597   with Xml.No_attribute _ ->
11598     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11599
11600 ";
11601
11602   generate_parsers grammar;
11603   pr "\n";
11604
11605   pr "\
11606 (* Run external virt-inspector, then use parser to parse the XML. *)
11607 let inspect ?connect ?xml names =
11608   let xml =
11609     match xml with
11610     | None ->
11611         if names = [] then invalid_arg \"inspect: no names given\";
11612         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11613           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11614           names in
11615         let cmd = List.map Filename.quote cmd in
11616         let cmd = String.concat \" \" cmd in
11617         let chan = open_process_in cmd in
11618         let xml = Xml.parse_in chan in
11619         (match close_process_in chan with
11620          | WEXITED 0 -> ()
11621          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11622          | WSIGNALED i | WSTOPPED i ->
11623              failwith (\"external virt-inspector command died or stopped on sig \" ^
11624                        string_of_int i)
11625         );
11626         xml
11627     | Some doc ->
11628         Xml.parse_string doc in
11629   parse_operatingsystems xml
11630 "
11631
11632 (* This is used to generate the src/MAX_PROC_NR file which
11633  * contains the maximum procedure number, a surrogate for the
11634  * ABI version number.  See src/Makefile.am for the details.
11635  *)
11636 and generate_max_proc_nr () =
11637   let proc_nrs = List.map (
11638     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11639   ) daemon_functions in
11640
11641   let max_proc_nr = List.fold_left max 0 proc_nrs in
11642
11643   pr "%d\n" max_proc_nr
11644
11645 let output_to filename k =
11646   let filename_new = filename ^ ".new" in
11647   chan := open_out filename_new;
11648   k ();
11649   close_out !chan;
11650   chan := Pervasives.stdout;
11651
11652   (* Is the new file different from the current file? *)
11653   if Sys.file_exists filename && files_equal filename filename_new then
11654     unlink filename_new                 (* same, so skip it *)
11655   else (
11656     (* different, overwrite old one *)
11657     (try chmod filename 0o644 with Unix_error _ -> ());
11658     rename filename_new filename;
11659     chmod filename 0o444;
11660     printf "written %s\n%!" filename;
11661   )
11662
11663 let perror msg = function
11664   | Unix_error (err, _, _) ->
11665       eprintf "%s: %s\n" msg (error_message err)
11666   | exn ->
11667       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11668
11669 (* Main program. *)
11670 let () =
11671   let lock_fd =
11672     try openfile "HACKING" [O_RDWR] 0
11673     with
11674     | Unix_error (ENOENT, _, _) ->
11675         eprintf "\
11676 You are probably running this from the wrong directory.
11677 Run it from the top source directory using the command
11678   src/generator.ml
11679 ";
11680         exit 1
11681     | exn ->
11682         perror "open: HACKING" exn;
11683         exit 1 in
11684
11685   (* Acquire a lock so parallel builds won't try to run the generator
11686    * twice at the same time.  Subsequent builds will wait for the first
11687    * one to finish.  Note the lock is released implicitly when the
11688    * program exits.
11689    *)
11690   (try lockf lock_fd F_LOCK 1
11691    with exn ->
11692      perror "lock: HACKING" exn;
11693      exit 1);
11694
11695   check_functions ();
11696
11697   output_to "src/guestfs_protocol.x" generate_xdr;
11698   output_to "src/guestfs-structs.h" generate_structs_h;
11699   output_to "src/guestfs-actions.h" generate_actions_h;
11700   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11701   output_to "src/guestfs-actions.c" generate_client_actions;
11702   output_to "src/guestfs-bindtests.c" generate_bindtests;
11703   output_to "src/guestfs-structs.pod" generate_structs_pod;
11704   output_to "src/guestfs-actions.pod" generate_actions_pod;
11705   output_to "src/guestfs-availability.pod" generate_availability_pod;
11706   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11707   output_to "src/libguestfs.syms" generate_linker_script;
11708   output_to "daemon/actions.h" generate_daemon_actions_h;
11709   output_to "daemon/stubs.c" generate_daemon_actions;
11710   output_to "daemon/names.c" generate_daemon_names;
11711   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11712   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11713   output_to "capitests/tests.c" generate_tests;
11714   output_to "fish/cmds.c" generate_fish_cmds;
11715   output_to "fish/completion.c" generate_fish_completion;
11716   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11717   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11718   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11719   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11720   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11721   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11722   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11723   output_to "perl/Guestfs.xs" generate_perl_xs;
11724   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11725   output_to "perl/bindtests.pl" generate_perl_bindtests;
11726   output_to "python/guestfs-py.c" generate_python_c;
11727   output_to "python/guestfs.py" generate_python_py;
11728   output_to "python/bindtests.py" generate_python_bindtests;
11729   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11730   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11731   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11732
11733   List.iter (
11734     fun (typ, jtyp) ->
11735       let cols = cols_of_struct typ in
11736       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11737       output_to filename (generate_java_struct jtyp cols);
11738   ) java_structs;
11739
11740   output_to "java/Makefile.inc" generate_java_makefile_inc;
11741   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11742   output_to "java/Bindtests.java" generate_java_bindtests;
11743   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11744   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11745   output_to "csharp/Libguestfs.cs" generate_csharp;
11746
11747   (* Always generate this file last, and unconditionally.  It's used
11748    * by the Makefile to know when we must re-run the generator.
11749    *)
11750   let chan = open_out "src/stamp-generator" in
11751   fprintf chan "1\n";
11752   close_out chan;
11753
11754   printf "generated %d lines of code\n" !lines