Add version numbers to Perl modules (RHBZ#521674).
[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   | FishOutput of fish_output_t (* how to display output in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 and fish_output_t =
191   | FishOutputOctal       (* for int return, print in octal *)
192   | FishOutputHexadecimal (* for int return, print in hex *)
193
194 (* You can supply zero or as many tests as you want per API call.
195  *
196  * Note that the test environment has 3 block devices, of size 500MB,
197  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
198  * a fourth ISO block device with some known files on it (/dev/sdd).
199  *
200  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
201  * Number of cylinders was 63 for IDE emulated disks with precisely
202  * the same size.  How exactly this is calculated is a mystery.
203  *
204  * The ISO block device (/dev/sdd) comes from images/test.iso.
205  *
206  * To be able to run the tests in a reasonable amount of time,
207  * the virtual machine and block devices are reused between tests.
208  * So don't try testing kill_subprocess :-x
209  *
210  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
211  *
212  * Don't assume anything about the previous contents of the block
213  * devices.  Use 'Init*' to create some initial scenarios.
214  *
215  * You can add a prerequisite clause to any individual test.  This
216  * is a run-time check, which, if it fails, causes the test to be
217  * skipped.  Useful if testing a command which might not work on
218  * all variations of libguestfs builds.  A test that has prerequisite
219  * of 'Always' is run unconditionally.
220  *
221  * In addition, packagers can skip individual tests by setting the
222  * environment variables:     eg:
223  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
224  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
225  *)
226 type tests = (test_init * test_prereq * test) list
227 and test =
228     (* Run the command sequence and just expect nothing to fail. *)
229   | TestRun of seq
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the string.
233      *)
234   | TestOutput of seq * string
235
236     (* Run the command sequence and expect the output of the final
237      * command to be the list of strings.
238      *)
239   | TestOutputList of seq * string list
240
241     (* Run the command sequence and expect the output of the final
242      * command to be the list of block devices (could be either
243      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
244      * character of each string).
245      *)
246   | TestOutputListOfDevices of seq * string list
247
248     (* Run the command sequence and expect the output of the final
249      * command to be the integer.
250      *)
251   | TestOutputInt of seq * int
252
253     (* Run the command sequence and expect the output of the final
254      * command to be <op> <int>, eg. ">=", "1".
255      *)
256   | TestOutputIntOp of seq * string * int
257
258     (* Run the command sequence and expect the output of the final
259      * command to be a true value (!= 0 or != NULL).
260      *)
261   | TestOutputTrue of seq
262
263     (* Run the command sequence and expect the output of the final
264      * command to be a false value (== 0 or == NULL, but not an error).
265      *)
266   | TestOutputFalse of seq
267
268     (* Run the command sequence and expect the output of the final
269      * command to be a list of the given length (but don't care about
270      * content).
271      *)
272   | TestOutputLength of seq * int
273
274     (* Run the command sequence and expect the output of the final
275      * command to be a buffer (RBufferOut), ie. string + size.
276      *)
277   | TestOutputBuffer of seq * string
278
279     (* Run the command sequence and expect the output of the final
280      * command to be a structure.
281      *)
282   | TestOutputStruct of seq * test_field_compare list
283
284     (* Run the command sequence and expect the final command (only)
285      * to fail.
286      *)
287   | TestLastFail of seq
288
289 and test_field_compare =
290   | CompareWithInt of string * int
291   | CompareWithIntOp of string * string * int
292   | CompareWithString of string * string
293   | CompareFieldsIntEq of string * string
294   | CompareFieldsStrEq of string * string
295
296 (* Test prerequisites. *)
297 and test_prereq =
298     (* Test always runs. *)
299   | Always
300
301     (* Test is currently disabled - eg. it fails, or it tests some
302      * unimplemented feature.
303      *)
304   | Disabled
305
306     (* 'string' is some C code (a function body) that should return
307      * true or false.  The test will run if the code returns true.
308      *)
309   | If of string
310
311     (* As for 'If' but the test runs _unless_ the code returns true. *)
312   | Unless of string
313
314 (* Some initial scenarios for testing. *)
315 and test_init =
316     (* Do nothing, block devices could contain random stuff including
317      * LVM PVs, and some filesystems might be mounted.  This is usually
318      * a bad idea.
319      *)
320   | InitNone
321
322     (* Block devices are empty and no filesystems are mounted. *)
323   | InitEmpty
324
325     (* /dev/sda contains a single partition /dev/sda1, with random
326      * content.  /dev/sdb and /dev/sdc may have random content.
327      * No LVM.
328      *)
329   | InitPartition
330
331     (* /dev/sda contains a single partition /dev/sda1, which is formatted
332      * as ext2, empty [except for lost+found] and mounted on /.
333      * /dev/sdb and /dev/sdc may have random content.
334      * No LVM.
335      *)
336   | InitBasicFS
337
338     (* /dev/sda:
339      *   /dev/sda1 (is a PV):
340      *     /dev/VG/LV (size 8MB):
341      *       formatted as ext2, empty [except for lost+found], mounted on /
342      * /dev/sdb and /dev/sdc may have random content.
343      *)
344   | InitBasicFSonLVM
345
346     (* /dev/sdd (the ISO, see images/ directory in source)
347      * is mounted on /
348      *)
349   | InitISOFS
350
351 (* Sequence of commands for testing. *)
352 and seq = cmd list
353 and cmd = string list
354
355 (* Note about long descriptions: When referring to another
356  * action, use the format C<guestfs_other> (ie. the full name of
357  * the C function).  This will be replaced as appropriate in other
358  * language bindings.
359  *
360  * Apart from that, long descriptions are just perldoc paragraphs.
361  *)
362
363 (* Generate a random UUID (used in tests). *)
364 let uuidgen () =
365   let chan = open_process_in "uuidgen" in
366   let uuid = input_line chan in
367   (match close_process_in chan with
368    | WEXITED 0 -> ()
369    | WEXITED _ ->
370        failwith "uuidgen: process exited with non-zero status"
371    | WSIGNALED _ | WSTOPPED _ ->
372        failwith "uuidgen: process signalled or stopped by signal"
373   );
374   uuid
375
376 (* These test functions are used in the language binding tests. *)
377
378 let test_all_args = [
379   String "str";
380   OptString "optstr";
381   StringList "strlist";
382   Bool "b";
383   Int "integer";
384   Int64 "integer64";
385   FileIn "filein";
386   FileOut "fileout";
387 ]
388
389 let test_all_rets = [
390   (* except for RErr, which is tested thoroughly elsewhere *)
391   "test0rint",         RInt "valout";
392   "test0rint64",       RInt64 "valout";
393   "test0rbool",        RBool "valout";
394   "test0rconststring", RConstString "valout";
395   "test0rconstoptstring", RConstOptString "valout";
396   "test0rstring",      RString "valout";
397   "test0rstringlist",  RStringList "valout";
398   "test0rstruct",      RStruct ("valout", "lvm_pv");
399   "test0rstructlist",  RStructList ("valout", "lvm_pv");
400   "test0rhashtable",   RHashtable "valout";
401 ]
402
403 let test_functions = [
404   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
405    [],
406    "internal test function - do not use",
407    "\
408 This is an internal test function which is used to test whether
409 the automatically generated bindings can handle every possible
410 parameter type correctly.
411
412 It echos the contents of each parameter to stdout.
413
414 You probably don't want to call this function.");
415 ] @ List.flatten (
416   List.map (
417     fun (name, ret) ->
418       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
419         [],
420         "internal test function - do not use",
421         "\
422 This is an internal test function which is used to test whether
423 the automatically generated bindings can handle every possible
424 return type correctly.
425
426 It converts string C<val> to the return type.
427
428 You probably don't want to call this function.");
429        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
430         [],
431         "internal test function - do not use",
432         "\
433 This is an internal test function which is used to test whether
434 the automatically generated bindings can handle every possible
435 return type correctly.
436
437 This function always returns an error.
438
439 You probably don't want to call this function.")]
440   ) test_all_rets
441 )
442
443 (* non_daemon_functions are any functions which don't get processed
444  * in the daemon, eg. functions for setting and getting local
445  * configuration values.
446  *)
447
448 let non_daemon_functions = test_functions @ [
449   ("launch", (RErr, []), -1, [FishAlias "run"],
450    [],
451    "launch the qemu subprocess",
452    "\
453 Internally libguestfs is implemented by running a virtual machine
454 using L<qemu(1)>.
455
456 You should call this after configuring the handle
457 (eg. adding drives) but before performing any actions.");
458
459   ("wait_ready", (RErr, []), -1, [NotInFish],
460    [],
461    "wait until the qemu subprocess launches (no op)",
462    "\
463 This function is a no op.
464
465 In versions of the API E<lt> 1.0.71 you had to call this function
466 just after calling C<guestfs_launch> to wait for the launch
467 to complete.  However this is no longer necessary because
468 C<guestfs_launch> now does the waiting.
469
470 If you see any calls to this function in code then you can just
471 remove them, unless you want to retain compatibility with older
472 versions of the API.");
473
474   ("kill_subprocess", (RErr, []), -1, [],
475    [],
476    "kill the qemu subprocess",
477    "\
478 This kills the qemu subprocess.  You should never need to call this.");
479
480   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
481    [],
482    "add an image to examine or modify",
483    "\
484 This function adds a virtual machine disk image C<filename> to the
485 guest.  The first time you call this function, the disk appears as IDE
486 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
487 so on.
488
489 You don't necessarily need to be root when using libguestfs.  However
490 you obviously do need sufficient permissions to access the filename
491 for whatever operations you want to perform (ie. read access if you
492 just want to read the image or write access if you want to modify the
493 image).
494
495 This is equivalent to the qemu parameter
496 C<-drive file=filename,cache=off,if=...>.
497
498 C<cache=off> is omitted in cases where it is not supported by
499 the underlying filesystem.
500
501 C<if=...> is set at compile time by the configuration option
502 C<./configure --with-drive-if=...>.  In the rare case where you
503 might need to change this at run time, use C<guestfs_add_drive_with_if>
504 or C<guestfs_add_drive_ro_with_if>.
505
506 Note that this call checks for the existence of C<filename>.  This
507 stops you from specifying other types of drive which are supported
508 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
509 the general C<guestfs_config> call instead.");
510
511   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
512    [],
513    "add a CD-ROM disk image to examine",
514    "\
515 This function adds a virtual CD-ROM disk image to the guest.
516
517 This is equivalent to the qemu parameter C<-cdrom filename>.
518
519 Notes:
520
521 =over 4
522
523 =item *
524
525 This call checks for the existence of C<filename>.  This
526 stops you from specifying other types of drive which are supported
527 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
528 the general C<guestfs_config> call instead.
529
530 =item *
531
532 If you just want to add an ISO file (often you use this as an
533 efficient way to transfer large files into the guest), then you
534 should probably use C<guestfs_add_drive_ro> instead.
535
536 =back");
537
538   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
539    [],
540    "add a drive in snapshot mode (read-only)",
541    "\
542 This adds a drive in snapshot mode, making it effectively
543 read-only.
544
545 Note that writes to the device are allowed, and will be seen for
546 the duration of the guestfs handle, but they are written
547 to a temporary file which is discarded as soon as the guestfs
548 handle is closed.  We don't currently have any method to enable
549 changes to be committed, although qemu can support this.
550
551 This is equivalent to the qemu parameter
552 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
553
554 C<if=...> is set at compile time by the configuration option
555 C<./configure --with-drive-if=...>.  In the rare case where you
556 might need to change this at run time, use C<guestfs_add_drive_with_if>
557 or C<guestfs_add_drive_ro_with_if>.
558
559 C<readonly=on> is only added where qemu supports this option.
560
561 Note that this call checks for the existence of C<filename>.  This
562 stops you from specifying other types of drive which are supported
563 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
564 the general C<guestfs_config> call instead.");
565
566   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
567    [],
568    "add qemu parameters",
569    "\
570 This can be used to add arbitrary qemu command line parameters
571 of the form C<-param value>.  Actually it's not quite arbitrary - we
572 prevent you from setting some parameters which would interfere with
573 parameters that we use.
574
575 The first character of C<param> string must be a C<-> (dash).
576
577 C<value> can be NULL.");
578
579   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
580    [],
581    "set the qemu binary",
582    "\
583 Set the qemu binary that we will use.
584
585 The default is chosen when the library was compiled by the
586 configure script.
587
588 You can also override this by setting the C<LIBGUESTFS_QEMU>
589 environment variable.
590
591 Setting C<qemu> to C<NULL> restores the default qemu binary.
592
593 Note that you should call this function as early as possible
594 after creating the handle.  This is because some pre-launch
595 operations depend on testing qemu features (by running C<qemu -help>).
596 If the qemu binary changes, we don't retest features, and
597 so you might see inconsistent results.  Using the environment
598 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
599 the qemu binary at the same time as the handle is created.");
600
601   ("get_qemu", (RConstString "qemu", []), -1, [],
602    [InitNone, Always, TestRun (
603       [["get_qemu"]])],
604    "get the qemu binary",
605    "\
606 Return the current qemu binary.
607
608 This is always non-NULL.  If it wasn't set already, then this will
609 return the default qemu binary name.");
610
611   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
612    [],
613    "set the search path",
614    "\
615 Set the path that libguestfs searches for kernel and initrd.img.
616
617 The default is C<$libdir/guestfs> unless overridden by setting
618 C<LIBGUESTFS_PATH> environment variable.
619
620 Setting C<path> to C<NULL> restores the default path.");
621
622   ("get_path", (RConstString "path", []), -1, [],
623    [InitNone, Always, TestRun (
624       [["get_path"]])],
625    "get the search path",
626    "\
627 Return the current search path.
628
629 This is always non-NULL.  If it wasn't set already, then this will
630 return the default path.");
631
632   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
633    [],
634    "add options to kernel command line",
635    "\
636 This function is used to add additional options to the
637 guest kernel command line.
638
639 The default is C<NULL> unless overridden by setting
640 C<LIBGUESTFS_APPEND> environment variable.
641
642 Setting C<append> to C<NULL> means I<no> additional options
643 are passed (libguestfs always adds a few of its own).");
644
645   ("get_append", (RConstOptString "append", []), -1, [],
646    (* This cannot be tested with the current framework.  The
647     * function can return NULL in normal operations, which the
648     * test framework interprets as an error.
649     *)
650    [],
651    "get the additional kernel options",
652    "\
653 Return the additional kernel options which are added to the
654 guest kernel command line.
655
656 If C<NULL> then no options are added.");
657
658   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
659    [],
660    "set autosync mode",
661    "\
662 If C<autosync> is true, this enables autosync.  Libguestfs will make a
663 best effort attempt to run C<guestfs_umount_all> followed by
664 C<guestfs_sync> when the handle is closed
665 (also if the program exits without closing handles).
666
667 This is disabled by default (except in guestfish where it is
668 enabled by default).");
669
670   ("get_autosync", (RBool "autosync", []), -1, [],
671    [InitNone, Always, TestRun (
672       [["get_autosync"]])],
673    "get autosync mode",
674    "\
675 Get the autosync flag.");
676
677   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
678    [],
679    "set verbose mode",
680    "\
681 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
682
683 Verbose messages are disabled unless the environment variable
684 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
685
686   ("get_verbose", (RBool "verbose", []), -1, [],
687    [],
688    "get verbose mode",
689    "\
690 This returns the verbose messages flag.");
691
692   ("is_ready", (RBool "ready", []), -1, [],
693    [InitNone, Always, TestOutputTrue (
694       [["is_ready"]])],
695    "is ready to accept commands",
696    "\
697 This returns true iff this handle is ready to accept commands
698 (in the C<READY> state).
699
700 For more information on states, see L<guestfs(3)>.");
701
702   ("is_config", (RBool "config", []), -1, [],
703    [InitNone, Always, TestOutputFalse (
704       [["is_config"]])],
705    "is in configuration state",
706    "\
707 This returns true iff this handle is being configured
708 (in the C<CONFIG> state).
709
710 For more information on states, see L<guestfs(3)>.");
711
712   ("is_launching", (RBool "launching", []), -1, [],
713    [InitNone, Always, TestOutputFalse (
714       [["is_launching"]])],
715    "is launching subprocess",
716    "\
717 This returns true iff this handle is launching the subprocess
718 (in the C<LAUNCHING> state).
719
720 For more information on states, see L<guestfs(3)>.");
721
722   ("is_busy", (RBool "busy", []), -1, [],
723    [InitNone, Always, TestOutputFalse (
724       [["is_busy"]])],
725    "is busy processing a command",
726    "\
727 This returns true iff this handle is busy processing a command
728 (in the C<BUSY> state).
729
730 For more information on states, see L<guestfs(3)>.");
731
732   ("get_state", (RInt "state", []), -1, [],
733    [],
734    "get the current state",
735    "\
736 This returns the current state as an opaque integer.  This is
737 only useful for printing debug and internal error messages.
738
739 For more information on states, see L<guestfs(3)>.");
740
741   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
742    [InitNone, Always, TestOutputInt (
743       [["set_memsize"; "500"];
744        ["get_memsize"]], 500)],
745    "set memory allocated to the qemu subprocess",
746    "\
747 This sets the memory size in megabytes allocated to the
748 qemu subprocess.  This only has any effect if called before
749 C<guestfs_launch>.
750
751 You can also change this by setting the environment
752 variable C<LIBGUESTFS_MEMSIZE> before the handle is
753 created.
754
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
757
758   ("get_memsize", (RInt "memsize", []), -1, [],
759    [InitNone, Always, TestOutputIntOp (
760       [["get_memsize"]], ">=", 256)],
761    "get memory allocated to the qemu subprocess",
762    "\
763 This gets the memory size in megabytes allocated to the
764 qemu subprocess.
765
766 If C<guestfs_set_memsize> was not called
767 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
768 then this returns the compiled-in default value for memsize.
769
770 For more information on the architecture of libguestfs,
771 see L<guestfs(3)>.");
772
773   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
774    [InitNone, Always, TestOutputIntOp (
775       [["get_pid"]], ">=", 1)],
776    "get PID of qemu subprocess",
777    "\
778 Return the process ID of the qemu subprocess.  If there is no
779 qemu subprocess, then this will return an error.
780
781 This is an internal call used for debugging and testing.");
782
783   ("version", (RStruct ("version", "version"), []), -1, [],
784    [InitNone, Always, TestOutputStruct (
785       [["version"]], [CompareWithInt ("major", 1)])],
786    "get the library version number",
787    "\
788 Return the libguestfs version number that the program is linked
789 against.
790
791 Note that because of dynamic linking this is not necessarily
792 the version of libguestfs that you compiled against.  You can
793 compile the program, and then at runtime dynamically link
794 against a completely different C<libguestfs.so> library.
795
796 This call was added in version C<1.0.58>.  In previous
797 versions of libguestfs there was no way to get the version
798 number.  From C code you can use ELF weak linking tricks to find out if
799 this symbol exists (if it doesn't, then it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 I<Note:> Don't use this call to test for availability
811 of features.  Distro backports makes this unreliable.  Use
812 C<guestfs_available> instead.");
813
814   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
815    [InitNone, Always, TestOutputTrue (
816       [["set_selinux"; "true"];
817        ["get_selinux"]])],
818    "set SELinux enabled or disabled at appliance boot",
819    "\
820 This sets the selinux flag that is passed to the appliance
821 at boot time.  The default is C<selinux=0> (disabled).
822
823 Note that if SELinux is enabled, it is always in
824 Permissive mode (C<enforcing=0>).
825
826 For more information on the architecture of libguestfs,
827 see L<guestfs(3)>.");
828
829   ("get_selinux", (RBool "selinux", []), -1, [],
830    [],
831    "get SELinux enabled flag",
832    "\
833 This returns the current setting of the selinux flag which
834 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
835
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
838
839   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
840    [InitNone, Always, TestOutputFalse (
841       [["set_trace"; "false"];
842        ["get_trace"]])],
843    "enable or disable command traces",
844    "\
845 If the command trace flag is set to 1, then commands are
846 printed on stdout before they are executed in a format
847 which is very similar to the one used by guestfish.  In
848 other words, you can run a program with this enabled, and
849 you will get out a script which you can feed to guestfish
850 to perform the same set of actions.
851
852 If you want to trace C API calls into libguestfs (and
853 other libraries) then possibly a better way is to use
854 the external ltrace(1) command.
855
856 Command traces are disabled unless the environment variable
857 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858
859   ("get_trace", (RBool "trace", []), -1, [],
860    [],
861    "get command trace enabled flag",
862    "\
863 Return the command trace flag.");
864
865   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
866    [InitNone, Always, TestOutputFalse (
867       [["set_direct"; "false"];
868        ["get_direct"]])],
869    "enable or disable direct appliance mode",
870    "\
871 If the direct appliance mode flag is enabled, then stdin and
872 stdout are passed directly through to the appliance once it
873 is launched.
874
875 One consequence of this is that log messages aren't caught
876 by the library and handled by C<guestfs_set_log_message_callback>,
877 but go straight to stdout.
878
879 You probably don't want to use this unless you know what you
880 are doing.
881
882 The default is disabled.");
883
884   ("get_direct", (RBool "direct", []), -1, [],
885    [],
886    "get direct appliance mode flag",
887    "\
888 Return the direct appliance mode flag.");
889
890   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
891    [InitNone, Always, TestOutputTrue (
892       [["set_recovery_proc"; "true"];
893        ["get_recovery_proc"]])],
894    "enable or disable the recovery process",
895    "\
896 If this is called with the parameter C<false> then
897 C<guestfs_launch> does not create a recovery process.  The
898 purpose of the recovery process is to stop runaway qemu
899 processes in the case where the main program aborts abruptly.
900
901 This only has any effect if called before C<guestfs_launch>,
902 and the default is true.
903
904 About the only time when you would want to disable this is
905 if the main process will fork itself into the background
906 (\"daemonize\" itself).  In this case the recovery process
907 thinks that the main program has disappeared and so kills
908 qemu, which is not very helpful.");
909
910   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911    [],
912    "get recovery process enabled flag",
913    "\
914 Return the recovery process enabled flag.");
915
916   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917    [],
918    "add a drive specifying the QEMU block emulation to use",
919    "\
920 This is the same as C<guestfs_add_drive> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
922
923   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive read-only specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive_ro> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930 ]
931
932 (* daemon_functions are any functions which cause some action
933  * to take place in the daemon.
934  *)
935
936 let daemon_functions = [
937   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
938    [InitEmpty, Always, TestOutput (
939       [["part_disk"; "/dev/sda"; "mbr"];
940        ["mkfs"; "ext2"; "/dev/sda1"];
941        ["mount"; "/dev/sda1"; "/"];
942        ["write_file"; "/new"; "new file contents"; "0"];
943        ["cat"; "/new"]], "new file contents")],
944    "mount a guest disk at a position in the filesystem",
945    "\
946 Mount a guest disk at a position in the filesystem.  Block devices
947 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
948 the guest.  If those block devices contain partitions, they will have
949 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
950 names can be used.
951
952 The rules are the same as for L<mount(2)>:  A filesystem must
953 first be mounted on C</> before others can be mounted.  Other
954 filesystems can only be mounted on directories which already
955 exist.
956
957 The mounted filesystem is writable, if we have sufficient permissions
958 on the underlying device.
959
960 B<Important note:>
961 When you use this call, the filesystem options C<sync> and C<noatime>
962 are set implicitly.  This was originally done because we thought it
963 would improve reliability, but it turns out that I<-o sync> has a
964 very large negative performance impact and negligible effect on
965 reliability.  Therefore we recommend that you avoid using
966 C<guestfs_mount> in any code that needs performance, and instead
967 use C<guestfs_mount_options> (use an empty string for the first
968 parameter if you don't want any options).");
969
970   ("sync", (RErr, []), 2, [],
971    [ InitEmpty, Always, TestRun [["sync"]]],
972    "sync disks, writes are flushed through to the disk image",
973    "\
974 This syncs the disk, so that any writes are flushed through to the
975 underlying disk image.
976
977 You should always call this if you have modified a disk image, before
978 closing the handle.");
979
980   ("touch", (RErr, [Pathname "path"]), 3, [],
981    [InitBasicFS, Always, TestOutputTrue (
982       [["touch"; "/new"];
983        ["exists"; "/new"]])],
984    "update file timestamps or create a new file",
985    "\
986 Touch acts like the L<touch(1)> command.  It can be used to
987 update the timestamps on a file, or, if the file does not exist,
988 to create a new zero-length file.");
989
990   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
991    [InitISOFS, Always, TestOutput (
992       [["cat"; "/known-2"]], "abcdef\n")],
993    "list the contents of a file",
994    "\
995 Return the contents of the file named C<path>.
996
997 Note that this function cannot correctly handle binary files
998 (specifically, files containing C<\\0> character which is treated
999 as end of string).  For those you need to use the C<guestfs_read_file>
1000 or C<guestfs_download> functions which have a more complex interface.");
1001
1002   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1003    [], (* XXX Tricky to test because it depends on the exact format
1004         * of the 'ls -l' command, which changes between F10 and F11.
1005         *)
1006    "list the files in a directory (long format)",
1007    "\
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd) in the format of 'ls -la'.
1010
1011 This command is mostly useful for interactive sessions.  It
1012 is I<not> intended that you try to parse the output string.");
1013
1014   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1015    [InitBasicFS, Always, TestOutputList (
1016       [["touch"; "/new"];
1017        ["touch"; "/newer"];
1018        ["touch"; "/newest"];
1019        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1020    "list the files in a directory",
1021    "\
1022 List the files in C<directory> (relative to the root directory,
1023 there is no cwd).  The '.' and '..' entries are not returned, but
1024 hidden files are shown.
1025
1026 This command is mostly useful for interactive sessions.  Programs
1027 should probably use C<guestfs_readdir> instead.");
1028
1029   ("list_devices", (RStringList "devices", []), 7, [],
1030    [InitEmpty, Always, TestOutputListOfDevices (
1031       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1032    "list the block devices",
1033    "\
1034 List all the block devices.
1035
1036 The full block device names are returned, eg. C</dev/sda>");
1037
1038   ("list_partitions", (RStringList "partitions", []), 8, [],
1039    [InitBasicFS, Always, TestOutputListOfDevices (
1040       [["list_partitions"]], ["/dev/sda1"]);
1041     InitEmpty, Always, TestOutputListOfDevices (
1042       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1043        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1044    "list the partitions",
1045    "\
1046 List all the partitions detected on all block devices.
1047
1048 The full partition device names are returned, eg. C</dev/sda1>
1049
1050 This does not return logical volumes.  For that you will need to
1051 call C<guestfs_lvs>.");
1052
1053   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1054    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1055       [["pvs"]], ["/dev/sda1"]);
1056     InitEmpty, Always, TestOutputListOfDevices (
1057       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1058        ["pvcreate"; "/dev/sda1"];
1059        ["pvcreate"; "/dev/sda2"];
1060        ["pvcreate"; "/dev/sda3"];
1061        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1062    "list the LVM physical volumes (PVs)",
1063    "\
1064 List all the physical volumes detected.  This is the equivalent
1065 of the L<pvs(8)> command.
1066
1067 This returns a list of just the device names that contain
1068 PVs (eg. C</dev/sda2>).
1069
1070 See also C<guestfs_pvs_full>.");
1071
1072   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1073    [InitBasicFSonLVM, Always, TestOutputList (
1074       [["vgs"]], ["VG"]);
1075     InitEmpty, Always, TestOutputList (
1076       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1077        ["pvcreate"; "/dev/sda1"];
1078        ["pvcreate"; "/dev/sda2"];
1079        ["pvcreate"; "/dev/sda3"];
1080        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1081        ["vgcreate"; "VG2"; "/dev/sda3"];
1082        ["vgs"]], ["VG1"; "VG2"])],
1083    "list the LVM volume groups (VGs)",
1084    "\
1085 List all the volumes groups detected.  This is the equivalent
1086 of the L<vgs(8)> command.
1087
1088 This returns a list of just the volume group names that were
1089 detected (eg. C<VolGroup00>).
1090
1091 See also C<guestfs_vgs_full>.");
1092
1093   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1094    [InitBasicFSonLVM, Always, TestOutputList (
1095       [["lvs"]], ["/dev/VG/LV"]);
1096     InitEmpty, Always, TestOutputList (
1097       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1098        ["pvcreate"; "/dev/sda1"];
1099        ["pvcreate"; "/dev/sda2"];
1100        ["pvcreate"; "/dev/sda3"];
1101        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1102        ["vgcreate"; "VG2"; "/dev/sda3"];
1103        ["lvcreate"; "LV1"; "VG1"; "50"];
1104        ["lvcreate"; "LV2"; "VG1"; "50"];
1105        ["lvcreate"; "LV3"; "VG2"; "50"];
1106        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1107    "list the LVM logical volumes (LVs)",
1108    "\
1109 List all the logical volumes detected.  This is the equivalent
1110 of the L<lvs(8)> command.
1111
1112 This returns a list of the logical volume device names
1113 (eg. C</dev/VolGroup00/LogVol00>).
1114
1115 See also C<guestfs_lvs_full>.");
1116
1117   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1118    [], (* XXX how to test? *)
1119    "list the LVM physical volumes (PVs)",
1120    "\
1121 List all the physical volumes detected.  This is the equivalent
1122 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1123
1124   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1125    [], (* XXX how to test? *)
1126    "list the LVM volume groups (VGs)",
1127    "\
1128 List all the volumes groups detected.  This is the equivalent
1129 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1130
1131   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1132    [], (* XXX how to test? *)
1133    "list the LVM logical volumes (LVs)",
1134    "\
1135 List all the logical volumes detected.  This is the equivalent
1136 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1137
1138   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1139    [InitISOFS, Always, TestOutputList (
1140       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1141     InitISOFS, Always, TestOutputList (
1142       [["read_lines"; "/empty"]], [])],
1143    "read file as lines",
1144    "\
1145 Return the contents of the file named C<path>.
1146
1147 The file contents are returned as a list of lines.  Trailing
1148 C<LF> and C<CRLF> character sequences are I<not> returned.
1149
1150 Note that this function cannot correctly handle binary files
1151 (specifically, files containing C<\\0> character which is treated
1152 as end of line).  For those you need to use the C<guestfs_read_file>
1153 function which has a more complex interface.");
1154
1155   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1156    [], (* XXX Augeas code needs tests. *)
1157    "create a new Augeas handle",
1158    "\
1159 Create a new Augeas handle for editing configuration files.
1160 If there was any previous Augeas handle associated with this
1161 guestfs session, then it is closed.
1162
1163 You must call this before using any other C<guestfs_aug_*>
1164 commands.
1165
1166 C<root> is the filesystem root.  C<root> must not be NULL,
1167 use C</> instead.
1168
1169 The flags are the same as the flags defined in
1170 E<lt>augeas.hE<gt>, the logical I<or> of the following
1171 integers:
1172
1173 =over 4
1174
1175 =item C<AUG_SAVE_BACKUP> = 1
1176
1177 Keep the original file with a C<.augsave> extension.
1178
1179 =item C<AUG_SAVE_NEWFILE> = 2
1180
1181 Save changes into a file with extension C<.augnew>, and
1182 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1183
1184 =item C<AUG_TYPE_CHECK> = 4
1185
1186 Typecheck lenses (can be expensive).
1187
1188 =item C<AUG_NO_STDINC> = 8
1189
1190 Do not use standard load path for modules.
1191
1192 =item C<AUG_SAVE_NOOP> = 16
1193
1194 Make save a no-op, just record what would have been changed.
1195
1196 =item C<AUG_NO_LOAD> = 32
1197
1198 Do not load the tree in C<guestfs_aug_init>.
1199
1200 =back
1201
1202 To close the handle, you can call C<guestfs_aug_close>.
1203
1204 To find out more about Augeas, see L<http://augeas.net/>.");
1205
1206   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1207    [], (* XXX Augeas code needs tests. *)
1208    "close the current Augeas handle",
1209    "\
1210 Close the current Augeas handle and free up any resources
1211 used by it.  After calling this, you have to call
1212 C<guestfs_aug_init> again before you can use any other
1213 Augeas functions.");
1214
1215   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas variable",
1218    "\
1219 Defines an Augeas variable C<name> whose value is the result
1220 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1221 undefined.
1222
1223 On success this returns the number of nodes in C<expr>, or
1224 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225
1226   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "define an Augeas node",
1229    "\
1230 Defines a variable C<name> whose value is the result of
1231 evaluating C<expr>.
1232
1233 If C<expr> evaluates to an empty nodeset, a node is created,
1234 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1235 C<name> will be the nodeset containing that single node.
1236
1237 On success this returns a pair containing the
1238 number of nodes in the nodeset, and a boolean flag
1239 if a node was created.");
1240
1241   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1242    [], (* XXX Augeas code needs tests. *)
1243    "look up the value of an Augeas path",
1244    "\
1245 Look up the value associated with C<path>.  If C<path>
1246 matches exactly one node, the C<value> is returned.");
1247
1248   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "set Augeas path to value",
1251    "\
1252 Set the value associated with C<path> to C<val>.
1253
1254 In the Augeas API, it is possible to clear a node by setting
1255 the value to NULL.  Due to an oversight in the libguestfs API
1256 you cannot do that with this call.  Instead you must use the
1257 C<guestfs_aug_clear> call.");
1258
1259   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1260    [], (* XXX Augeas code needs tests. *)
1261    "insert a sibling Augeas node",
1262    "\
1263 Create a new sibling C<label> for C<path>, inserting it into
1264 the tree before or after C<path> (depending on the boolean
1265 flag C<before>).
1266
1267 C<path> must match exactly one existing node in the tree, and
1268 C<label> must be a label, ie. not contain C</>, C<*> or end
1269 with a bracketed index C<[N]>.");
1270
1271   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "remove an Augeas path",
1274    "\
1275 Remove C<path> and all of its children.
1276
1277 On success this returns the number of entries which were removed.");
1278
1279   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "move Augeas node",
1282    "\
1283 Move the node C<src> to C<dest>.  C<src> must match exactly
1284 one node.  C<dest> is overwritten if it exists.");
1285
1286   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "return Augeas nodes which match augpath",
1289    "\
1290 Returns a list of paths which match the path expression C<path>.
1291 The returned paths are sufficiently qualified so that they match
1292 exactly one node in the current tree.");
1293
1294   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "write all pending Augeas changes to disk",
1297    "\
1298 This writes all pending changes to disk.
1299
1300 The flags which were passed to C<guestfs_aug_init> affect exactly
1301 how files are saved.");
1302
1303   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1304    [], (* XXX Augeas code needs tests. *)
1305    "load files into the tree",
1306    "\
1307 Load files into the tree.
1308
1309 See C<aug_load> in the Augeas documentation for the full gory
1310 details.");
1311
1312   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1313    [], (* XXX Augeas code needs tests. *)
1314    "list Augeas nodes under augpath",
1315    "\
1316 This is just a shortcut for listing C<guestfs_aug_match>
1317 C<path/*> and sorting the resulting nodes into alphabetical order.");
1318
1319   ("rm", (RErr, [Pathname "path"]), 29, [],
1320    [InitBasicFS, Always, TestRun
1321       [["touch"; "/new"];
1322        ["rm"; "/new"]];
1323     InitBasicFS, Always, TestLastFail
1324       [["rm"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["mkdir"; "/new"];
1327        ["rm"; "/new"]]],
1328    "remove a file",
1329    "\
1330 Remove the single file C<path>.");
1331
1332   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1333    [InitBasicFS, Always, TestRun
1334       [["mkdir"; "/new"];
1335        ["rmdir"; "/new"]];
1336     InitBasicFS, Always, TestLastFail
1337       [["rmdir"; "/new"]];
1338     InitBasicFS, Always, TestLastFail
1339       [["touch"; "/new"];
1340        ["rmdir"; "/new"]]],
1341    "remove a directory",
1342    "\
1343 Remove the single directory C<path>.");
1344
1345   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1346    [InitBasicFS, Always, TestOutputFalse
1347       [["mkdir"; "/new"];
1348        ["mkdir"; "/new/foo"];
1349        ["touch"; "/new/foo/bar"];
1350        ["rm_rf"; "/new"];
1351        ["exists"; "/new"]]],
1352    "remove a file or directory recursively",
1353    "\
1354 Remove the file or directory C<path>, recursively removing the
1355 contents if its a directory.  This is like the C<rm -rf> shell
1356 command.");
1357
1358   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1359    [InitBasicFS, Always, TestOutputTrue
1360       [["mkdir"; "/new"];
1361        ["is_dir"; "/new"]];
1362     InitBasicFS, Always, TestLastFail
1363       [["mkdir"; "/new/foo/bar"]]],
1364    "create a directory",
1365    "\
1366 Create a directory named C<path>.");
1367
1368   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new/foo/bar"]];
1372     InitBasicFS, Always, TestOutputTrue
1373       [["mkdir_p"; "/new/foo/bar"];
1374        ["is_dir"; "/new/foo"]];
1375     InitBasicFS, Always, TestOutputTrue
1376       [["mkdir_p"; "/new/foo/bar"];
1377        ["is_dir"; "/new"]];
1378     (* Regression tests for RHBZ#503133: *)
1379     InitBasicFS, Always, TestRun
1380       [["mkdir"; "/new"];
1381        ["mkdir_p"; "/new"]];
1382     InitBasicFS, Always, TestLastFail
1383       [["touch"; "/new"];
1384        ["mkdir_p"; "/new"]]],
1385    "create a directory and parents",
1386    "\
1387 Create a directory named C<path>, creating any parent directories
1388 as necessary.  This is like the C<mkdir -p> shell command.");
1389
1390   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1391    [], (* XXX Need stat command to test *)
1392    "change file mode",
1393    "\
1394 Change the mode (permissions) of C<path> to C<mode>.  Only
1395 numeric modes are supported.
1396
1397 I<Note>: When using this command from guestfish, C<mode>
1398 by default would be decimal, unless you prefix it with
1399 C<0> to get octal, ie. use C<0700> not C<700>.
1400
1401 The mode actually set is affected by the umask.");
1402
1403   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1404    [], (* XXX Need stat command to test *)
1405    "change file owner and group",
1406    "\
1407 Change the file owner to C<owner> and group to C<group>.
1408
1409 Only numeric uid and gid are supported.  If you want to use
1410 names, you will need to locate and parse the password file
1411 yourself (Augeas support makes this relatively easy).");
1412
1413   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1414    [InitISOFS, Always, TestOutputTrue (
1415       [["exists"; "/empty"]]);
1416     InitISOFS, Always, TestOutputTrue (
1417       [["exists"; "/directory"]])],
1418    "test if file or directory exists",
1419    "\
1420 This returns C<true> if and only if there is a file, directory
1421 (or anything) with the given C<path> name.
1422
1423 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1424
1425   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1426    [InitISOFS, Always, TestOutputTrue (
1427       [["is_file"; "/known-1"]]);
1428     InitISOFS, Always, TestOutputFalse (
1429       [["is_file"; "/directory"]])],
1430    "test if file exists",
1431    "\
1432 This returns C<true> if and only if there is a file
1433 with the given C<path> name.  Note that it returns false for
1434 other objects like directories.
1435
1436 See also C<guestfs_stat>.");
1437
1438   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1439    [InitISOFS, Always, TestOutputFalse (
1440       [["is_dir"; "/known-3"]]);
1441     InitISOFS, Always, TestOutputTrue (
1442       [["is_dir"; "/directory"]])],
1443    "test if file exists",
1444    "\
1445 This returns C<true> if and only if there is a directory
1446 with the given C<path> name.  Note that it returns false for
1447 other objects like files.
1448
1449 See also C<guestfs_stat>.");
1450
1451   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1452    [InitEmpty, Always, TestOutputListOfDevices (
1453       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454        ["pvcreate"; "/dev/sda1"];
1455        ["pvcreate"; "/dev/sda2"];
1456        ["pvcreate"; "/dev/sda3"];
1457        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1458    "create an LVM physical volume",
1459    "\
1460 This creates an LVM physical volume on the named C<device>,
1461 where C<device> should usually be a partition name such
1462 as C</dev/sda1>.");
1463
1464   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1465    [InitEmpty, Always, TestOutputList (
1466       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467        ["pvcreate"; "/dev/sda1"];
1468        ["pvcreate"; "/dev/sda2"];
1469        ["pvcreate"; "/dev/sda3"];
1470        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1471        ["vgcreate"; "VG2"; "/dev/sda3"];
1472        ["vgs"]], ["VG1"; "VG2"])],
1473    "create an LVM volume group",
1474    "\
1475 This creates an LVM volume group called C<volgroup>
1476 from the non-empty list of physical volumes C<physvols>.");
1477
1478   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1479    [InitEmpty, Always, TestOutputList (
1480       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1481        ["pvcreate"; "/dev/sda1"];
1482        ["pvcreate"; "/dev/sda2"];
1483        ["pvcreate"; "/dev/sda3"];
1484        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1485        ["vgcreate"; "VG2"; "/dev/sda3"];
1486        ["lvcreate"; "LV1"; "VG1"; "50"];
1487        ["lvcreate"; "LV2"; "VG1"; "50"];
1488        ["lvcreate"; "LV3"; "VG2"; "50"];
1489        ["lvcreate"; "LV4"; "VG2"; "50"];
1490        ["lvcreate"; "LV5"; "VG2"; "50"];
1491        ["lvs"]],
1492       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1493        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1494    "create an LVM logical volume",
1495    "\
1496 This creates an LVM logical volume called C<logvol>
1497 on the volume group C<volgroup>, with C<size> megabytes.");
1498
1499   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1500    [InitEmpty, Always, TestOutput (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount_options"; ""; "/dev/sda1"; "/"];
1504        ["write_file"; "/new"; "new file contents"; "0"];
1505        ["cat"; "/new"]], "new file contents")],
1506    "make a filesystem",
1507    "\
1508 This creates a filesystem on C<device> (usually a partition
1509 or LVM logical volume).  The filesystem type is C<fstype>, for
1510 example C<ext3>.");
1511
1512   ("sfdisk", (RErr, [Device "device";
1513                      Int "cyls"; Int "heads"; Int "sectors";
1514                      StringList "lines"]), 43, [DangerWillRobinson],
1515    [],
1516    "create partitions on a block device",
1517    "\
1518 This is a direct interface to the L<sfdisk(8)> program for creating
1519 partitions on block devices.
1520
1521 C<device> should be a block device, for example C</dev/sda>.
1522
1523 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1524 and sectors on the device, which are passed directly to sfdisk as
1525 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1526 of these, then the corresponding parameter is omitted.  Usually for
1527 'large' disks, you can just pass C<0> for these, but for small
1528 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1529 out the right geometry and you will need to tell it.
1530
1531 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1532 information refer to the L<sfdisk(8)> manpage.
1533
1534 To create a single partition occupying the whole disk, you would
1535 pass C<lines> as a single element list, when the single element being
1536 the string C<,> (comma).
1537
1538 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1539 C<guestfs_part_init>");
1540
1541   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1542    [InitBasicFS, Always, TestOutput (
1543       [["write_file"; "/new"; "new file contents"; "0"];
1544        ["cat"; "/new"]], "new file contents");
1545     InitBasicFS, Always, TestOutput (
1546       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1547        ["cat"; "/new"]], "\nnew file contents\n");
1548     InitBasicFS, Always, TestOutput (
1549       [["write_file"; "/new"; "\n\n"; "0"];
1550        ["cat"; "/new"]], "\n\n");
1551     InitBasicFS, Always, TestOutput (
1552       [["write_file"; "/new"; ""; "0"];
1553        ["cat"; "/new"]], "");
1554     InitBasicFS, Always, TestOutput (
1555       [["write_file"; "/new"; "\n\n\n"; "0"];
1556        ["cat"; "/new"]], "\n\n\n");
1557     InitBasicFS, Always, TestOutput (
1558       [["write_file"; "/new"; "\n"; "0"];
1559        ["cat"; "/new"]], "\n")],
1560    "create a file",
1561    "\
1562 This call creates a file called C<path>.  The contents of the
1563 file is the string C<content> (which can contain any 8 bit data),
1564 with length C<size>.
1565
1566 As a special case, if C<size> is C<0>
1567 then the length is calculated using C<strlen> (so in this case
1568 the content cannot contain embedded ASCII NULs).
1569
1570 I<NB.> Owing to a bug, writing content containing ASCII NUL
1571 characters does I<not> work, even if the length is specified.
1572 We hope to resolve this bug in a future version.  In the meantime
1573 use C<guestfs_upload>.");
1574
1575   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1576    [InitEmpty, Always, TestOutputListOfDevices (
1577       [["part_disk"; "/dev/sda"; "mbr"];
1578        ["mkfs"; "ext2"; "/dev/sda1"];
1579        ["mount_options"; ""; "/dev/sda1"; "/"];
1580        ["mounts"]], ["/dev/sda1"]);
1581     InitEmpty, Always, TestOutputList (
1582       [["part_disk"; "/dev/sda"; "mbr"];
1583        ["mkfs"; "ext2"; "/dev/sda1"];
1584        ["mount_options"; ""; "/dev/sda1"; "/"];
1585        ["umount"; "/"];
1586        ["mounts"]], [])],
1587    "unmount a filesystem",
1588    "\
1589 This unmounts the given filesystem.  The filesystem may be
1590 specified either by its mountpoint (path) or the device which
1591 contains the filesystem.");
1592
1593   ("mounts", (RStringList "devices", []), 46, [],
1594    [InitBasicFS, Always, TestOutputListOfDevices (
1595       [["mounts"]], ["/dev/sda1"])],
1596    "show mounted filesystems",
1597    "\
1598 This returns the list of currently mounted filesystems.  It returns
1599 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1600
1601 Some internal mounts are not shown.
1602
1603 See also: C<guestfs_mountpoints>");
1604
1605   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1606    [InitBasicFS, Always, TestOutputList (
1607       [["umount_all"];
1608        ["mounts"]], []);
1609     (* check that umount_all can unmount nested mounts correctly: *)
1610     InitEmpty, Always, TestOutputList (
1611       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1612        ["mkfs"; "ext2"; "/dev/sda1"];
1613        ["mkfs"; "ext2"; "/dev/sda2"];
1614        ["mkfs"; "ext2"; "/dev/sda3"];
1615        ["mount_options"; ""; "/dev/sda1"; "/"];
1616        ["mkdir"; "/mp1"];
1617        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1618        ["mkdir"; "/mp1/mp2"];
1619        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1620        ["mkdir"; "/mp1/mp2/mp3"];
1621        ["umount_all"];
1622        ["mounts"]], [])],
1623    "unmount all filesystems",
1624    "\
1625 This unmounts all mounted filesystems.
1626
1627 Some internal mounts are not unmounted by this call.");
1628
1629   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1630    [],
1631    "remove all LVM LVs, VGs and PVs",
1632    "\
1633 This command removes all LVM logical volumes, volume groups
1634 and physical volumes.");
1635
1636   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1637    [InitISOFS, Always, TestOutput (
1638       [["file"; "/empty"]], "empty");
1639     InitISOFS, Always, TestOutput (
1640       [["file"; "/known-1"]], "ASCII text");
1641     InitISOFS, Always, TestLastFail (
1642       [["file"; "/notexists"]])],
1643    "determine file type",
1644    "\
1645 This call uses the standard L<file(1)> command to determine
1646 the type or contents of the file.  This also works on devices,
1647 for example to find out whether a partition contains a filesystem.
1648
1649 This call will also transparently look inside various types
1650 of compressed file.
1651
1652 The exact command which runs is C<file -zbsL path>.  Note in
1653 particular that the filename is not prepended to the output
1654 (the C<-b> option).");
1655
1656   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1657    [InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 1"]], "Result1");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 2"]], "Result2\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 3"]], "\nResult3");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 4"]], "\nResult4\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 5"]], "\nResult5\n\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 7"]], "");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 8"]], "\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 9"]], "\n\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1697     InitBasicFS, Always, TestOutput (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1701     InitBasicFS, Always, TestLastFail (
1702       [["upload"; "test-command"; "/test-command"];
1703        ["chmod"; "0o755"; "/test-command"];
1704        ["command"; "/test-command"]])],
1705    "run a command from the guest filesystem",
1706    "\
1707 This call runs a command from the guest filesystem.  The
1708 filesystem must be mounted, and must contain a compatible
1709 operating system (ie. something Linux, with the same
1710 or compatible processor architecture).
1711
1712 The single parameter is an argv-style list of arguments.
1713 The first element is the name of the program to run.
1714 Subsequent elements are parameters.  The list must be
1715 non-empty (ie. must contain a program name).  Note that
1716 the command runs directly, and is I<not> invoked via
1717 the shell (see C<guestfs_sh>).
1718
1719 The return value is anything printed to I<stdout> by
1720 the command.
1721
1722 If the command returns a non-zero exit status, then
1723 this function returns an error message.  The error message
1724 string is the content of I<stderr> from the command.
1725
1726 The C<$PATH> environment variable will contain at least
1727 C</usr/bin> and C</bin>.  If you require a program from
1728 another location, you should provide the full path in the
1729 first parameter.
1730
1731 Shared libraries and data files required by the program
1732 must be available on filesystems which are mounted in the
1733 correct places.  It is the caller's responsibility to ensure
1734 all filesystems that are needed are mounted at the right
1735 locations.");
1736
1737   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1738    [InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 1"]], ["Result1"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 2"]], ["Result2"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 7"]], []);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 8"]], [""]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 9"]], ["";""]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1778     InitBasicFS, Always, TestOutputList (
1779       [["upload"; "test-command"; "/test-command"];
1780        ["chmod"; "0o755"; "/test-command"];
1781        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1782    "run a command, returning lines",
1783    "\
1784 This is the same as C<guestfs_command>, but splits the
1785 result into a list of lines.
1786
1787 See also: C<guestfs_sh_lines>");
1788
1789   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1790    [InitISOFS, Always, TestOutputStruct (
1791       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1792    "get file information",
1793    "\
1794 Returns file information for the given C<path>.
1795
1796 This is the same as the C<stat(2)> system call.");
1797
1798   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1799    [InitISOFS, Always, TestOutputStruct (
1800       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1801    "get file information for a symbolic link",
1802    "\
1803 Returns file information for the given C<path>.
1804
1805 This is the same as C<guestfs_stat> except that if C<path>
1806 is a symbolic link, then the link is stat-ed, not the file it
1807 refers to.
1808
1809 This is the same as the C<lstat(2)> system call.");
1810
1811   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1812    [InitISOFS, Always, TestOutputStruct (
1813       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1814    "get file system statistics",
1815    "\
1816 Returns file system statistics for any mounted file system.
1817 C<path> should be a file or directory in the mounted file system
1818 (typically it is the mount point itself, but it doesn't need to be).
1819
1820 This is the same as the C<statvfs(2)> system call.");
1821
1822   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1823    [], (* XXX test *)
1824    "get ext2/ext3/ext4 superblock details",
1825    "\
1826 This returns the contents of the ext2, ext3 or ext4 filesystem
1827 superblock on C<device>.
1828
1829 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1830 manpage for more details.  The list of fields returned isn't
1831 clearly defined, and depends on both the version of C<tune2fs>
1832 that libguestfs was built against, and the filesystem itself.");
1833
1834   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1835    [InitEmpty, Always, TestOutputTrue (
1836       [["blockdev_setro"; "/dev/sda"];
1837        ["blockdev_getro"; "/dev/sda"]])],
1838    "set block device to read-only",
1839    "\
1840 Sets the block device named C<device> to read-only.
1841
1842 This uses the L<blockdev(8)> command.");
1843
1844   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1845    [InitEmpty, Always, TestOutputFalse (
1846       [["blockdev_setrw"; "/dev/sda"];
1847        ["blockdev_getro"; "/dev/sda"]])],
1848    "set block device to read-write",
1849    "\
1850 Sets the block device named C<device> to read-write.
1851
1852 This uses the L<blockdev(8)> command.");
1853
1854   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1855    [InitEmpty, Always, TestOutputTrue (
1856       [["blockdev_setro"; "/dev/sda"];
1857        ["blockdev_getro"; "/dev/sda"]])],
1858    "is block device set to read-only",
1859    "\
1860 Returns a boolean indicating if the block device is read-only
1861 (true if read-only, false if not).
1862
1863 This uses the L<blockdev(8)> command.");
1864
1865   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1866    [InitEmpty, Always, TestOutputInt (
1867       [["blockdev_getss"; "/dev/sda"]], 512)],
1868    "get sectorsize of block device",
1869    "\
1870 This returns the size of sectors on a block device.
1871 Usually 512, but can be larger for modern devices.
1872
1873 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1874 for that).
1875
1876 This uses the L<blockdev(8)> command.");
1877
1878   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1879    [InitEmpty, Always, TestOutputInt (
1880       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1881    "get blocksize of block device",
1882    "\
1883 This returns the block size of a device.
1884
1885 (Note this is different from both I<size in blocks> and
1886 I<filesystem block size>).
1887
1888 This uses the L<blockdev(8)> command.");
1889
1890   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1891    [], (* XXX test *)
1892    "set blocksize of block device",
1893    "\
1894 This sets the block size of a device.
1895
1896 (Note this is different from both I<size in blocks> and
1897 I<filesystem block size>).
1898
1899 This uses the L<blockdev(8)> command.");
1900
1901   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1902    [InitEmpty, Always, TestOutputInt (
1903       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1904    "get total size of device in 512-byte sectors",
1905    "\
1906 This returns the size of the device in units of 512-byte sectors
1907 (even if the sectorsize isn't 512 bytes ... weird).
1908
1909 See also C<guestfs_blockdev_getss> for the real sector size of
1910 the device, and C<guestfs_blockdev_getsize64> for the more
1911 useful I<size in bytes>.
1912
1913 This uses the L<blockdev(8)> command.");
1914
1915   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1916    [InitEmpty, Always, TestOutputInt (
1917       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1918    "get total size of device in bytes",
1919    "\
1920 This returns the size of the device in bytes.
1921
1922 See also C<guestfs_blockdev_getsz>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1927    [InitEmpty, Always, TestRun
1928       [["blockdev_flushbufs"; "/dev/sda"]]],
1929    "flush device buffers",
1930    "\
1931 This tells the kernel to flush internal buffers associated
1932 with C<device>.
1933
1934 This uses the L<blockdev(8)> command.");
1935
1936   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1937    [InitEmpty, Always, TestRun
1938       [["blockdev_rereadpt"; "/dev/sda"]]],
1939    "reread partition table",
1940    "\
1941 Reread the partition table on C<device>.
1942
1943 This uses the L<blockdev(8)> command.");
1944
1945   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1946    [InitBasicFS, Always, TestOutput (
1947       (* Pick a file from cwd which isn't likely to change. *)
1948       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1949        ["checksum"; "md5"; "/COPYING.LIB"]],
1950       Digest.to_hex (Digest.file "COPYING.LIB"))],
1951    "upload a file from the local machine",
1952    "\
1953 Upload local file C<filename> to C<remotefilename> on the
1954 filesystem.
1955
1956 C<filename> can also be a named pipe.
1957
1958 See also C<guestfs_download>.");
1959
1960   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1961    [InitBasicFS, Always, TestOutput (
1962       (* Pick a file from cwd which isn't likely to change. *)
1963       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1964        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1965        ["upload"; "testdownload.tmp"; "/upload"];
1966        ["checksum"; "md5"; "/upload"]],
1967       Digest.to_hex (Digest.file "COPYING.LIB"))],
1968    "download a file to the local machine",
1969    "\
1970 Download file C<remotefilename> and save it as C<filename>
1971 on the local machine.
1972
1973 C<filename> can also be a named pipe.
1974
1975 See also C<guestfs_upload>, C<guestfs_cat>.");
1976
1977   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1978    [InitISOFS, Always, TestOutput (
1979       [["checksum"; "crc"; "/known-3"]], "2891671662");
1980     InitISOFS, Always, TestLastFail (
1981       [["checksum"; "crc"; "/notexists"]]);
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1990     InitISOFS, Always, TestOutput (
1991       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1992     InitISOFS, Always, TestOutput (
1993       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1994     (* Test for RHBZ#579608, absolute symbolic links. *)
1995     InitISOFS, Always, TestOutput (
1996       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1997    "compute MD5, SHAx or CRC checksum of file",
1998    "\
1999 This call computes the MD5, SHAx or CRC checksum of the
2000 file named C<path>.
2001
2002 The type of checksum to compute is given by the C<csumtype>
2003 parameter which must have one of the following values:
2004
2005 =over 4
2006
2007 =item C<crc>
2008
2009 Compute the cyclic redundancy check (CRC) specified by POSIX
2010 for the C<cksum> command.
2011
2012 =item C<md5>
2013
2014 Compute the MD5 hash (using the C<md5sum> program).
2015
2016 =item C<sha1>
2017
2018 Compute the SHA1 hash (using the C<sha1sum> program).
2019
2020 =item C<sha224>
2021
2022 Compute the SHA224 hash (using the C<sha224sum> program).
2023
2024 =item C<sha256>
2025
2026 Compute the SHA256 hash (using the C<sha256sum> program).
2027
2028 =item C<sha384>
2029
2030 Compute the SHA384 hash (using the C<sha384sum> program).
2031
2032 =item C<sha512>
2033
2034 Compute the SHA512 hash (using the C<sha512sum> program).
2035
2036 =back
2037
2038 The checksum is returned as a printable string.
2039
2040 To get the checksum for a device, use C<guestfs_checksum_device>.
2041
2042 To get the checksums for many files, use C<guestfs_checksums_out>.");
2043
2044   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2045    [InitBasicFS, Always, TestOutput (
2046       [["tar_in"; "../images/helloworld.tar"; "/"];
2047        ["cat"; "/hello"]], "hello\n")],
2048    "unpack tarfile to directory",
2049    "\
2050 This command uploads and unpacks local file C<tarfile> (an
2051 I<uncompressed> tar file) into C<directory>.
2052
2053 To upload a compressed tarball, use C<guestfs_tgz_in>
2054 or C<guestfs_txz_in>.");
2055
2056   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2057    [],
2058    "pack directory into tarfile",
2059    "\
2060 This command packs the contents of C<directory> and downloads
2061 it to local file C<tarfile>.
2062
2063 To download a compressed tarball, use C<guestfs_tgz_out>
2064 or C<guestfs_txz_out>.");
2065
2066   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2067    [InitBasicFS, Always, TestOutput (
2068       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2069        ["cat"; "/hello"]], "hello\n")],
2070    "unpack compressed tarball to directory",
2071    "\
2072 This command uploads and unpacks local file C<tarball> (a
2073 I<gzip compressed> tar file) into C<directory>.
2074
2075 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2076
2077   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2078    [],
2079    "pack directory into compressed tarball",
2080    "\
2081 This command packs the contents of C<directory> and downloads
2082 it to local file C<tarball>.
2083
2084 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2085
2086   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2087    [InitBasicFS, Always, TestLastFail (
2088       [["umount"; "/"];
2089        ["mount_ro"; "/dev/sda1"; "/"];
2090        ["touch"; "/new"]]);
2091     InitBasicFS, Always, TestOutput (
2092       [["write_file"; "/new"; "data"; "0"];
2093        ["umount"; "/"];
2094        ["mount_ro"; "/dev/sda1"; "/"];
2095        ["cat"; "/new"]], "data")],
2096    "mount a guest disk, read-only",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 mounts the filesystem with the read-only (I<-o ro>) flag.");
2100
2101   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2102    [],
2103    "mount a guest disk with mount options",
2104    "\
2105 This is the same as the C<guestfs_mount> command, but it
2106 allows you to set the mount options as for the
2107 L<mount(8)> I<-o> flag.
2108
2109 If the C<options> parameter is an empty string, then
2110 no options are passed (all options default to whatever
2111 the filesystem uses).");
2112
2113   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2114    [],
2115    "mount a guest disk with mount options and vfstype",
2116    "\
2117 This is the same as the C<guestfs_mount> command, but it
2118 allows you to set both the mount options and the vfstype
2119 as for the L<mount(8)> I<-o> and I<-t> flags.");
2120
2121   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2122    [],
2123    "debugging and internals",
2124    "\
2125 The C<guestfs_debug> command exposes some internals of
2126 C<guestfsd> (the guestfs daemon) that runs inside the
2127 qemu subprocess.
2128
2129 There is no comprehensive help for this command.  You have
2130 to look at the file C<daemon/debug.c> in the libguestfs source
2131 to find out what you can do.");
2132
2133   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2134    [InitEmpty, Always, TestOutputList (
2135       [["part_disk"; "/dev/sda"; "mbr"];
2136        ["pvcreate"; "/dev/sda1"];
2137        ["vgcreate"; "VG"; "/dev/sda1"];
2138        ["lvcreate"; "LV1"; "VG"; "50"];
2139        ["lvcreate"; "LV2"; "VG"; "50"];
2140        ["lvremove"; "/dev/VG/LV1"];
2141        ["lvs"]], ["/dev/VG/LV2"]);
2142     InitEmpty, Always, TestOutputList (
2143       [["part_disk"; "/dev/sda"; "mbr"];
2144        ["pvcreate"; "/dev/sda1"];
2145        ["vgcreate"; "VG"; "/dev/sda1"];
2146        ["lvcreate"; "LV1"; "VG"; "50"];
2147        ["lvcreate"; "LV2"; "VG"; "50"];
2148        ["lvremove"; "/dev/VG"];
2149        ["lvs"]], []);
2150     InitEmpty, Always, TestOutputList (
2151       [["part_disk"; "/dev/sda"; "mbr"];
2152        ["pvcreate"; "/dev/sda1"];
2153        ["vgcreate"; "VG"; "/dev/sda1"];
2154        ["lvcreate"; "LV1"; "VG"; "50"];
2155        ["lvcreate"; "LV2"; "VG"; "50"];
2156        ["lvremove"; "/dev/VG"];
2157        ["vgs"]], ["VG"])],
2158    "remove an LVM logical volume",
2159    "\
2160 Remove an LVM logical volume C<device>, where C<device> is
2161 the path to the LV, such as C</dev/VG/LV>.
2162
2163 You can also remove all LVs in a volume group by specifying
2164 the VG name, C</dev/VG>.");
2165
2166   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2167    [InitEmpty, Always, TestOutputList (
2168       [["part_disk"; "/dev/sda"; "mbr"];
2169        ["pvcreate"; "/dev/sda1"];
2170        ["vgcreate"; "VG"; "/dev/sda1"];
2171        ["lvcreate"; "LV1"; "VG"; "50"];
2172        ["lvcreate"; "LV2"; "VG"; "50"];
2173        ["vgremove"; "VG"];
2174        ["lvs"]], []);
2175     InitEmpty, Always, TestOutputList (
2176       [["part_disk"; "/dev/sda"; "mbr"];
2177        ["pvcreate"; "/dev/sda1"];
2178        ["vgcreate"; "VG"; "/dev/sda1"];
2179        ["lvcreate"; "LV1"; "VG"; "50"];
2180        ["lvcreate"; "LV2"; "VG"; "50"];
2181        ["vgremove"; "VG"];
2182        ["vgs"]], [])],
2183    "remove an LVM volume group",
2184    "\
2185 Remove an LVM volume group C<vgname>, (for example C<VG>).
2186
2187 This also forcibly removes all logical volumes in the volume
2188 group (if any).");
2189
2190   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2191    [InitEmpty, Always, TestOutputListOfDevices (
2192       [["part_disk"; "/dev/sda"; "mbr"];
2193        ["pvcreate"; "/dev/sda1"];
2194        ["vgcreate"; "VG"; "/dev/sda1"];
2195        ["lvcreate"; "LV1"; "VG"; "50"];
2196        ["lvcreate"; "LV2"; "VG"; "50"];
2197        ["vgremove"; "VG"];
2198        ["pvremove"; "/dev/sda1"];
2199        ["lvs"]], []);
2200     InitEmpty, Always, TestOutputListOfDevices (
2201       [["part_disk"; "/dev/sda"; "mbr"];
2202        ["pvcreate"; "/dev/sda1"];
2203        ["vgcreate"; "VG"; "/dev/sda1"];
2204        ["lvcreate"; "LV1"; "VG"; "50"];
2205        ["lvcreate"; "LV2"; "VG"; "50"];
2206        ["vgremove"; "VG"];
2207        ["pvremove"; "/dev/sda1"];
2208        ["vgs"]], []);
2209     InitEmpty, Always, TestOutputListOfDevices (
2210       [["part_disk"; "/dev/sda"; "mbr"];
2211        ["pvcreate"; "/dev/sda1"];
2212        ["vgcreate"; "VG"; "/dev/sda1"];
2213        ["lvcreate"; "LV1"; "VG"; "50"];
2214        ["lvcreate"; "LV2"; "VG"; "50"];
2215        ["vgremove"; "VG"];
2216        ["pvremove"; "/dev/sda1"];
2217        ["pvs"]], [])],
2218    "remove an LVM physical volume",
2219    "\
2220 This wipes a physical volume C<device> so that LVM will no longer
2221 recognise it.
2222
2223 The implementation uses the C<pvremove> command which refuses to
2224 wipe physical volumes that contain any volume groups, so you have
2225 to remove those first.");
2226
2227   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2228    [InitBasicFS, Always, TestOutput (
2229       [["set_e2label"; "/dev/sda1"; "testlabel"];
2230        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2231    "set the ext2/3/4 filesystem label",
2232    "\
2233 This sets the ext2/3/4 filesystem label of the filesystem on
2234 C<device> to C<label>.  Filesystem labels are limited to
2235 16 characters.
2236
2237 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2238 to return the existing label on a filesystem.");
2239
2240   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2241    [],
2242    "get the ext2/3/4 filesystem label",
2243    "\
2244 This returns the ext2/3/4 filesystem label of the filesystem on
2245 C<device>.");
2246
2247   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2248    (let uuid = uuidgen () in
2249     [InitBasicFS, Always, TestOutput (
2250        [["set_e2uuid"; "/dev/sda1"; uuid];
2251         ["get_e2uuid"; "/dev/sda1"]], uuid);
2252      InitBasicFS, Always, TestOutput (
2253        [["set_e2uuid"; "/dev/sda1"; "clear"];
2254         ["get_e2uuid"; "/dev/sda1"]], "");
2255      (* We can't predict what UUIDs will be, so just check the commands run. *)
2256      InitBasicFS, Always, TestRun (
2257        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2258      InitBasicFS, Always, TestRun (
2259        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2260    "set the ext2/3/4 filesystem UUID",
2261    "\
2262 This sets the ext2/3/4 filesystem UUID of the filesystem on
2263 C<device> to C<uuid>.  The format of the UUID and alternatives
2264 such as C<clear>, C<random> and C<time> are described in the
2265 L<tune2fs(8)> manpage.
2266
2267 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2268 to return the existing UUID of a filesystem.");
2269
2270   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2271    [],
2272    "get the ext2/3/4 filesystem UUID",
2273    "\
2274 This returns the ext2/3/4 filesystem UUID of the filesystem on
2275 C<device>.");
2276
2277   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2278    [InitBasicFS, Always, TestOutputInt (
2279       [["umount"; "/dev/sda1"];
2280        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2281     InitBasicFS, Always, TestOutputInt (
2282       [["umount"; "/dev/sda1"];
2283        ["zero"; "/dev/sda1"];
2284        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2285    "run the filesystem checker",
2286    "\
2287 This runs the filesystem checker (fsck) on C<device> which
2288 should have filesystem type C<fstype>.
2289
2290 The returned integer is the status.  See L<fsck(8)> for the
2291 list of status codes from C<fsck>.
2292
2293 Notes:
2294
2295 =over 4
2296
2297 =item *
2298
2299 Multiple status codes can be summed together.
2300
2301 =item *
2302
2303 A non-zero return code can mean \"success\", for example if
2304 errors have been corrected on the filesystem.
2305
2306 =item *
2307
2308 Checking or repairing NTFS volumes is not supported
2309 (by linux-ntfs).
2310
2311 =back
2312
2313 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2314
2315   ("zero", (RErr, [Device "device"]), 85, [],
2316    [InitBasicFS, Always, TestOutput (
2317       [["umount"; "/dev/sda1"];
2318        ["zero"; "/dev/sda1"];
2319        ["file"; "/dev/sda1"]], "data")],
2320    "write zeroes to the device",
2321    "\
2322 This command writes zeroes over the first few blocks of C<device>.
2323
2324 How many blocks are zeroed isn't specified (but it's I<not> enough
2325 to securely wipe the device).  It should be sufficient to remove
2326 any partition tables, filesystem superblocks and so on.
2327
2328 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2329
2330   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2331    (* Test disabled because grub-install incompatible with virtio-blk driver.
2332     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2333     *)
2334    [InitBasicFS, Disabled, TestOutputTrue (
2335       [["grub_install"; "/"; "/dev/sda1"];
2336        ["is_dir"; "/boot"]])],
2337    "install GRUB",
2338    "\
2339 This command installs GRUB (the Grand Unified Bootloader) on
2340 C<device>, with the root directory being C<root>.");
2341
2342   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["write_file"; "/old"; "file content"; "0"];
2345        ["cp"; "/old"; "/new"];
2346        ["cat"; "/new"]], "file content");
2347     InitBasicFS, Always, TestOutputTrue (
2348       [["write_file"; "/old"; "file content"; "0"];
2349        ["cp"; "/old"; "/new"];
2350        ["is_file"; "/old"]]);
2351     InitBasicFS, Always, TestOutput (
2352       [["write_file"; "/old"; "file content"; "0"];
2353        ["mkdir"; "/dir"];
2354        ["cp"; "/old"; "/dir/new"];
2355        ["cat"; "/dir/new"]], "file content")],
2356    "copy a file",
2357    "\
2358 This copies a file from C<src> to C<dest> where C<dest> is
2359 either a destination filename or destination directory.");
2360
2361   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2362    [InitBasicFS, Always, TestOutput (
2363       [["mkdir"; "/olddir"];
2364        ["mkdir"; "/newdir"];
2365        ["write_file"; "/olddir/file"; "file content"; "0"];
2366        ["cp_a"; "/olddir"; "/newdir"];
2367        ["cat"; "/newdir/olddir/file"]], "file content")],
2368    "copy a file or directory recursively",
2369    "\
2370 This copies a file or directory from C<src> to C<dest>
2371 recursively using the C<cp -a> command.");
2372
2373   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2374    [InitBasicFS, Always, TestOutput (
2375       [["write_file"; "/old"; "file content"; "0"];
2376        ["mv"; "/old"; "/new"];
2377        ["cat"; "/new"]], "file content");
2378     InitBasicFS, Always, TestOutputFalse (
2379       [["write_file"; "/old"; "file content"; "0"];
2380        ["mv"; "/old"; "/new"];
2381        ["is_file"; "/old"]])],
2382    "move a file",
2383    "\
2384 This moves a file from C<src> to C<dest> where C<dest> is
2385 either a destination filename or destination directory.");
2386
2387   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2388    [InitEmpty, Always, TestRun (
2389       [["drop_caches"; "3"]])],
2390    "drop kernel page cache, dentries and inodes",
2391    "\
2392 This instructs the guest kernel to drop its page cache,
2393 and/or dentries and inode caches.  The parameter C<whattodrop>
2394 tells the kernel what precisely to drop, see
2395 L<http://linux-mm.org/Drop_Caches>
2396
2397 Setting C<whattodrop> to 3 should drop everything.
2398
2399 This automatically calls L<sync(2)> before the operation,
2400 so that the maximum guest memory is freed.");
2401
2402   ("dmesg", (RString "kmsgs", []), 91, [],
2403    [InitEmpty, Always, TestRun (
2404       [["dmesg"]])],
2405    "return kernel messages",
2406    "\
2407 This returns the kernel messages (C<dmesg> output) from
2408 the guest kernel.  This is sometimes useful for extended
2409 debugging of problems.
2410
2411 Another way to get the same information is to enable
2412 verbose messages with C<guestfs_set_verbose> or by setting
2413 the environment variable C<LIBGUESTFS_DEBUG=1> before
2414 running the program.");
2415
2416   ("ping_daemon", (RErr, []), 92, [],
2417    [InitEmpty, Always, TestRun (
2418       [["ping_daemon"]])],
2419    "ping the guest daemon",
2420    "\
2421 This is a test probe into the guestfs daemon running inside
2422 the qemu subprocess.  Calling this function checks that the
2423 daemon responds to the ping message, without affecting the daemon
2424 or attached block device(s) in any other way.");
2425
2426   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2427    [InitBasicFS, Always, TestOutputTrue (
2428       [["write_file"; "/file1"; "contents of a file"; "0"];
2429        ["cp"; "/file1"; "/file2"];
2430        ["equal"; "/file1"; "/file2"]]);
2431     InitBasicFS, Always, TestOutputFalse (
2432       [["write_file"; "/file1"; "contents of a file"; "0"];
2433        ["write_file"; "/file2"; "contents of another file"; "0"];
2434        ["equal"; "/file1"; "/file2"]]);
2435     InitBasicFS, Always, TestLastFail (
2436       [["equal"; "/file1"; "/file2"]])],
2437    "test if two files have equal contents",
2438    "\
2439 This compares the two files C<file1> and C<file2> and returns
2440 true if their content is exactly equal, or false otherwise.
2441
2442 The external L<cmp(1)> program is used for the comparison.");
2443
2444   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2445    [InitISOFS, Always, TestOutputList (
2446       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2447     InitISOFS, Always, TestOutputList (
2448       [["strings"; "/empty"]], []);
2449     (* Test for RHBZ#579608, absolute symbolic links. *)
2450     InitISOFS, Always, TestRun (
2451       [["strings"; "/abssymlink"]])],
2452    "print the printable strings in a file",
2453    "\
2454 This runs the L<strings(1)> command on a file and returns
2455 the list of printable strings found.");
2456
2457   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2458    [InitISOFS, Always, TestOutputList (
2459       [["strings_e"; "b"; "/known-5"]], []);
2460     InitBasicFS, Disabled, TestOutputList (
2461       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2462        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2463    "print the printable strings in a file",
2464    "\
2465 This is like the C<guestfs_strings> command, but allows you to
2466 specify the encoding.
2467
2468 See the L<strings(1)> manpage for the full list of encodings.
2469
2470 Commonly useful encodings are C<l> (lower case L) which will
2471 show strings inside Windows/x86 files.
2472
2473 The returned strings are transcoded to UTF-8.");
2474
2475   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2476    [InitISOFS, Always, TestOutput (
2477       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2478     (* Test for RHBZ#501888c2 regression which caused large hexdump
2479      * commands to segfault.
2480      *)
2481     InitISOFS, Always, TestRun (
2482       [["hexdump"; "/100krandom"]]);
2483     (* Test for RHBZ#579608, absolute symbolic links. *)
2484     InitISOFS, Always, TestRun (
2485       [["hexdump"; "/abssymlink"]])],
2486    "dump a file in hexadecimal",
2487    "\
2488 This runs C<hexdump -C> on the given C<path>.  The result is
2489 the human-readable, canonical hex dump of the file.");
2490
2491   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2492    [InitNone, Always, TestOutput (
2493       [["part_disk"; "/dev/sda"; "mbr"];
2494        ["mkfs"; "ext3"; "/dev/sda1"];
2495        ["mount_options"; ""; "/dev/sda1"; "/"];
2496        ["write_file"; "/new"; "test file"; "0"];
2497        ["umount"; "/dev/sda1"];
2498        ["zerofree"; "/dev/sda1"];
2499        ["mount_options"; ""; "/dev/sda1"; "/"];
2500        ["cat"; "/new"]], "test file")],
2501    "zero unused inodes and disk blocks on ext2/3 filesystem",
2502    "\
2503 This runs the I<zerofree> program on C<device>.  This program
2504 claims to zero unused inodes and disk blocks on an ext2/3
2505 filesystem, thus making it possible to compress the filesystem
2506 more effectively.
2507
2508 You should B<not> run this program if the filesystem is
2509 mounted.
2510
2511 It is possible that using this program can damage the filesystem
2512 or data on the filesystem.");
2513
2514   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2515    [],
2516    "resize an LVM physical volume",
2517    "\
2518 This resizes (expands or shrinks) an existing LVM physical
2519 volume to match the new size of the underlying device.");
2520
2521   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2522                        Int "cyls"; Int "heads"; Int "sectors";
2523                        String "line"]), 99, [DangerWillRobinson],
2524    [],
2525    "modify a single partition on a block device",
2526    "\
2527 This runs L<sfdisk(8)> option to modify just the single
2528 partition C<n> (note: C<n> counts from 1).
2529
2530 For other parameters, see C<guestfs_sfdisk>.  You should usually
2531 pass C<0> for the cyls/heads/sectors parameters.
2532
2533 See also: C<guestfs_part_add>");
2534
2535   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2536    [],
2537    "display the partition table",
2538    "\
2539 This displays the partition table on C<device>, in the
2540 human-readable output of the L<sfdisk(8)> command.  It is
2541 not intended to be parsed.
2542
2543 See also: C<guestfs_part_list>");
2544
2545   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2546    [],
2547    "display the kernel geometry",
2548    "\
2549 This displays the kernel's idea of the geometry of C<device>.
2550
2551 The result is in human-readable format, and not designed to
2552 be parsed.");
2553
2554   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2555    [],
2556    "display the disk geometry from the partition table",
2557    "\
2558 This displays the disk geometry of C<device> read from the
2559 partition table.  Especially in the case where the underlying
2560 block device has been resized, this can be different from the
2561 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2562
2563 The result is in human-readable format, and not designed to
2564 be parsed.");
2565
2566   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2567    [],
2568    "activate or deactivate all volume groups",
2569    "\
2570 This command activates or (if C<activate> is false) deactivates
2571 all logical volumes in all volume groups.
2572 If activated, then they are made known to the
2573 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2574 then those devices disappear.
2575
2576 This command is the same as running C<vgchange -a y|n>");
2577
2578   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2579    [],
2580    "activate or deactivate some volume groups",
2581    "\
2582 This command activates or (if C<activate> is false) deactivates
2583 all logical volumes in the listed volume groups C<volgroups>.
2584 If activated, then they are made known to the
2585 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2586 then those devices disappear.
2587
2588 This command is the same as running C<vgchange -a y|n volgroups...>
2589
2590 Note that if C<volgroups> is an empty list then B<all> volume groups
2591 are activated or deactivated.");
2592
2593   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2594    [InitNone, Always, TestOutput (
2595       [["part_disk"; "/dev/sda"; "mbr"];
2596        ["pvcreate"; "/dev/sda1"];
2597        ["vgcreate"; "VG"; "/dev/sda1"];
2598        ["lvcreate"; "LV"; "VG"; "10"];
2599        ["mkfs"; "ext2"; "/dev/VG/LV"];
2600        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2601        ["write_file"; "/new"; "test content"; "0"];
2602        ["umount"; "/"];
2603        ["lvresize"; "/dev/VG/LV"; "20"];
2604        ["e2fsck_f"; "/dev/VG/LV"];
2605        ["resize2fs"; "/dev/VG/LV"];
2606        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2607        ["cat"; "/new"]], "test content");
2608     InitNone, Always, TestRun (
2609       (* Make an LV smaller to test RHBZ#587484. *)
2610       [["part_disk"; "/dev/sda"; "mbr"];
2611        ["pvcreate"; "/dev/sda1"];
2612        ["vgcreate"; "VG"; "/dev/sda1"];
2613        ["lvcreate"; "LV"; "VG"; "20"];
2614        ["lvresize"; "/dev/VG/LV"; "10"]])],
2615    "resize an LVM logical volume",
2616    "\
2617 This resizes (expands or shrinks) an existing LVM logical
2618 volume to C<mbytes>.  When reducing, data in the reduced part
2619 is lost.");
2620
2621   ("resize2fs", (RErr, [Device "device"]), 106, [],
2622    [], (* lvresize tests this *)
2623    "resize an ext2/ext3 filesystem",
2624    "\
2625 This resizes an ext2 or ext3 filesystem to match the size of
2626 the underlying device.
2627
2628 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2629 on the C<device> before calling this command.  For unknown reasons
2630 C<resize2fs> sometimes gives an error about this and sometimes not.
2631 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2632 calling this function.");
2633
2634   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2635    [InitBasicFS, Always, TestOutputList (
2636       [["find"; "/"]], ["lost+found"]);
2637     InitBasicFS, Always, TestOutputList (
2638       [["touch"; "/a"];
2639        ["mkdir"; "/b"];
2640        ["touch"; "/b/c"];
2641        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2642     InitBasicFS, Always, TestOutputList (
2643       [["mkdir_p"; "/a/b/c"];
2644        ["touch"; "/a/b/c/d"];
2645        ["find"; "/a/b/"]], ["c"; "c/d"])],
2646    "find all files and directories",
2647    "\
2648 This command lists out all files and directories, recursively,
2649 starting at C<directory>.  It is essentially equivalent to
2650 running the shell command C<find directory -print> but some
2651 post-processing happens on the output, described below.
2652
2653 This returns a list of strings I<without any prefix>.  Thus
2654 if the directory structure was:
2655
2656  /tmp/a
2657  /tmp/b
2658  /tmp/c/d
2659
2660 then the returned list from C<guestfs_find> C</tmp> would be
2661 4 elements:
2662
2663  a
2664  b
2665  c
2666  c/d
2667
2668 If C<directory> is not a directory, then this command returns
2669 an error.
2670
2671 The returned list is sorted.
2672
2673 See also C<guestfs_find0>.");
2674
2675   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2676    [], (* lvresize tests this *)
2677    "check an ext2/ext3 filesystem",
2678    "\
2679 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2680 filesystem checker on C<device>, noninteractively (C<-p>),
2681 even if the filesystem appears to be clean (C<-f>).
2682
2683 This command is only needed because of C<guestfs_resize2fs>
2684 (q.v.).  Normally you should use C<guestfs_fsck>.");
2685
2686   ("sleep", (RErr, [Int "secs"]), 109, [],
2687    [InitNone, Always, TestRun (
2688       [["sleep"; "1"]])],
2689    "sleep for some seconds",
2690    "\
2691 Sleep for C<secs> seconds.");
2692
2693   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2694    [InitNone, Always, TestOutputInt (
2695       [["part_disk"; "/dev/sda"; "mbr"];
2696        ["mkfs"; "ntfs"; "/dev/sda1"];
2697        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2698     InitNone, Always, TestOutputInt (
2699       [["part_disk"; "/dev/sda"; "mbr"];
2700        ["mkfs"; "ext2"; "/dev/sda1"];
2701        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2702    "probe NTFS volume",
2703    "\
2704 This command runs the L<ntfs-3g.probe(8)> command which probes
2705 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2706 be mounted read-write, and some cannot be mounted at all).
2707
2708 C<rw> is a boolean flag.  Set it to true if you want to test
2709 if the volume can be mounted read-write.  Set it to false if
2710 you want to test if the volume can be mounted read-only.
2711
2712 The return value is an integer which C<0> if the operation
2713 would succeed, or some non-zero value documented in the
2714 L<ntfs-3g.probe(8)> manual page.");
2715
2716   ("sh", (RString "output", [String "command"]), 111, [],
2717    [], (* XXX needs tests *)
2718    "run a command via the shell",
2719    "\
2720 This call runs a command from the guest filesystem via the
2721 guest's C</bin/sh>.
2722
2723 This is like C<guestfs_command>, but passes the command to:
2724
2725  /bin/sh -c \"command\"
2726
2727 Depending on the guest's shell, this usually results in
2728 wildcards being expanded, shell expressions being interpolated
2729 and so on.
2730
2731 All the provisos about C<guestfs_command> apply to this call.");
2732
2733   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2734    [], (* XXX needs tests *)
2735    "run a command via the shell returning lines",
2736    "\
2737 This is the same as C<guestfs_sh>, but splits the result
2738 into a list of lines.
2739
2740 See also: C<guestfs_command_lines>");
2741
2742   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2743    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2744     * code in stubs.c, since all valid glob patterns must start with "/".
2745     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2746     *)
2747    [InitBasicFS, Always, TestOutputList (
2748       [["mkdir_p"; "/a/b/c"];
2749        ["touch"; "/a/b/c/d"];
2750        ["touch"; "/a/b/c/e"];
2751        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2752     InitBasicFS, Always, TestOutputList (
2753       [["mkdir_p"; "/a/b/c"];
2754        ["touch"; "/a/b/c/d"];
2755        ["touch"; "/a/b/c/e"];
2756        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2757     InitBasicFS, Always, TestOutputList (
2758       [["mkdir_p"; "/a/b/c"];
2759        ["touch"; "/a/b/c/d"];
2760        ["touch"; "/a/b/c/e"];
2761        ["glob_expand"; "/a/*/x/*"]], [])],
2762    "expand a wildcard path",
2763    "\
2764 This command searches for all the pathnames matching
2765 C<pattern> according to the wildcard expansion rules
2766 used by the shell.
2767
2768 If no paths match, then this returns an empty list
2769 (note: not an error).
2770
2771 It is just a wrapper around the C L<glob(3)> function
2772 with flags C<GLOB_MARK|GLOB_BRACE>.
2773 See that manual page for more details.");
2774
2775   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2776    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2777       [["scrub_device"; "/dev/sdc"]])],
2778    "scrub (securely wipe) a device",
2779    "\
2780 This command writes patterns over C<device> to make data retrieval
2781 more difficult.
2782
2783 It is an interface to the L<scrub(1)> program.  See that
2784 manual page for more details.");
2785
2786   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2787    [InitBasicFS, Always, TestRun (
2788       [["write_file"; "/file"; "content"; "0"];
2789        ["scrub_file"; "/file"]])],
2790    "scrub (securely wipe) a file",
2791    "\
2792 This command writes patterns over a file to make data retrieval
2793 more difficult.
2794
2795 The file is I<removed> after scrubbing.
2796
2797 It is an interface to the L<scrub(1)> program.  See that
2798 manual page for more details.");
2799
2800   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2801    [], (* XXX needs testing *)
2802    "scrub (securely wipe) free space",
2803    "\
2804 This command creates the directory C<dir> and then fills it
2805 with files until the filesystem is full, and scrubs the files
2806 as for C<guestfs_scrub_file>, and deletes them.
2807 The intention is to scrub any free space on the partition
2808 containing C<dir>.
2809
2810 It is an interface to the L<scrub(1)> program.  See that
2811 manual page for more details.");
2812
2813   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2814    [InitBasicFS, Always, TestRun (
2815       [["mkdir"; "/tmp"];
2816        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2817    "create a temporary directory",
2818    "\
2819 This command creates a temporary directory.  The
2820 C<template> parameter should be a full pathname for the
2821 temporary directory name with the final six characters being
2822 \"XXXXXX\".
2823
2824 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2825 the second one being suitable for Windows filesystems.
2826
2827 The name of the temporary directory that was created
2828 is returned.
2829
2830 The temporary directory is created with mode 0700
2831 and is owned by root.
2832
2833 The caller is responsible for deleting the temporary
2834 directory and its contents after use.
2835
2836 See also: L<mkdtemp(3)>");
2837
2838   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2839    [InitISOFS, Always, TestOutputInt (
2840       [["wc_l"; "/10klines"]], 10000);
2841     (* Test for RHBZ#579608, absolute symbolic links. *)
2842     InitISOFS, Always, TestOutputInt (
2843       [["wc_l"; "/abssymlink"]], 10000)],
2844    "count lines in a file",
2845    "\
2846 This command counts the lines in a file, using the
2847 C<wc -l> external command.");
2848
2849   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2850    [InitISOFS, Always, TestOutputInt (
2851       [["wc_w"; "/10klines"]], 10000)],
2852    "count words in a file",
2853    "\
2854 This command counts the words in a file, using the
2855 C<wc -w> external command.");
2856
2857   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2858    [InitISOFS, Always, TestOutputInt (
2859       [["wc_c"; "/100kallspaces"]], 102400)],
2860    "count characters in a file",
2861    "\
2862 This command counts the characters in a file, using the
2863 C<wc -c> external command.");
2864
2865   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2866    [InitISOFS, Always, TestOutputList (
2867       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2868     (* Test for RHBZ#579608, absolute symbolic links. *)
2869     InitISOFS, Always, TestOutputList (
2870       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2871    "return first 10 lines of a file",
2872    "\
2873 This command returns up to the first 10 lines of a file as
2874 a list of strings.");
2875
2876   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2877    [InitISOFS, Always, TestOutputList (
2878       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2879     InitISOFS, Always, TestOutputList (
2880       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2881     InitISOFS, Always, TestOutputList (
2882       [["head_n"; "0"; "/10klines"]], [])],
2883    "return first N lines of a file",
2884    "\
2885 If the parameter C<nrlines> is a positive number, this returns the first
2886 C<nrlines> lines of the file C<path>.
2887
2888 If the parameter C<nrlines> is a negative number, this returns lines
2889 from the file C<path>, excluding the last C<nrlines> lines.
2890
2891 If the parameter C<nrlines> is zero, this returns an empty list.");
2892
2893   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2894    [InitISOFS, Always, TestOutputList (
2895       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2896    "return last 10 lines of a file",
2897    "\
2898 This command returns up to the last 10 lines of a file as
2899 a list of strings.");
2900
2901   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2902    [InitISOFS, Always, TestOutputList (
2903       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2904     InitISOFS, Always, TestOutputList (
2905       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2906     InitISOFS, Always, TestOutputList (
2907       [["tail_n"; "0"; "/10klines"]], [])],
2908    "return last N lines of a file",
2909    "\
2910 If the parameter C<nrlines> is a positive number, this returns the last
2911 C<nrlines> lines of the file C<path>.
2912
2913 If the parameter C<nrlines> is a negative number, this returns lines
2914 from the file C<path>, starting with the C<-nrlines>th line.
2915
2916 If the parameter C<nrlines> is zero, this returns an empty list.");
2917
2918   ("df", (RString "output", []), 125, [],
2919    [], (* XXX Tricky to test because it depends on the exact format
2920         * of the 'df' command and other imponderables.
2921         *)
2922    "report file system disk space usage",
2923    "\
2924 This command runs the C<df> command to report disk space used.
2925
2926 This command is mostly useful for interactive sessions.  It
2927 is I<not> intended that you try to parse the output string.
2928 Use C<statvfs> from programs.");
2929
2930   ("df_h", (RString "output", []), 126, [],
2931    [], (* XXX Tricky to test because it depends on the exact format
2932         * of the 'df' command and other imponderables.
2933         *)
2934    "report file system disk space usage (human readable)",
2935    "\
2936 This command runs the C<df -h> command to report disk space used
2937 in human-readable format.
2938
2939 This command is mostly useful for interactive sessions.  It
2940 is I<not> intended that you try to parse the output string.
2941 Use C<statvfs> from programs.");
2942
2943   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2944    [InitISOFS, Always, TestOutputInt (
2945       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2946    "estimate file space usage",
2947    "\
2948 This command runs the C<du -s> command to estimate file space
2949 usage for C<path>.
2950
2951 C<path> can be a file or a directory.  If C<path> is a directory
2952 then the estimate includes the contents of the directory and all
2953 subdirectories (recursively).
2954
2955 The result is the estimated size in I<kilobytes>
2956 (ie. units of 1024 bytes).");
2957
2958   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2959    [InitISOFS, Always, TestOutputList (
2960       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2961    "list files in an initrd",
2962    "\
2963 This command lists out files contained in an initrd.
2964
2965 The files are listed without any initial C</> character.  The
2966 files are listed in the order they appear (not necessarily
2967 alphabetical).  Directory names are listed as separate items.
2968
2969 Old Linux kernels (2.4 and earlier) used a compressed ext2
2970 filesystem as initrd.  We I<only> support the newer initramfs
2971 format (compressed cpio files).");
2972
2973   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2974    [],
2975    "mount a file using the loop device",
2976    "\
2977 This command lets you mount C<file> (a filesystem image
2978 in a file) on a mount point.  It is entirely equivalent to
2979 the command C<mount -o loop file mountpoint>.");
2980
2981   ("mkswap", (RErr, [Device "device"]), 130, [],
2982    [InitEmpty, Always, TestRun (
2983       [["part_disk"; "/dev/sda"; "mbr"];
2984        ["mkswap"; "/dev/sda1"]])],
2985    "create a swap partition",
2986    "\
2987 Create a swap partition on C<device>.");
2988
2989   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2990    [InitEmpty, Always, TestRun (
2991       [["part_disk"; "/dev/sda"; "mbr"];
2992        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2993    "create a swap partition with a label",
2994    "\
2995 Create a swap partition on C<device> with label C<label>.
2996
2997 Note that you cannot attach a swap label to a block device
2998 (eg. C</dev/sda>), just to a partition.  This appears to be
2999 a limitation of the kernel or swap tools.");
3000
3001   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3002    (let uuid = uuidgen () in
3003     [InitEmpty, Always, TestRun (
3004        [["part_disk"; "/dev/sda"; "mbr"];
3005         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3006    "create a swap partition with an explicit UUID",
3007    "\
3008 Create a swap partition on C<device> with UUID C<uuid>.");
3009
3010   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3011    [InitBasicFS, Always, TestOutputStruct (
3012       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3013        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3014        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3015     InitBasicFS, Always, TestOutputStruct (
3016       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3017        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3018    "make block, character or FIFO devices",
3019    "\
3020 This call creates block or character special devices, or
3021 named pipes (FIFOs).
3022
3023 The C<mode> parameter should be the mode, using the standard
3024 constants.  C<devmajor> and C<devminor> are the
3025 device major and minor numbers, only used when creating block
3026 and character special devices.
3027
3028 Note that, just like L<mknod(2)>, the mode must be bitwise
3029 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3030 just creates a regular file).  These constants are
3031 available in the standard Linux header files, or you can use
3032 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3033 which are wrappers around this command which bitwise OR
3034 in the appropriate constant for you.
3035
3036 The mode actually set is affected by the umask.");
3037
3038   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3039    [InitBasicFS, Always, TestOutputStruct (
3040       [["mkfifo"; "0o777"; "/node"];
3041        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3042    "make FIFO (named pipe)",
3043    "\
3044 This call creates a FIFO (named pipe) called C<path> with
3045 mode C<mode>.  It is just a convenient wrapper around
3046 C<guestfs_mknod>.
3047
3048 The mode actually set is affected by the umask.");
3049
3050   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3051    [InitBasicFS, Always, TestOutputStruct (
3052       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3053        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3054    "make block device node",
3055    "\
3056 This call creates a block device node called C<path> with
3057 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3058 It is just a convenient wrapper around C<guestfs_mknod>.
3059
3060 The mode actually set is affected by the umask.");
3061
3062   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3063    [InitBasicFS, Always, TestOutputStruct (
3064       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3065        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3066    "make char device node",
3067    "\
3068 This call creates a char device node called C<path> with
3069 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3070 It is just a convenient wrapper around C<guestfs_mknod>.
3071
3072 The mode actually set is affected by the umask.");
3073
3074   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3075    [InitEmpty, Always, TestOutputInt (
3076       [["umask"; "0o22"]], 0o22)],
3077    "set file mode creation mask (umask)",
3078    "\
3079 This function sets the mask used for creating new files and
3080 device nodes to C<mask & 0777>.
3081
3082 Typical umask values would be C<022> which creates new files
3083 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3084 C<002> which creates new files with permissions like
3085 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3086
3087 The default umask is C<022>.  This is important because it
3088 means that directories and device nodes will be created with
3089 C<0644> or C<0755> mode even if you specify C<0777>.
3090
3091 See also C<guestfs_get_umask>,
3092 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3093
3094 This call returns the previous umask.");
3095
3096   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3097    [],
3098    "read directories entries",
3099    "\
3100 This returns the list of directory entries in directory C<dir>.
3101
3102 All entries in the directory are returned, including C<.> and
3103 C<..>.  The entries are I<not> sorted, but returned in the same
3104 order as the underlying filesystem.
3105
3106 Also this call returns basic file type information about each
3107 file.  The C<ftyp> field will contain one of the following characters:
3108
3109 =over 4
3110
3111 =item 'b'
3112
3113 Block special
3114
3115 =item 'c'
3116
3117 Char special
3118
3119 =item 'd'
3120
3121 Directory
3122
3123 =item 'f'
3124
3125 FIFO (named pipe)
3126
3127 =item 'l'
3128
3129 Symbolic link
3130
3131 =item 'r'
3132
3133 Regular file
3134
3135 =item 's'
3136
3137 Socket
3138
3139 =item 'u'
3140
3141 Unknown file type
3142
3143 =item '?'
3144
3145 The L<readdir(3)> returned a C<d_type> field with an
3146 unexpected value
3147
3148 =back
3149
3150 This function is primarily intended for use by programs.  To
3151 get a simple list of names, use C<guestfs_ls>.  To get a printable
3152 directory for human consumption, use C<guestfs_ll>.");
3153
3154   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3155    [],
3156    "create partitions on a block device",
3157    "\
3158 This is a simplified interface to the C<guestfs_sfdisk>
3159 command, where partition sizes are specified in megabytes
3160 only (rounded to the nearest cylinder) and you don't need
3161 to specify the cyls, heads and sectors parameters which
3162 were rarely if ever used anyway.
3163
3164 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3165 and C<guestfs_part_disk>");
3166
3167   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3168    [],
3169    "determine file type inside a compressed file",
3170    "\
3171 This command runs C<file> after first decompressing C<path>
3172 using C<method>.
3173
3174 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3175
3176 Since 1.0.63, use C<guestfs_file> instead which can now
3177 process compressed files.");
3178
3179   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3180    [],
3181    "list extended attributes of a file or directory",
3182    "\
3183 This call lists the extended attributes of the file or directory
3184 C<path>.
3185
3186 At the system call level, this is a combination of the
3187 L<listxattr(2)> and L<getxattr(2)> calls.
3188
3189 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3190
3191   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3192    [],
3193    "list extended attributes of a file or directory",
3194    "\
3195 This is the same as C<guestfs_getxattrs>, but if C<path>
3196 is a symbolic link, then it returns the extended attributes
3197 of the link itself.");
3198
3199   ("setxattr", (RErr, [String "xattr";
3200                        String "val"; Int "vallen"; (* will be BufferIn *)
3201                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3202    [],
3203    "set extended attribute of a file or directory",
3204    "\
3205 This call sets the extended attribute named C<xattr>
3206 of the file C<path> to the value C<val> (of length C<vallen>).
3207 The value is arbitrary 8 bit data.
3208
3209 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3210
3211   ("lsetxattr", (RErr, [String "xattr";
3212                         String "val"; Int "vallen"; (* will be BufferIn *)
3213                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3214    [],
3215    "set extended attribute of a file or directory",
3216    "\
3217 This is the same as C<guestfs_setxattr>, but if C<path>
3218 is a symbolic link, then it sets an extended attribute
3219 of the link itself.");
3220
3221   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3222    [],
3223    "remove extended attribute of a file or directory",
3224    "\
3225 This call removes the extended attribute named C<xattr>
3226 of the file C<path>.
3227
3228 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3229
3230   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3231    [],
3232    "remove extended attribute of a file or directory",
3233    "\
3234 This is the same as C<guestfs_removexattr>, but if C<path>
3235 is a symbolic link, then it removes an extended attribute
3236 of the link itself.");
3237
3238   ("mountpoints", (RHashtable "mps", []), 147, [],
3239    [],
3240    "show mountpoints",
3241    "\
3242 This call is similar to C<guestfs_mounts>.  That call returns
3243 a list of devices.  This one returns a hash table (map) of
3244 device name to directory where the device is mounted.");
3245
3246   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3247    (* This is a special case: while you would expect a parameter
3248     * of type "Pathname", that doesn't work, because it implies
3249     * NEED_ROOT in the generated calling code in stubs.c, and
3250     * this function cannot use NEED_ROOT.
3251     *)
3252    [],
3253    "create a mountpoint",
3254    "\
3255 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3256 specialized calls that can be used to create extra mountpoints
3257 before mounting the first filesystem.
3258
3259 These calls are I<only> necessary in some very limited circumstances,
3260 mainly the case where you want to mount a mix of unrelated and/or
3261 read-only filesystems together.
3262
3263 For example, live CDs often contain a \"Russian doll\" nest of
3264 filesystems, an ISO outer layer, with a squashfs image inside, with
3265 an ext2/3 image inside that.  You can unpack this as follows
3266 in guestfish:
3267
3268  add-ro Fedora-11-i686-Live.iso
3269  run
3270  mkmountpoint /cd
3271  mkmountpoint /squash
3272  mkmountpoint /ext3
3273  mount /dev/sda /cd
3274  mount-loop /cd/LiveOS/squashfs.img /squash
3275  mount-loop /squash/LiveOS/ext3fs.img /ext3
3276
3277 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3278
3279   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3280    [],
3281    "remove a mountpoint",
3282    "\
3283 This calls removes a mountpoint that was previously created
3284 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3285 for full details.");
3286
3287   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3288    [InitISOFS, Always, TestOutputBuffer (
3289       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3290     (* Test various near large, large and too large files (RHBZ#589039). *)
3291     InitBasicFS, Always, TestLastFail (
3292       [["touch"; "/a"];
3293        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3294        ["read_file"; "/a"]]);
3295     InitBasicFS, Always, TestLastFail (
3296       [["touch"; "/a"];
3297        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3298        ["read_file"; "/a"]]);
3299     InitBasicFS, Always, TestLastFail (
3300       [["touch"; "/a"];
3301        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3302        ["read_file"; "/a"]])],
3303    "read a file",
3304    "\
3305 This calls returns the contents of the file C<path> as a
3306 buffer.
3307
3308 Unlike C<guestfs_cat>, this function can correctly
3309 handle files that contain embedded ASCII NUL characters.
3310 However unlike C<guestfs_download>, this function is limited
3311 in the total size of file that can be handled.");
3312
3313   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3314    [InitISOFS, Always, TestOutputList (
3315       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3316     InitISOFS, Always, TestOutputList (
3317       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3318     (* Test for RHBZ#579608, absolute symbolic links. *)
3319     InitISOFS, Always, TestOutputList (
3320       [["grep"; "nomatch"; "/abssymlink"]], [])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<grep> program and returns the
3324 matching lines.");
3325
3326   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<egrep> program and returns the
3332 matching lines.");
3333
3334   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3335    [InitISOFS, Always, TestOutputList (
3336       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3337    "return lines matching a pattern",
3338    "\
3339 This calls the external C<fgrep> program and returns the
3340 matching lines.");
3341
3342   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3343    [InitISOFS, Always, TestOutputList (
3344       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3345    "return lines matching a pattern",
3346    "\
3347 This calls the external C<grep -i> program and returns the
3348 matching lines.");
3349
3350   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3351    [InitISOFS, Always, TestOutputList (
3352       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3353    "return lines matching a pattern",
3354    "\
3355 This calls the external C<egrep -i> program and returns the
3356 matching lines.");
3357
3358   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3359    [InitISOFS, Always, TestOutputList (
3360       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3361    "return lines matching a pattern",
3362    "\
3363 This calls the external C<fgrep -i> program and returns the
3364 matching lines.");
3365
3366   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3367    [InitISOFS, Always, TestOutputList (
3368       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3369    "return lines matching a pattern",
3370    "\
3371 This calls the external C<zgrep> program and returns the
3372 matching lines.");
3373
3374   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3375    [InitISOFS, Always, TestOutputList (
3376       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3377    "return lines matching a pattern",
3378    "\
3379 This calls the external C<zegrep> program and returns the
3380 matching lines.");
3381
3382   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3383    [InitISOFS, Always, TestOutputList (
3384       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3385    "return lines matching a pattern",
3386    "\
3387 This calls the external C<zfgrep> program and returns the
3388 matching lines.");
3389
3390   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3391    [InitISOFS, Always, TestOutputList (
3392       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3393    "return lines matching a pattern",
3394    "\
3395 This calls the external C<zgrep -i> program and returns the
3396 matching lines.");
3397
3398   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3399    [InitISOFS, Always, TestOutputList (
3400       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3401    "return lines matching a pattern",
3402    "\
3403 This calls the external C<zegrep -i> program and returns the
3404 matching lines.");
3405
3406   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3407    [InitISOFS, Always, TestOutputList (
3408       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3409    "return lines matching a pattern",
3410    "\
3411 This calls the external C<zfgrep -i> program and returns the
3412 matching lines.");
3413
3414   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3415    [InitISOFS, Always, TestOutput (
3416       [["realpath"; "/../directory"]], "/directory")],
3417    "canonicalized absolute pathname",
3418    "\
3419 Return the canonicalized absolute pathname of C<path>.  The
3420 returned path has no C<.>, C<..> or symbolic link path elements.");
3421
3422   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3423    [InitBasicFS, Always, TestOutputStruct (
3424       [["touch"; "/a"];
3425        ["ln"; "/a"; "/b"];
3426        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3427    "create a hard link",
3428    "\
3429 This command creates a hard link using the C<ln> command.");
3430
3431   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3432    [InitBasicFS, Always, TestOutputStruct (
3433       [["touch"; "/a"];
3434        ["touch"; "/b"];
3435        ["ln_f"; "/a"; "/b"];
3436        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437    "create a hard link",
3438    "\
3439 This command creates a hard link using the C<ln -f> command.
3440 The C<-f> option removes the link (C<linkname>) if it exists already.");
3441
3442   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3443    [InitBasicFS, Always, TestOutputStruct (
3444       [["touch"; "/a"];
3445        ["ln_s"; "a"; "/b"];
3446        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3447    "create a symbolic link",
3448    "\
3449 This command creates a symbolic link using the C<ln -s> command.");
3450
3451   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3452    [InitBasicFS, Always, TestOutput (
3453       [["mkdir_p"; "/a/b"];
3454        ["touch"; "/a/b/c"];
3455        ["ln_sf"; "../d"; "/a/b/c"];
3456        ["readlink"; "/a/b/c"]], "../d")],
3457    "create a symbolic link",
3458    "\
3459 This command creates a symbolic link using the C<ln -sf> command,
3460 The C<-f> option removes the link (C<linkname>) if it exists already.");
3461
3462   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3463    [] (* XXX tested above *),
3464    "read the target of a symbolic link",
3465    "\
3466 This command reads the target of a symbolic link.");
3467
3468   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3469    [InitBasicFS, Always, TestOutputStruct (
3470       [["fallocate"; "/a"; "1000000"];
3471        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3472    "preallocate a file in the guest filesystem",
3473    "\
3474 This command preallocates a file (containing zero bytes) named
3475 C<path> of size C<len> bytes.  If the file exists already, it
3476 is overwritten.
3477
3478 Do not confuse this with the guestfish-specific
3479 C<alloc> command which allocates a file in the host and
3480 attaches it as a device.");
3481
3482   ("swapon_device", (RErr, [Device "device"]), 170, [],
3483    [InitPartition, Always, TestRun (
3484       [["mkswap"; "/dev/sda1"];
3485        ["swapon_device"; "/dev/sda1"];
3486        ["swapoff_device"; "/dev/sda1"]])],
3487    "enable swap on device",
3488    "\
3489 This command enables the libguestfs appliance to use the
3490 swap device or partition named C<device>.  The increased
3491 memory is made available for all commands, for example
3492 those run using C<guestfs_command> or C<guestfs_sh>.
3493
3494 Note that you should not swap to existing guest swap
3495 partitions unless you know what you are doing.  They may
3496 contain hibernation information, or other information that
3497 the guest doesn't want you to trash.  You also risk leaking
3498 information about the host to the guest this way.  Instead,
3499 attach a new host device to the guest and swap on that.");
3500
3501   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3502    [], (* XXX tested by swapon_device *)
3503    "disable swap on device",
3504    "\
3505 This command disables the libguestfs appliance swap
3506 device or partition named C<device>.
3507 See C<guestfs_swapon_device>.");
3508
3509   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3510    [InitBasicFS, Always, TestRun (
3511       [["fallocate"; "/swap"; "8388608"];
3512        ["mkswap_file"; "/swap"];
3513        ["swapon_file"; "/swap"];
3514        ["swapoff_file"; "/swap"]])],
3515    "enable swap on file",
3516    "\
3517 This command enables swap to a file.
3518 See C<guestfs_swapon_device> for other notes.");
3519
3520   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3521    [], (* XXX tested by swapon_file *)
3522    "disable swap on file",
3523    "\
3524 This command disables the libguestfs appliance swap on file.");
3525
3526   ("swapon_label", (RErr, [String "label"]), 174, [],
3527    [InitEmpty, Always, TestRun (
3528       [["part_disk"; "/dev/sdb"; "mbr"];
3529        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3530        ["swapon_label"; "swapit"];
3531        ["swapoff_label"; "swapit"];
3532        ["zero"; "/dev/sdb"];
3533        ["blockdev_rereadpt"; "/dev/sdb"]])],
3534    "enable swap on labeled swap partition",
3535    "\
3536 This command enables swap to a labeled swap partition.
3537 See C<guestfs_swapon_device> for other notes.");
3538
3539   ("swapoff_label", (RErr, [String "label"]), 175, [],
3540    [], (* XXX tested by swapon_label *)
3541    "disable swap on labeled swap partition",
3542    "\
3543 This command disables the libguestfs appliance swap on
3544 labeled swap partition.");
3545
3546   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3547    (let uuid = uuidgen () in
3548     [InitEmpty, Always, TestRun (
3549        [["mkswap_U"; uuid; "/dev/sdb"];
3550         ["swapon_uuid"; uuid];
3551         ["swapoff_uuid"; uuid]])]),
3552    "enable swap on swap partition by UUID",
3553    "\
3554 This command enables swap to a swap partition with the given UUID.
3555 See C<guestfs_swapon_device> for other notes.");
3556
3557   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3558    [], (* XXX tested by swapon_uuid *)
3559    "disable swap on swap partition by UUID",
3560    "\
3561 This command disables the libguestfs appliance swap partition
3562 with the given UUID.");
3563
3564   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3565    [InitBasicFS, Always, TestRun (
3566       [["fallocate"; "/swap"; "8388608"];
3567        ["mkswap_file"; "/swap"]])],
3568    "create a swap file",
3569    "\
3570 Create a swap file.
3571
3572 This command just writes a swap file signature to an existing
3573 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3574
3575   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3576    [InitISOFS, Always, TestRun (
3577       [["inotify_init"; "0"]])],
3578    "create an inotify handle",
3579    "\
3580 This command creates a new inotify handle.
3581 The inotify subsystem can be used to notify events which happen to
3582 objects in the guest filesystem.
3583
3584 C<maxevents> is the maximum number of events which will be
3585 queued up between calls to C<guestfs_inotify_read> or
3586 C<guestfs_inotify_files>.
3587 If this is passed as C<0>, then the kernel (or previously set)
3588 default is used.  For Linux 2.6.29 the default was 16384 events.
3589 Beyond this limit, the kernel throws away events, but records
3590 the fact that it threw them away by setting a flag
3591 C<IN_Q_OVERFLOW> in the returned structure list (see
3592 C<guestfs_inotify_read>).
3593
3594 Before any events are generated, you have to add some
3595 watches to the internal watch list.  See:
3596 C<guestfs_inotify_add_watch>,
3597 C<guestfs_inotify_rm_watch> and
3598 C<guestfs_inotify_watch_all>.
3599
3600 Queued up events should be read periodically by calling
3601 C<guestfs_inotify_read>
3602 (or C<guestfs_inotify_files> which is just a helpful
3603 wrapper around C<guestfs_inotify_read>).  If you don't
3604 read the events out often enough then you risk the internal
3605 queue overflowing.
3606
3607 The handle should be closed after use by calling
3608 C<guestfs_inotify_close>.  This also removes any
3609 watches automatically.
3610
3611 See also L<inotify(7)> for an overview of the inotify interface
3612 as exposed by the Linux kernel, which is roughly what we expose
3613 via libguestfs.  Note that there is one global inotify handle
3614 per libguestfs instance.");
3615
3616   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3617    [InitBasicFS, Always, TestOutputList (
3618       [["inotify_init"; "0"];
3619        ["inotify_add_watch"; "/"; "1073741823"];
3620        ["touch"; "/a"];
3621        ["touch"; "/b"];
3622        ["inotify_files"]], ["a"; "b"])],
3623    "add an inotify watch",
3624    "\
3625 Watch C<path> for the events listed in C<mask>.
3626
3627 Note that if C<path> is a directory then events within that
3628 directory are watched, but this does I<not> happen recursively
3629 (in subdirectories).
3630
3631 Note for non-C or non-Linux callers: the inotify events are
3632 defined by the Linux kernel ABI and are listed in
3633 C</usr/include/sys/inotify.h>.");
3634
3635   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3636    [],
3637    "remove an inotify watch",
3638    "\
3639 Remove a previously defined inotify watch.
3640 See C<guestfs_inotify_add_watch>.");
3641
3642   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3643    [],
3644    "return list of inotify events",
3645    "\
3646 Return the complete queue of events that have happened
3647 since the previous read call.
3648
3649 If no events have happened, this returns an empty list.
3650
3651 I<Note>: In order to make sure that all events have been
3652 read, you must call this function repeatedly until it
3653 returns an empty list.  The reason is that the call will
3654 read events up to the maximum appliance-to-host message
3655 size and leave remaining events in the queue.");
3656
3657   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3658    [],
3659    "return list of watched files that had events",
3660    "\
3661 This function is a helpful wrapper around C<guestfs_inotify_read>
3662 which just returns a list of pathnames of objects that were
3663 touched.  The returned pathnames are sorted and deduplicated.");
3664
3665   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3666    [],
3667    "close the inotify handle",
3668    "\
3669 This closes the inotify handle which was previously
3670 opened by inotify_init.  It removes all watches, throws
3671 away any pending events, and deallocates all resources.");
3672
3673   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3674    [],
3675    "set SELinux security context",
3676    "\
3677 This sets the SELinux security context of the daemon
3678 to the string C<context>.
3679
3680 See the documentation about SELINUX in L<guestfs(3)>.");
3681
3682   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3683    [],
3684    "get SELinux security context",
3685    "\
3686 This gets the SELinux security context of the daemon.
3687
3688 See the documentation about SELINUX in L<guestfs(3)>,
3689 and C<guestfs_setcon>");
3690
3691   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3692    [InitEmpty, Always, TestOutput (
3693       [["part_disk"; "/dev/sda"; "mbr"];
3694        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3695        ["mount_options"; ""; "/dev/sda1"; "/"];
3696        ["write_file"; "/new"; "new file contents"; "0"];
3697        ["cat"; "/new"]], "new file contents")],
3698    "make a filesystem with block size",
3699    "\
3700 This call is similar to C<guestfs_mkfs>, but it allows you to
3701 control the block size of the resulting filesystem.  Supported
3702 block sizes depend on the filesystem type, but typically they
3703 are C<1024>, C<2048> or C<4096> only.");
3704
3705   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3706    [InitEmpty, Always, TestOutput (
3707       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3708        ["mke2journal"; "4096"; "/dev/sda1"];
3709        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3710        ["mount_options"; ""; "/dev/sda2"; "/"];
3711        ["write_file"; "/new"; "new file contents"; "0"];
3712        ["cat"; "/new"]], "new file contents")],
3713    "make ext2/3/4 external journal",
3714    "\
3715 This creates an ext2 external journal on C<device>.  It is equivalent
3716 to the command:
3717
3718  mke2fs -O journal_dev -b blocksize device");
3719
3720   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3721    [InitEmpty, Always, TestOutput (
3722       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3723        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3724        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3725        ["mount_options"; ""; "/dev/sda2"; "/"];
3726        ["write_file"; "/new"; "new file contents"; "0"];
3727        ["cat"; "/new"]], "new file contents")],
3728    "make ext2/3/4 external journal with label",
3729    "\
3730 This creates an ext2 external journal on C<device> with label C<label>.");
3731
3732   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3733    (let uuid = uuidgen () in
3734     [InitEmpty, Always, TestOutput (
3735        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3736         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3737         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3738         ["mount_options"; ""; "/dev/sda2"; "/"];
3739         ["write_file"; "/new"; "new file contents"; "0"];
3740         ["cat"; "/new"]], "new file contents")]),
3741    "make ext2/3/4 external journal with UUID",
3742    "\
3743 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3744
3745   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3746    [],
3747    "make ext2/3/4 filesystem with external journal",
3748    "\
3749 This creates an ext2/3/4 filesystem on C<device> with
3750 an external journal on C<journal>.  It is equivalent
3751 to the command:
3752
3753  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3754
3755 See also C<guestfs_mke2journal>.");
3756
3757   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3758    [],
3759    "make ext2/3/4 filesystem with external journal",
3760    "\
3761 This creates an ext2/3/4 filesystem on C<device> with
3762 an external journal on the journal labeled C<label>.
3763
3764 See also C<guestfs_mke2journal_L>.");
3765
3766   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3767    [],
3768    "make ext2/3/4 filesystem with external journal",
3769    "\
3770 This creates an ext2/3/4 filesystem on C<device> with
3771 an external journal on the journal with UUID C<uuid>.
3772
3773 See also C<guestfs_mke2journal_U>.");
3774
3775   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3776    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3777    "load a kernel module",
3778    "\
3779 This loads a kernel module in the appliance.
3780
3781 The kernel module must have been whitelisted when libguestfs
3782 was built (see C<appliance/kmod.whitelist.in> in the source).");
3783
3784   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3785    [InitNone, Always, TestOutput (
3786       [["echo_daemon"; "This is a test"]], "This is a test"
3787     )],
3788    "echo arguments back to the client",
3789    "\
3790 This command concatenate the list of C<words> passed with single spaces between
3791 them and returns the resulting string.
3792
3793 You can use this command to test the connection through to the daemon.
3794
3795 See also C<guestfs_ping_daemon>.");
3796
3797   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3798    [], (* There is a regression test for this. *)
3799    "find all files and directories, returning NUL-separated list",
3800    "\
3801 This command lists out all files and directories, recursively,
3802 starting at C<directory>, placing the resulting list in the
3803 external file called C<files>.
3804
3805 This command works the same way as C<guestfs_find> with the
3806 following exceptions:
3807
3808 =over 4
3809
3810 =item *
3811
3812 The resulting list is written to an external file.
3813
3814 =item *
3815
3816 Items (filenames) in the result are separated
3817 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3818
3819 =item *
3820
3821 This command is not limited in the number of names that it
3822 can return.
3823
3824 =item *
3825
3826 The result list is not sorted.
3827
3828 =back");
3829
3830   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3831    [InitISOFS, Always, TestOutput (
3832       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3833     InitISOFS, Always, TestOutput (
3834       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3835     InitISOFS, Always, TestOutput (
3836       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3837     InitISOFS, Always, TestLastFail (
3838       [["case_sensitive_path"; "/Known-1/"]]);
3839     InitBasicFS, Always, TestOutput (
3840       [["mkdir"; "/a"];
3841        ["mkdir"; "/a/bbb"];
3842        ["touch"; "/a/bbb/c"];
3843        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3844     InitBasicFS, Always, TestOutput (
3845       [["mkdir"; "/a"];
3846        ["mkdir"; "/a/bbb"];
3847        ["touch"; "/a/bbb/c"];
3848        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3849     InitBasicFS, Always, TestLastFail (
3850       [["mkdir"; "/a"];
3851        ["mkdir"; "/a/bbb"];
3852        ["touch"; "/a/bbb/c"];
3853        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3854    "return true path on case-insensitive filesystem",
3855    "\
3856 This can be used to resolve case insensitive paths on
3857 a filesystem which is case sensitive.  The use case is
3858 to resolve paths which you have read from Windows configuration
3859 files or the Windows Registry, to the true path.
3860
3861 The command handles a peculiarity of the Linux ntfs-3g
3862 filesystem driver (and probably others), which is that although
3863 the underlying filesystem is case-insensitive, the driver
3864 exports the filesystem to Linux as case-sensitive.
3865
3866 One consequence of this is that special directories such
3867 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3868 (or other things) depending on the precise details of how
3869 they were created.  In Windows itself this would not be
3870 a problem.
3871
3872 Bug or feature?  You decide:
3873 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3874
3875 This function resolves the true case of each element in the
3876 path and returns the case-sensitive path.
3877
3878 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3879 might return C<\"/WINDOWS/system32\"> (the exact return value
3880 would depend on details of how the directories were originally
3881 created under Windows).
3882
3883 I<Note>:
3884 This function does not handle drive names, backslashes etc.
3885
3886 See also C<guestfs_realpath>.");
3887
3888   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3889    [InitBasicFS, Always, TestOutput (
3890       [["vfs_type"; "/dev/sda1"]], "ext2")],
3891    "get the Linux VFS type corresponding to a mounted device",
3892    "\
3893 This command gets the block device type corresponding to
3894 a mounted device called C<device>.
3895
3896 Usually the result is the name of the Linux VFS module that
3897 is used to mount this device (probably determined automatically
3898 if you used the C<guestfs_mount> call).");
3899
3900   ("truncate", (RErr, [Pathname "path"]), 199, [],
3901    [InitBasicFS, Always, TestOutputStruct (
3902       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3903        ["truncate"; "/test"];
3904        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3905    "truncate a file to zero size",
3906    "\
3907 This command truncates C<path> to a zero-length file.  The
3908 file must exist already.");
3909
3910   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3911    [InitBasicFS, Always, TestOutputStruct (
3912       [["touch"; "/test"];
3913        ["truncate_size"; "/test"; "1000"];
3914        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3915    "truncate a file to a particular size",
3916    "\
3917 This command truncates C<path> to size C<size> bytes.  The file
3918 must exist already.  If the file is smaller than C<size> then
3919 the file is extended to the required size with null bytes.");
3920
3921   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3922    [InitBasicFS, Always, TestOutputStruct (
3923       [["touch"; "/test"];
3924        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3925        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3926    "set timestamp of a file with nanosecond precision",
3927    "\
3928 This command sets the timestamps of a file with nanosecond
3929 precision.
3930
3931 C<atsecs, atnsecs> are the last access time (atime) in secs and
3932 nanoseconds from the epoch.
3933
3934 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3935 secs and nanoseconds from the epoch.
3936
3937 If the C<*nsecs> field contains the special value C<-1> then
3938 the corresponding timestamp is set to the current time.  (The
3939 C<*secs> field is ignored in this case).
3940
3941 If the C<*nsecs> field contains the special value C<-2> then
3942 the corresponding timestamp is left unchanged.  (The
3943 C<*secs> field is ignored in this case).");
3944
3945   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3946    [InitBasicFS, Always, TestOutputStruct (
3947       [["mkdir_mode"; "/test"; "0o111"];
3948        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3949    "create a directory with a particular mode",
3950    "\
3951 This command creates a directory, setting the initial permissions
3952 of the directory to C<mode>.
3953
3954 For common Linux filesystems, the actual mode which is set will
3955 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3956 interpret the mode in other ways.
3957
3958 See also C<guestfs_mkdir>, C<guestfs_umask>");
3959
3960   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3961    [], (* XXX *)
3962    "change file owner and group",
3963    "\
3964 Change the file owner to C<owner> and group to C<group>.
3965 This is like C<guestfs_chown> but if C<path> is a symlink then
3966 the link itself is changed, not the target.
3967
3968 Only numeric uid and gid are supported.  If you want to use
3969 names, you will need to locate and parse the password file
3970 yourself (Augeas support makes this relatively easy).");
3971
3972   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3973    [], (* XXX *)
3974    "lstat on multiple files",
3975    "\
3976 This call allows you to perform the C<guestfs_lstat> operation
3977 on multiple files, where all files are in the directory C<path>.
3978 C<names> is the list of files from this directory.
3979
3980 On return you get a list of stat structs, with a one-to-one
3981 correspondence to the C<names> list.  If any name did not exist
3982 or could not be lstat'd, then the C<ino> field of that structure
3983 is set to C<-1>.
3984
3985 This call is intended for programs that want to efficiently
3986 list a directory contents without making many round-trips.
3987 See also C<guestfs_lxattrlist> for a similarly efficient call
3988 for getting extended attributes.  Very long directory listings
3989 might cause the protocol message size to be exceeded, causing
3990 this call to fail.  The caller must split up such requests
3991 into smaller groups of names.");
3992
3993   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3994    [], (* XXX *)
3995    "lgetxattr on multiple files",
3996    "\
3997 This call allows you to get the extended attributes
3998 of multiple files, where all files are in the directory C<path>.
3999 C<names> is the list of files from this directory.
4000
4001 On return you get a flat list of xattr structs which must be
4002 interpreted sequentially.  The first xattr struct always has a zero-length
4003 C<attrname>.  C<attrval> in this struct is zero-length
4004 to indicate there was an error doing C<lgetxattr> for this
4005 file, I<or> is a C string which is a decimal number
4006 (the number of following attributes for this file, which could
4007 be C<\"0\">).  Then after the first xattr struct are the
4008 zero or more attributes for the first named file.
4009 This repeats for the second and subsequent files.
4010
4011 This call is intended for programs that want to efficiently
4012 list a directory contents without making many round-trips.
4013 See also C<guestfs_lstatlist> for a similarly efficient call
4014 for getting standard stats.  Very long directory listings
4015 might cause the protocol message size to be exceeded, causing
4016 this call to fail.  The caller must split up such requests
4017 into smaller groups of names.");
4018
4019   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4020    [], (* XXX *)
4021    "readlink on multiple files",
4022    "\
4023 This call allows you to do a C<readlink> operation
4024 on multiple files, where all files are in the directory C<path>.
4025 C<names> is the list of files from this directory.
4026
4027 On return you get a list of strings, with a one-to-one
4028 correspondence to the C<names> list.  Each string is the
4029 value of the symbol link.
4030
4031 If the C<readlink(2)> operation fails on any name, then
4032 the corresponding result string is the empty string C<\"\">.
4033 However the whole operation is completed even if there
4034 were C<readlink(2)> errors, and so you can call this
4035 function with names where you don't know if they are
4036 symbolic links already (albeit slightly less efficient).
4037
4038 This call is intended for programs that want to efficiently
4039 list a directory contents without making many round-trips.
4040 Very long directory listings might cause the protocol
4041 message size to be exceeded, causing
4042 this call to fail.  The caller must split up such requests
4043 into smaller groups of names.");
4044
4045   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4046    [InitISOFS, Always, TestOutputBuffer (
4047       [["pread"; "/known-4"; "1"; "3"]], "\n");
4048     InitISOFS, Always, TestOutputBuffer (
4049       [["pread"; "/empty"; "0"; "100"]], "")],
4050    "read part of a file",
4051    "\
4052 This command lets you read part of a file.  It reads C<count>
4053 bytes of the file, starting at C<offset>, from file C<path>.
4054
4055 This may read fewer bytes than requested.  For further details
4056 see the L<pread(2)> system call.");
4057
4058   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4059    [InitEmpty, Always, TestRun (
4060       [["part_init"; "/dev/sda"; "gpt"]])],
4061    "create an empty partition table",
4062    "\
4063 This creates an empty partition table on C<device> of one of the
4064 partition types listed below.  Usually C<parttype> should be
4065 either C<msdos> or C<gpt> (for large disks).
4066
4067 Initially there are no partitions.  Following this, you should
4068 call C<guestfs_part_add> for each partition required.
4069
4070 Possible values for C<parttype> are:
4071
4072 =over 4
4073
4074 =item B<efi> | B<gpt>
4075
4076 Intel EFI / GPT partition table.
4077
4078 This is recommended for >= 2 TB partitions that will be accessed
4079 from Linux and Intel-based Mac OS X.  It also has limited backwards
4080 compatibility with the C<mbr> format.
4081
4082 =item B<mbr> | B<msdos>
4083
4084 The standard PC \"Master Boot Record\" (MBR) format used
4085 by MS-DOS and Windows.  This partition type will B<only> work
4086 for device sizes up to 2 TB.  For large disks we recommend
4087 using C<gpt>.
4088
4089 =back
4090
4091 Other partition table types that may work but are not
4092 supported include:
4093
4094 =over 4
4095
4096 =item B<aix>
4097
4098 AIX disk labels.
4099
4100 =item B<amiga> | B<rdb>
4101
4102 Amiga \"Rigid Disk Block\" format.
4103
4104 =item B<bsd>
4105
4106 BSD disk labels.
4107
4108 =item B<dasd>
4109
4110 DASD, used on IBM mainframes.
4111
4112 =item B<dvh>
4113
4114 MIPS/SGI volumes.
4115
4116 =item B<mac>
4117
4118 Old Mac partition format.  Modern Macs use C<gpt>.
4119
4120 =item B<pc98>
4121
4122 NEC PC-98 format, common in Japan apparently.
4123
4124 =item B<sun>
4125
4126 Sun disk labels.
4127
4128 =back");
4129
4130   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4131    [InitEmpty, Always, TestRun (
4132       [["part_init"; "/dev/sda"; "mbr"];
4133        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4134     InitEmpty, Always, TestRun (
4135       [["part_init"; "/dev/sda"; "gpt"];
4136        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4137        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4138     InitEmpty, Always, TestRun (
4139       [["part_init"; "/dev/sda"; "mbr"];
4140        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4141        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4142        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4143        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4144    "add a partition to the device",
4145    "\
4146 This command adds a partition to C<device>.  If there is no partition
4147 table on the device, call C<guestfs_part_init> first.
4148
4149 The C<prlogex> parameter is the type of partition.  Normally you
4150 should pass C<p> or C<primary> here, but MBR partition tables also
4151 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4152 types.
4153
4154 C<startsect> and C<endsect> are the start and end of the partition
4155 in I<sectors>.  C<endsect> may be negative, which means it counts
4156 backwards from the end of the disk (C<-1> is the last sector).
4157
4158 Creating a partition which covers the whole disk is not so easy.
4159 Use C<guestfs_part_disk> to do that.");
4160
4161   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4162    [InitEmpty, Always, TestRun (
4163       [["part_disk"; "/dev/sda"; "mbr"]]);
4164     InitEmpty, Always, TestRun (
4165       [["part_disk"; "/dev/sda"; "gpt"]])],
4166    "partition whole disk with a single primary partition",
4167    "\
4168 This command is simply a combination of C<guestfs_part_init>
4169 followed by C<guestfs_part_add> to create a single primary partition
4170 covering the whole disk.
4171
4172 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4173 but other possible values are described in C<guestfs_part_init>.");
4174
4175   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4176    [InitEmpty, Always, TestRun (
4177       [["part_disk"; "/dev/sda"; "mbr"];
4178        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4179    "make a partition bootable",
4180    "\
4181 This sets the bootable flag on partition numbered C<partnum> on
4182 device C<device>.  Note that partitions are numbered from 1.
4183
4184 The bootable flag is used by some operating systems (notably
4185 Windows) to determine which partition to boot from.  It is by
4186 no means universally recognized.");
4187
4188   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4189    [InitEmpty, Always, TestRun (
4190       [["part_disk"; "/dev/sda"; "gpt"];
4191        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4192    "set partition name",
4193    "\
4194 This sets the partition name on partition numbered C<partnum> on
4195 device C<device>.  Note that partitions are numbered from 1.
4196
4197 The partition name can only be set on certain types of partition
4198 table.  This works on C<gpt> but not on C<mbr> partitions.");
4199
4200   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4201    [], (* XXX Add a regression test for this. *)
4202    "list partitions on a device",
4203    "\
4204 This command parses the partition table on C<device> and
4205 returns the list of partitions found.
4206
4207 The fields in the returned structure are:
4208
4209 =over 4
4210
4211 =item B<part_num>
4212
4213 Partition number, counting from 1.
4214
4215 =item B<part_start>
4216
4217 Start of the partition I<in bytes>.  To get sectors you have to
4218 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4219
4220 =item B<part_end>
4221
4222 End of the partition in bytes.
4223
4224 =item B<part_size>
4225
4226 Size of the partition in bytes.
4227
4228 =back");
4229
4230   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4231    [InitEmpty, Always, TestOutput (
4232       [["part_disk"; "/dev/sda"; "gpt"];
4233        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4234    "get the partition table type",
4235    "\
4236 This command examines the partition table on C<device> and
4237 returns the partition table type (format) being used.
4238
4239 Common return values include: C<msdos> (a DOS/Windows style MBR
4240 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4241 values are possible, although unusual.  See C<guestfs_part_init>
4242 for a full list.");
4243
4244   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4245    [InitBasicFS, Always, TestOutputBuffer (
4246       [["fill"; "0x63"; "10"; "/test"];
4247        ["read_file"; "/test"]], "cccccccccc")],
4248    "fill a file with octets",
4249    "\
4250 This command creates a new file called C<path>.  The initial
4251 content of the file is C<len> octets of C<c>, where C<c>
4252 must be a number in the range C<[0..255]>.
4253
4254 To fill a file with zero bytes (sparsely), it is
4255 much more efficient to use C<guestfs_truncate_size>.
4256 To create a file with a pattern of repeating bytes
4257 use C<guestfs_fill_pattern>.");
4258
4259   ("available", (RErr, [StringList "groups"]), 216, [],
4260    [InitNone, Always, TestRun [["available"; ""]]],
4261    "test availability of some parts of the API",
4262    "\
4263 This command is used to check the availability of some
4264 groups of functionality in the appliance, which not all builds of
4265 the libguestfs appliance will be able to provide.
4266
4267 The libguestfs groups, and the functions that those
4268 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4269
4270 The argument C<groups> is a list of group names, eg:
4271 C<[\"inotify\", \"augeas\"]> would check for the availability of
4272 the Linux inotify functions and Augeas (configuration file
4273 editing) functions.
4274
4275 The command returns no error if I<all> requested groups are available.
4276
4277 It fails with an error if one or more of the requested
4278 groups is unavailable in the appliance.
4279
4280 If an unknown group name is included in the
4281 list of groups then an error is always returned.
4282
4283 I<Notes:>
4284
4285 =over 4
4286
4287 =item *
4288
4289 You must call C<guestfs_launch> before calling this function.
4290
4291 The reason is because we don't know what groups are
4292 supported by the appliance/daemon until it is running and can
4293 be queried.
4294
4295 =item *
4296
4297 If a group of functions is available, this does not necessarily
4298 mean that they will work.  You still have to check for errors
4299 when calling individual API functions even if they are
4300 available.
4301
4302 =item *
4303
4304 It is usually the job of distro packagers to build
4305 complete functionality into the libguestfs appliance.
4306 Upstream libguestfs, if built from source with all
4307 requirements satisfied, will support everything.
4308
4309 =item *
4310
4311 This call was added in version C<1.0.80>.  In previous
4312 versions of libguestfs all you could do would be to speculatively
4313 execute a command to find out if the daemon implemented it.
4314 See also C<guestfs_version>.
4315
4316 =back");
4317
4318   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4319    [InitBasicFS, Always, TestOutputBuffer (
4320       [["write_file"; "/src"; "hello, world"; "0"];
4321        ["dd"; "/src"; "/dest"];
4322        ["read_file"; "/dest"]], "hello, world")],
4323    "copy from source to destination using dd",
4324    "\
4325 This command copies from one source device or file C<src>
4326 to another destination device or file C<dest>.  Normally you
4327 would use this to copy to or from a device or partition, for
4328 example to duplicate a filesystem.
4329
4330 If the destination is a device, it must be as large or larger
4331 than the source file or device, otherwise the copy will fail.
4332 This command cannot do partial copies (see C<guestfs_copy_size>).");
4333
4334   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4335    [InitBasicFS, Always, TestOutputInt (
4336       [["write_file"; "/file"; "hello, world"; "0"];
4337        ["filesize"; "/file"]], 12)],
4338    "return the size of the file in bytes",
4339    "\
4340 This command returns the size of C<file> in bytes.
4341
4342 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4343 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4344 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4345
4346   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4347    [InitBasicFSonLVM, Always, TestOutputList (
4348       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4349        ["lvs"]], ["/dev/VG/LV2"])],
4350    "rename an LVM logical volume",
4351    "\
4352 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4353
4354   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4355    [InitBasicFSonLVM, Always, TestOutputList (
4356       [["umount"; "/"];
4357        ["vg_activate"; "false"; "VG"];
4358        ["vgrename"; "VG"; "VG2"];
4359        ["vg_activate"; "true"; "VG2"];
4360        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4361        ["vgs"]], ["VG2"])],
4362    "rename an LVM volume group",
4363    "\
4364 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4365
4366   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4367    [InitISOFS, Always, TestOutputBuffer (
4368       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4369    "list the contents of a single file in an initrd",
4370    "\
4371 This command unpacks the file C<filename> from the initrd file
4372 called C<initrdpath>.  The filename must be given I<without> the
4373 initial C</> character.
4374
4375 For example, in guestfish you could use the following command
4376 to examine the boot script (usually called C</init>)
4377 contained in a Linux initrd or initramfs image:
4378
4379  initrd-cat /boot/initrd-<version>.img init
4380
4381 See also C<guestfs_initrd_list>.");
4382
4383   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4384    [],
4385    "get the UUID of a physical volume",
4386    "\
4387 This command returns the UUID of the LVM PV C<device>.");
4388
4389   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4390    [],
4391    "get the UUID of a volume group",
4392    "\
4393 This command returns the UUID of the LVM VG named C<vgname>.");
4394
4395   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4396    [],
4397    "get the UUID of a logical volume",
4398    "\
4399 This command returns the UUID of the LVM LV C<device>.");
4400
4401   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4402    [],
4403    "get the PV UUIDs containing the volume group",
4404    "\
4405 Given a VG called C<vgname>, this returns the UUIDs of all
4406 the physical volumes that this volume group resides on.
4407
4408 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4409 calls to associate physical volumes and volume groups.
4410
4411 See also C<guestfs_vglvuuids>.");
4412
4413   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4414    [],
4415    "get the LV UUIDs of all LVs in the volume group",
4416    "\
4417 Given a VG called C<vgname>, this returns the UUIDs of all
4418 the logical volumes created in this volume group.
4419
4420 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4421 calls to associate logical volumes and volume groups.
4422
4423 See also C<guestfs_vgpvuuids>.");
4424
4425   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4426    [InitBasicFS, Always, TestOutputBuffer (
4427       [["write_file"; "/src"; "hello, world"; "0"];
4428        ["copy_size"; "/src"; "/dest"; "5"];
4429        ["read_file"; "/dest"]], "hello")],
4430    "copy size bytes from source to destination using dd",
4431    "\
4432 This command copies exactly C<size> bytes from one source device
4433 or file C<src> to another destination device or file C<dest>.
4434
4435 Note this will fail if the source is too short or if the destination
4436 is not large enough.");
4437
4438   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4439    [InitBasicFSonLVM, Always, TestRun (
4440       [["zero_device"; "/dev/VG/LV"]])],
4441    "write zeroes to an entire device",
4442    "\
4443 This command writes zeroes over the entire C<device>.  Compare
4444 with C<guestfs_zero> which just zeroes the first few blocks of
4445 a device.");
4446
4447   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4448    [InitBasicFS, Always, TestOutput (
4449       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4450        ["cat"; "/hello"]], "hello\n")],
4451    "unpack compressed tarball to directory",
4452    "\
4453 This command uploads and unpacks local file C<tarball> (an
4454 I<xz compressed> tar file) into C<directory>.");
4455
4456   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4457    [],
4458    "pack directory into compressed tarball",
4459    "\
4460 This command packs the contents of C<directory> and downloads
4461 it to local file C<tarball> (as an xz compressed tar archive).");
4462
4463   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4464    [],
4465    "resize an NTFS filesystem",
4466    "\
4467 This command resizes an NTFS filesystem, expanding or
4468 shrinking it to the size of the underlying device.
4469 See also L<ntfsresize(8)>.");
4470
4471   ("vgscan", (RErr, []), 232, [],
4472    [InitEmpty, Always, TestRun (
4473       [["vgscan"]])],
4474    "rescan for LVM physical volumes, volume groups and logical volumes",
4475    "\
4476 This rescans all block devices and rebuilds the list of LVM
4477 physical volumes, volume groups and logical volumes.");
4478
4479   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4480    [InitEmpty, Always, TestRun (
4481       [["part_init"; "/dev/sda"; "mbr"];
4482        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4483        ["part_del"; "/dev/sda"; "1"]])],
4484    "delete a partition",
4485    "\
4486 This command deletes the partition numbered C<partnum> on C<device>.
4487
4488 Note that in the case of MBR partitioning, deleting an
4489 extended partition also deletes any logical partitions
4490 it contains.");
4491
4492   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4493    [InitEmpty, Always, TestOutputTrue (
4494       [["part_init"; "/dev/sda"; "mbr"];
4495        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4496        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4497        ["part_get_bootable"; "/dev/sda"; "1"]])],
4498    "return true if a partition is bootable",
4499    "\
4500 This command returns true if the partition C<partnum> on
4501 C<device> has the bootable flag set.
4502
4503 See also C<guestfs_part_set_bootable>.");
4504
4505   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4506    [InitEmpty, Always, TestOutputInt (
4507       [["part_init"; "/dev/sda"; "mbr"];
4508        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4509        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4510        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4511    "get the MBR type byte (ID byte) from a partition",
4512    "\
4513 Returns the MBR type byte (also known as the ID byte) from
4514 the numbered partition C<partnum>.
4515
4516 Note that only MBR (old DOS-style) partitions have type bytes.
4517 You will get undefined results for other partition table
4518 types (see C<guestfs_part_get_parttype>).");
4519
4520   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4521    [], (* tested by part_get_mbr_id *)
4522    "set the MBR type byte (ID byte) of a partition",
4523    "\
4524 Sets the MBR type byte (also known as the ID byte) of
4525 the numbered partition C<partnum> to C<idbyte>.  Note
4526 that the type bytes quoted in most documentation are
4527 in fact hexadecimal numbers, but usually documented
4528 without any leading \"0x\" which might be confusing.
4529
4530 Note that only MBR (old DOS-style) partitions have type bytes.
4531 You will get undefined results for other partition table
4532 types (see C<guestfs_part_get_parttype>).");
4533
4534   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4535    [InitISOFS, Always, TestOutput (
4536       [["checksum_device"; "md5"; "/dev/sdd"]],
4537       (Digest.to_hex (Digest.file "images/test.iso")))],
4538    "compute MD5, SHAx or CRC checksum of the contents of a device",
4539    "\
4540 This call computes the MD5, SHAx or CRC checksum of the
4541 contents of the device named C<device>.  For the types of
4542 checksums supported see the C<guestfs_checksum> command.");
4543
4544   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4545    [InitNone, Always, TestRun (
4546       [["part_disk"; "/dev/sda"; "mbr"];
4547        ["pvcreate"; "/dev/sda1"];
4548        ["vgcreate"; "VG"; "/dev/sda1"];
4549        ["lvcreate"; "LV"; "VG"; "10"];
4550        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4551    "expand an LV to fill free space",
4552    "\
4553 This expands an existing logical volume C<lv> so that it fills
4554 C<pc>% of the remaining free space in the volume group.  Commonly
4555 you would call this with pc = 100 which expands the logical volume
4556 as much as possible, using all remaining free space in the volume
4557 group.");
4558
4559   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4560    [], (* XXX Augeas code needs tests. *)
4561    "clear Augeas path",
4562    "\
4563 Set the value associated with C<path> to C<NULL>.  This
4564 is the same as the L<augtool(1)> C<clear> command.");
4565
4566   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4567    [InitEmpty, Always, TestOutputInt (
4568       [["get_umask"]], 0o22)],
4569    "get the current umask",
4570    "\
4571 Return the current umask.  By default the umask is C<022>
4572 unless it has been set by calling C<guestfs_umask>.");
4573
4574   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4575    [],
4576    "upload a file to the appliance (internal use only)",
4577    "\
4578 The C<guestfs_debug_upload> command uploads a file to
4579 the libguestfs appliance.
4580
4581 There is no comprehensive help for this command.  You have
4582 to look at the file C<daemon/debug.c> in the libguestfs source
4583 to find out what it is for.");
4584
4585   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4586    [InitBasicFS, Always, TestOutput (
4587       [["base64_in"; "../images/hello.b64"; "/hello"];
4588        ["cat"; "/hello"]], "hello\n")],
4589    "upload base64-encoded data to file",
4590    "\
4591 This command uploads base64-encoded data from C<base64file>
4592 to C<filename>.");
4593
4594   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4595    [],
4596    "download file and encode as base64",
4597    "\
4598 This command downloads the contents of C<filename>, writing
4599 it out to local file C<base64file> encoded as base64.");
4600
4601   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4602    [],
4603    "compute MD5, SHAx or CRC checksum of files in a directory",
4604    "\
4605 This command computes the checksums of all regular files in
4606 C<directory> and then emits a list of those checksums to
4607 the local output file C<sumsfile>.
4608
4609 This can be used for verifying the integrity of a virtual
4610 machine.  However to be properly secure you should pay
4611 attention to the output of the checksum command (it uses
4612 the ones from GNU coreutils).  In particular when the
4613 filename is not printable, coreutils uses a special
4614 backslash syntax.  For more information, see the GNU
4615 coreutils info file.");
4616
4617   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4618    [InitBasicFS, Always, TestOutputBuffer (
4619       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4620        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4621    "fill a file with a repeating pattern of bytes",
4622    "\
4623 This function is like C<guestfs_fill> except that it creates
4624 a new file of length C<len> containing the repeating pattern
4625 of bytes in C<pattern>.  The pattern is truncated if necessary
4626 to ensure the length of the file is exactly C<len> bytes.");
4627
4628 ]
4629
4630 let all_functions = non_daemon_functions @ daemon_functions
4631
4632 (* In some places we want the functions to be displayed sorted
4633  * alphabetically, so this is useful:
4634  *)
4635 let all_functions_sorted =
4636   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4637                compare n1 n2) all_functions
4638
4639 (* This is used to generate the src/MAX_PROC_NR file which
4640  * contains the maximum procedure number, a surrogate for the
4641  * ABI version number.  See src/Makefile.am for the details.
4642  *)
4643 let max_proc_nr =
4644   let proc_nrs = List.map (
4645     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4646   ) daemon_functions in
4647   List.fold_left max 0 proc_nrs
4648
4649 (* Field types for structures. *)
4650 type field =
4651   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4652   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4653   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4654   | FUInt32
4655   | FInt32
4656   | FUInt64
4657   | FInt64
4658   | FBytes                      (* Any int measure that counts bytes. *)
4659   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4660   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4661
4662 (* Because we generate extra parsing code for LVM command line tools,
4663  * we have to pull out the LVM columns separately here.
4664  *)
4665 let lvm_pv_cols = [
4666   "pv_name", FString;
4667   "pv_uuid", FUUID;
4668   "pv_fmt", FString;
4669   "pv_size", FBytes;
4670   "dev_size", FBytes;
4671   "pv_free", FBytes;
4672   "pv_used", FBytes;
4673   "pv_attr", FString (* XXX *);
4674   "pv_pe_count", FInt64;
4675   "pv_pe_alloc_count", FInt64;
4676   "pv_tags", FString;
4677   "pe_start", FBytes;
4678   "pv_mda_count", FInt64;
4679   "pv_mda_free", FBytes;
4680   (* Not in Fedora 10:
4681      "pv_mda_size", FBytes;
4682   *)
4683 ]
4684 let lvm_vg_cols = [
4685   "vg_name", FString;
4686   "vg_uuid", FUUID;
4687   "vg_fmt", FString;
4688   "vg_attr", FString (* XXX *);
4689   "vg_size", FBytes;
4690   "vg_free", FBytes;
4691   "vg_sysid", FString;
4692   "vg_extent_size", FBytes;
4693   "vg_extent_count", FInt64;
4694   "vg_free_count", FInt64;
4695   "max_lv", FInt64;
4696   "max_pv", FInt64;
4697   "pv_count", FInt64;
4698   "lv_count", FInt64;
4699   "snap_count", FInt64;
4700   "vg_seqno", FInt64;
4701   "vg_tags", FString;
4702   "vg_mda_count", FInt64;
4703   "vg_mda_free", FBytes;
4704   (* Not in Fedora 10:
4705      "vg_mda_size", FBytes;
4706   *)
4707 ]
4708 let lvm_lv_cols = [
4709   "lv_name", FString;
4710   "lv_uuid", FUUID;
4711   "lv_attr", FString (* XXX *);
4712   "lv_major", FInt64;
4713   "lv_minor", FInt64;
4714   "lv_kernel_major", FInt64;
4715   "lv_kernel_minor", FInt64;
4716   "lv_size", FBytes;
4717   "seg_count", FInt64;
4718   "origin", FString;
4719   "snap_percent", FOptPercent;
4720   "copy_percent", FOptPercent;
4721   "move_pv", FString;
4722   "lv_tags", FString;
4723   "mirror_log", FString;
4724   "modules", FString;
4725 ]
4726
4727 (* Names and fields in all structures (in RStruct and RStructList)
4728  * that we support.
4729  *)
4730 let structs = [
4731   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4732    * not use this struct in any new code.
4733    *)
4734   "int_bool", [
4735     "i", FInt32;                (* for historical compatibility *)
4736     "b", FInt32;                (* for historical compatibility *)
4737   ];
4738
4739   (* LVM PVs, VGs, LVs. *)
4740   "lvm_pv", lvm_pv_cols;
4741   "lvm_vg", lvm_vg_cols;
4742   "lvm_lv", lvm_lv_cols;
4743
4744   (* Column names and types from stat structures.
4745    * NB. Can't use things like 'st_atime' because glibc header files
4746    * define some of these as macros.  Ugh.
4747    *)
4748   "stat", [
4749     "dev", FInt64;
4750     "ino", FInt64;
4751     "mode", FInt64;
4752     "nlink", FInt64;
4753     "uid", FInt64;
4754     "gid", FInt64;
4755     "rdev", FInt64;
4756     "size", FInt64;
4757     "blksize", FInt64;
4758     "blocks", FInt64;
4759     "atime", FInt64;
4760     "mtime", FInt64;
4761     "ctime", FInt64;
4762   ];
4763   "statvfs", [
4764     "bsize", FInt64;
4765     "frsize", FInt64;
4766     "blocks", FInt64;
4767     "bfree", FInt64;
4768     "bavail", FInt64;
4769     "files", FInt64;
4770     "ffree", FInt64;
4771     "favail", FInt64;
4772     "fsid", FInt64;
4773     "flag", FInt64;
4774     "namemax", FInt64;
4775   ];
4776
4777   (* Column names in dirent structure. *)
4778   "dirent", [
4779     "ino", FInt64;
4780     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4781     "ftyp", FChar;
4782     "name", FString;
4783   ];
4784
4785   (* Version numbers. *)
4786   "version", [
4787     "major", FInt64;
4788     "minor", FInt64;
4789     "release", FInt64;
4790     "extra", FString;
4791   ];
4792
4793   (* Extended attribute. *)
4794   "xattr", [
4795     "attrname", FString;
4796     "attrval", FBuffer;
4797   ];
4798
4799   (* Inotify events. *)
4800   "inotify_event", [
4801     "in_wd", FInt64;
4802     "in_mask", FUInt32;
4803     "in_cookie", FUInt32;
4804     "in_name", FString;
4805   ];
4806
4807   (* Partition table entry. *)
4808   "partition", [
4809     "part_num", FInt32;
4810     "part_start", FBytes;
4811     "part_end", FBytes;
4812     "part_size", FBytes;
4813   ];
4814 ] (* end of structs *)
4815
4816 (* Ugh, Java has to be different ..
4817  * These names are also used by the Haskell bindings.
4818  *)
4819 let java_structs = [
4820   "int_bool", "IntBool";
4821   "lvm_pv", "PV";
4822   "lvm_vg", "VG";
4823   "lvm_lv", "LV";
4824   "stat", "Stat";
4825   "statvfs", "StatVFS";
4826   "dirent", "Dirent";
4827   "version", "Version";
4828   "xattr", "XAttr";
4829   "inotify_event", "INotifyEvent";
4830   "partition", "Partition";
4831 ]
4832
4833 (* What structs are actually returned. *)
4834 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4835
4836 (* Returns a list of RStruct/RStructList structs that are returned
4837  * by any function.  Each element of returned list is a pair:
4838  *
4839  * (structname, RStructOnly)
4840  *    == there exists function which returns RStruct (_, structname)
4841  * (structname, RStructListOnly)
4842  *    == there exists function which returns RStructList (_, structname)
4843  * (structname, RStructAndList)
4844  *    == there are functions returning both RStruct (_, structname)
4845  *                                      and RStructList (_, structname)
4846  *)
4847 let rstructs_used_by functions =
4848   (* ||| is a "logical OR" for rstructs_used_t *)
4849   let (|||) a b =
4850     match a, b with
4851     | RStructAndList, _
4852     | _, RStructAndList -> RStructAndList
4853     | RStructOnly, RStructListOnly
4854     | RStructListOnly, RStructOnly -> RStructAndList
4855     | RStructOnly, RStructOnly -> RStructOnly
4856     | RStructListOnly, RStructListOnly -> RStructListOnly
4857   in
4858
4859   let h = Hashtbl.create 13 in
4860
4861   (* if elem->oldv exists, update entry using ||| operator,
4862    * else just add elem->newv to the hash
4863    *)
4864   let update elem newv =
4865     try  let oldv = Hashtbl.find h elem in
4866          Hashtbl.replace h elem (newv ||| oldv)
4867     with Not_found -> Hashtbl.add h elem newv
4868   in
4869
4870   List.iter (
4871     fun (_, style, _, _, _, _, _) ->
4872       match fst style with
4873       | RStruct (_, structname) -> update structname RStructOnly
4874       | RStructList (_, structname) -> update structname RStructListOnly
4875       | _ -> ()
4876   ) functions;
4877
4878   (* return key->values as a list of (key,value) *)
4879   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4880
4881 (* Used for testing language bindings. *)
4882 type callt =
4883   | CallString of string
4884   | CallOptString of string option
4885   | CallStringList of string list
4886   | CallInt of int
4887   | CallInt64 of int64
4888   | CallBool of bool
4889
4890 (* Used to memoize the result of pod2text. *)
4891 let pod2text_memo_filename = "src/.pod2text.data"
4892 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4893   try
4894     let chan = open_in pod2text_memo_filename in
4895     let v = input_value chan in
4896     close_in chan;
4897     v
4898   with
4899     _ -> Hashtbl.create 13
4900 let pod2text_memo_updated () =
4901   let chan = open_out pod2text_memo_filename in
4902   output_value chan pod2text_memo;
4903   close_out chan
4904
4905 (* Useful functions.
4906  * Note we don't want to use any external OCaml libraries which
4907  * makes this a bit harder than it should be.
4908  *)
4909 module StringMap = Map.Make (String)
4910
4911 let failwithf fs = ksprintf failwith fs
4912
4913 let unique = let i = ref 0 in fun () -> incr i; !i
4914
4915 let replace_char s c1 c2 =
4916   let s2 = String.copy s in
4917   let r = ref false in
4918   for i = 0 to String.length s2 - 1 do
4919     if String.unsafe_get s2 i = c1 then (
4920       String.unsafe_set s2 i c2;
4921       r := true
4922     )
4923   done;
4924   if not !r then s else s2
4925
4926 let isspace c =
4927   c = ' '
4928   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4929
4930 let triml ?(test = isspace) str =
4931   let i = ref 0 in
4932   let n = ref (String.length str) in
4933   while !n > 0 && test str.[!i]; do
4934     decr n;
4935     incr i
4936   done;
4937   if !i = 0 then str
4938   else String.sub str !i !n
4939
4940 let trimr ?(test = isspace) str =
4941   let n = ref (String.length str) in
4942   while !n > 0 && test str.[!n-1]; do
4943     decr n
4944   done;
4945   if !n = String.length str then str
4946   else String.sub str 0 !n
4947
4948 let trim ?(test = isspace) str =
4949   trimr ~test (triml ~test str)
4950
4951 let rec find s sub =
4952   let len = String.length s in
4953   let sublen = String.length sub in
4954   let rec loop i =
4955     if i <= len-sublen then (
4956       let rec loop2 j =
4957         if j < sublen then (
4958           if s.[i+j] = sub.[j] then loop2 (j+1)
4959           else -1
4960         ) else
4961           i (* found *)
4962       in
4963       let r = loop2 0 in
4964       if r = -1 then loop (i+1) else r
4965     ) else
4966       -1 (* not found *)
4967   in
4968   loop 0
4969
4970 let rec replace_str s s1 s2 =
4971   let len = String.length s in
4972   let sublen = String.length s1 in
4973   let i = find s s1 in
4974   if i = -1 then s
4975   else (
4976     let s' = String.sub s 0 i in
4977     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4978     s' ^ s2 ^ replace_str s'' s1 s2
4979   )
4980
4981 let rec string_split sep str =
4982   let len = String.length str in
4983   let seplen = String.length sep in
4984   let i = find str sep in
4985   if i = -1 then [str]
4986   else (
4987     let s' = String.sub str 0 i in
4988     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4989     s' :: string_split sep s''
4990   )
4991
4992 let files_equal n1 n2 =
4993   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4994   match Sys.command cmd with
4995   | 0 -> true
4996   | 1 -> false
4997   | i -> failwithf "%s: failed with error code %d" cmd i
4998
4999 let rec filter_map f = function
5000   | [] -> []
5001   | x :: xs ->
5002       match f x with
5003       | Some y -> y :: filter_map f xs
5004       | None -> filter_map f xs
5005
5006 let rec find_map f = function
5007   | [] -> raise Not_found
5008   | x :: xs ->
5009       match f x with
5010       | Some y -> y
5011       | None -> find_map f xs
5012
5013 let iteri f xs =
5014   let rec loop i = function
5015     | [] -> ()
5016     | x :: xs -> f i x; loop (i+1) xs
5017   in
5018   loop 0 xs
5019
5020 let mapi f xs =
5021   let rec loop i = function
5022     | [] -> []
5023     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5024   in
5025   loop 0 xs
5026
5027 let count_chars c str =
5028   let count = ref 0 in
5029   for i = 0 to String.length str - 1 do
5030     if c = String.unsafe_get str i then incr count
5031   done;
5032   !count
5033
5034 let name_of_argt = function
5035   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5036   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5037   | FileIn n | FileOut n -> n
5038
5039 let java_name_of_struct typ =
5040   try List.assoc typ java_structs
5041   with Not_found ->
5042     failwithf
5043       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5044
5045 let cols_of_struct typ =
5046   try List.assoc typ structs
5047   with Not_found ->
5048     failwithf "cols_of_struct: unknown struct %s" typ
5049
5050 let seq_of_test = function
5051   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5052   | TestOutputListOfDevices (s, _)
5053   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5054   | TestOutputTrue s | TestOutputFalse s
5055   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5056   | TestOutputStruct (s, _)
5057   | TestLastFail s -> s
5058
5059 (* Handling for function flags. *)
5060 let protocol_limit_warning =
5061   "Because of the message protocol, there is a transfer limit
5062 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5063
5064 let danger_will_robinson =
5065   "B<This command is dangerous.  Without careful use you
5066 can easily destroy all your data>."
5067
5068 let deprecation_notice flags =
5069   try
5070     let alt =
5071       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5072     let txt =
5073       sprintf "This function is deprecated.
5074 In new code, use the C<%s> call instead.
5075
5076 Deprecated functions will not be removed from the API, but the
5077 fact that they are deprecated indicates that there are problems
5078 with correct use of these functions." alt in
5079     Some txt
5080   with
5081     Not_found -> None
5082
5083 (* Create list of optional groups. *)
5084 let optgroups =
5085   let h = Hashtbl.create 13 in
5086   List.iter (
5087     fun (name, _, _, flags, _, _, _) ->
5088       List.iter (
5089         function
5090         | Optional group ->
5091             let names = try Hashtbl.find h group with Not_found -> [] in
5092             Hashtbl.replace h group (name :: names)
5093         | _ -> ()
5094       ) flags
5095   ) daemon_functions;
5096   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5097   let groups =
5098     List.map (
5099       fun group -> group, List.sort compare (Hashtbl.find h group)
5100     ) groups in
5101   List.sort (fun x y -> compare (fst x) (fst y)) groups
5102
5103 (* Check function names etc. for consistency. *)
5104 let check_functions () =
5105   let contains_uppercase str =
5106     let len = String.length str in
5107     let rec loop i =
5108       if i >= len then false
5109       else (
5110         let c = str.[i] in
5111         if c >= 'A' && c <= 'Z' then true
5112         else loop (i+1)
5113       )
5114     in
5115     loop 0
5116   in
5117
5118   (* Check function names. *)
5119   List.iter (
5120     fun (name, _, _, _, _, _, _) ->
5121       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5122         failwithf "function name %s does not need 'guestfs' prefix" name;
5123       if name = "" then
5124         failwithf "function name is empty";
5125       if name.[0] < 'a' || name.[0] > 'z' then
5126         failwithf "function name %s must start with lowercase a-z" name;
5127       if String.contains name '-' then
5128         failwithf "function name %s should not contain '-', use '_' instead."
5129           name
5130   ) all_functions;
5131
5132   (* Check function parameter/return names. *)
5133   List.iter (
5134     fun (name, style, _, _, _, _, _) ->
5135       let check_arg_ret_name n =
5136         if contains_uppercase n then
5137           failwithf "%s param/ret %s should not contain uppercase chars"
5138             name n;
5139         if String.contains n '-' || String.contains n '_' then
5140           failwithf "%s param/ret %s should not contain '-' or '_'"
5141             name n;
5142         if n = "value" then
5143           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;
5144         if n = "int" || n = "char" || n = "short" || n = "long" then
5145           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5146         if n = "i" || n = "n" then
5147           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5148         if n = "argv" || n = "args" then
5149           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5150
5151         (* List Haskell, OCaml and C keywords here.
5152          * http://www.haskell.org/haskellwiki/Keywords
5153          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5154          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5155          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5156          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5157          * Omitting _-containing words, since they're handled above.
5158          * Omitting the OCaml reserved word, "val", is ok,
5159          * and saves us from renaming several parameters.
5160          *)
5161         let reserved = [
5162           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5163           "char"; "class"; "const"; "constraint"; "continue"; "data";
5164           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5165           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5166           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5167           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5168           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5169           "interface";
5170           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5171           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5172           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5173           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5174           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5175           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5176           "volatile"; "when"; "where"; "while";
5177           ] in
5178         if List.mem n reserved then
5179           failwithf "%s has param/ret using reserved word %s" name n;
5180       in
5181
5182       (match fst style with
5183        | RErr -> ()
5184        | RInt n | RInt64 n | RBool n
5185        | RConstString n | RConstOptString n | RString n
5186        | RStringList n | RStruct (n, _) | RStructList (n, _)
5187        | RHashtable n | RBufferOut n ->
5188            check_arg_ret_name n
5189       );
5190       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5191   ) all_functions;
5192
5193   (* Check short descriptions. *)
5194   List.iter (
5195     fun (name, _, _, _, _, shortdesc, _) ->
5196       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5197         failwithf "short description of %s should begin with lowercase." name;
5198       let c = shortdesc.[String.length shortdesc-1] in
5199       if c = '\n' || c = '.' then
5200         failwithf "short description of %s should not end with . or \\n." name
5201   ) all_functions;
5202
5203   (* Check long descriptions. *)
5204   List.iter (
5205     fun (name, _, _, _, _, _, longdesc) ->
5206       if longdesc.[String.length longdesc-1] = '\n' then
5207         failwithf "long description of %s should not end with \\n." name
5208   ) all_functions;
5209
5210   (* Check proc_nrs. *)
5211   List.iter (
5212     fun (name, _, proc_nr, _, _, _, _) ->
5213       if proc_nr <= 0 then
5214         failwithf "daemon function %s should have proc_nr > 0" name
5215   ) daemon_functions;
5216
5217   List.iter (
5218     fun (name, _, proc_nr, _, _, _, _) ->
5219       if proc_nr <> -1 then
5220         failwithf "non-daemon function %s should have proc_nr -1" name
5221   ) non_daemon_functions;
5222
5223   let proc_nrs =
5224     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5225       daemon_functions in
5226   let proc_nrs =
5227     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5228   let rec loop = function
5229     | [] -> ()
5230     | [_] -> ()
5231     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5232         loop rest
5233     | (name1,nr1) :: (name2,nr2) :: _ ->
5234         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5235           name1 name2 nr1 nr2
5236   in
5237   loop proc_nrs;
5238
5239   (* Check tests. *)
5240   List.iter (
5241     function
5242       (* Ignore functions that have no tests.  We generate a
5243        * warning when the user does 'make check' instead.
5244        *)
5245     | name, _, _, _, [], _, _ -> ()
5246     | name, _, _, _, tests, _, _ ->
5247         let funcs =
5248           List.map (
5249             fun (_, _, test) ->
5250               match seq_of_test test with
5251               | [] ->
5252                   failwithf "%s has a test containing an empty sequence" name
5253               | cmds -> List.map List.hd cmds
5254           ) tests in
5255         let funcs = List.flatten funcs in
5256
5257         let tested = List.mem name funcs in
5258
5259         if not tested then
5260           failwithf "function %s has tests but does not test itself" name
5261   ) all_functions
5262
5263 (* 'pr' prints to the current output file. *)
5264 let chan = ref Pervasives.stdout
5265 let lines = ref 0
5266 let pr fs =
5267   ksprintf
5268     (fun str ->
5269        let i = count_chars '\n' str in
5270        lines := !lines + i;
5271        output_string !chan str
5272     ) fs
5273
5274 let copyright_years =
5275   let this_year = 1900 + (localtime (time ())).tm_year in
5276   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5277
5278 (* Generate a header block in a number of standard styles. *)
5279 type comment_style =
5280     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5281 type license = GPLv2plus | LGPLv2plus
5282
5283 let generate_header ?(extra_inputs = []) comment license =
5284   let inputs = "src/generator.ml" :: extra_inputs in
5285   let c = match comment with
5286     | CStyle ->         pr "/* "; " *"
5287     | CPlusPlusStyle -> pr "// "; "//"
5288     | HashStyle ->      pr "# ";  "#"
5289     | OCamlStyle ->     pr "(* "; " *"
5290     | HaskellStyle ->   pr "{- "; "  " in
5291   pr "libguestfs generated file\n";
5292   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5293   List.iter (pr "%s   %s\n" c) inputs;
5294   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5295   pr "%s\n" c;
5296   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5297   pr "%s\n" c;
5298   (match license with
5299    | GPLv2plus ->
5300        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5301        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5302        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5303        pr "%s (at your option) any later version.\n" c;
5304        pr "%s\n" c;
5305        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5306        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5307        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5308        pr "%s GNU General Public License for more details.\n" c;
5309        pr "%s\n" c;
5310        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5311        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5312        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5313
5314    | LGPLv2plus ->
5315        pr "%s This library is free software; you can redistribute it and/or\n" c;
5316        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5317        pr "%s License as published by the Free Software Foundation; either\n" c;
5318        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5319        pr "%s\n" c;
5320        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5321        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5322        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5323        pr "%s Lesser General Public License for more details.\n" c;
5324        pr "%s\n" c;
5325        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5326        pr "%s License along with this library; if not, write to the Free Software\n" c;
5327        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5328   );
5329   (match comment with
5330    | CStyle -> pr " */\n"
5331    | CPlusPlusStyle
5332    | HashStyle -> ()
5333    | OCamlStyle -> pr " *)\n"
5334    | HaskellStyle -> pr "-}\n"
5335   );
5336   pr "\n"
5337
5338 (* Start of main code generation functions below this line. *)
5339
5340 (* Generate the pod documentation for the C API. *)
5341 let rec generate_actions_pod () =
5342   List.iter (
5343     fun (shortname, style, _, flags, _, _, longdesc) ->
5344       if not (List.mem NotInDocs flags) then (
5345         let name = "guestfs_" ^ shortname in
5346         pr "=head2 %s\n\n" name;
5347         pr " ";
5348         generate_prototype ~extern:false ~handle:"g" name style;
5349         pr "\n\n";
5350         pr "%s\n\n" longdesc;
5351         (match fst style with
5352          | RErr ->
5353              pr "This function returns 0 on success or -1 on error.\n\n"
5354          | RInt _ ->
5355              pr "On error this function returns -1.\n\n"
5356          | RInt64 _ ->
5357              pr "On error this function returns -1.\n\n"
5358          | RBool _ ->
5359              pr "This function returns a C truth value on success or -1 on error.\n\n"
5360          | RConstString _ ->
5361              pr "This function returns a string, or NULL on error.
5362 The string is owned by the guest handle and must I<not> be freed.\n\n"
5363          | RConstOptString _ ->
5364              pr "This function returns a string which may be NULL.
5365 There is way to return an error from this function.
5366 The string is owned by the guest handle and must I<not> be freed.\n\n"
5367          | RString _ ->
5368              pr "This function returns a string, or NULL on error.
5369 I<The caller must free the returned string after use>.\n\n"
5370          | RStringList _ ->
5371              pr "This function returns a NULL-terminated array of strings
5372 (like L<environ(3)>), or NULL if there was an error.
5373 I<The caller must free the strings and the array after use>.\n\n"
5374          | RStruct (_, typ) ->
5375              pr "This function returns a C<struct guestfs_%s *>,
5376 or NULL if there was an error.
5377 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5378          | RStructList (_, typ) ->
5379              pr "This function returns a C<struct guestfs_%s_list *>
5380 (see E<lt>guestfs-structs.hE<gt>),
5381 or NULL if there was an error.
5382 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5383          | RHashtable _ ->
5384              pr "This function returns a NULL-terminated array of
5385 strings, or NULL if there was an error.
5386 The array of strings will always have length C<2n+1>, where
5387 C<n> keys and values alternate, followed by the trailing NULL entry.
5388 I<The caller must free the strings and the array after use>.\n\n"
5389          | RBufferOut _ ->
5390              pr "This function returns a buffer, or NULL on error.
5391 The size of the returned buffer is written to C<*size_r>.
5392 I<The caller must free the returned buffer after use>.\n\n"
5393         );
5394         if List.mem ProtocolLimitWarning flags then
5395           pr "%s\n\n" protocol_limit_warning;
5396         if List.mem DangerWillRobinson flags then
5397           pr "%s\n\n" danger_will_robinson;
5398         match deprecation_notice flags with
5399         | None -> ()
5400         | Some txt -> pr "%s\n\n" txt
5401       )
5402   ) all_functions_sorted
5403
5404 and generate_structs_pod () =
5405   (* Structs documentation. *)
5406   List.iter (
5407     fun (typ, cols) ->
5408       pr "=head2 guestfs_%s\n" typ;
5409       pr "\n";
5410       pr " struct guestfs_%s {\n" typ;
5411       List.iter (
5412         function
5413         | name, FChar -> pr "   char %s;\n" name
5414         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5415         | name, FInt32 -> pr "   int32_t %s;\n" name
5416         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5417         | name, FInt64 -> pr "   int64_t %s;\n" name
5418         | name, FString -> pr "   char *%s;\n" name
5419         | name, FBuffer ->
5420             pr "   /* The next two fields describe a byte array. */\n";
5421             pr "   uint32_t %s_len;\n" name;
5422             pr "   char *%s;\n" name
5423         | name, FUUID ->
5424             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5425             pr "   char %s[32];\n" name
5426         | name, FOptPercent ->
5427             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5428             pr "   float %s;\n" name
5429       ) cols;
5430       pr " };\n";
5431       pr " \n";
5432       pr " struct guestfs_%s_list {\n" typ;
5433       pr "   uint32_t len; /* Number of elements in list. */\n";
5434       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5435       pr " };\n";
5436       pr " \n";
5437       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5438       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5439         typ typ;
5440       pr "\n"
5441   ) structs
5442
5443 and generate_availability_pod () =
5444   (* Availability documentation. *)
5445   pr "=over 4\n";
5446   pr "\n";
5447   List.iter (
5448     fun (group, functions) ->
5449       pr "=item B<%s>\n" group;
5450       pr "\n";
5451       pr "The following functions:\n";
5452       List.iter (pr "L</guestfs_%s>\n") functions;
5453       pr "\n"
5454   ) optgroups;
5455   pr "=back\n";
5456   pr "\n"
5457
5458 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5459  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5460  *
5461  * We have to use an underscore instead of a dash because otherwise
5462  * rpcgen generates incorrect code.
5463  *
5464  * This header is NOT exported to clients, but see also generate_structs_h.
5465  *)
5466 and generate_xdr () =
5467   generate_header CStyle LGPLv2plus;
5468
5469   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5470   pr "typedef string str<>;\n";
5471   pr "\n";
5472
5473   (* Internal structures. *)
5474   List.iter (
5475     function
5476     | typ, cols ->
5477         pr "struct guestfs_int_%s {\n" typ;
5478         List.iter (function
5479                    | name, FChar -> pr "  char %s;\n" name
5480                    | name, FString -> pr "  string %s<>;\n" name
5481                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5482                    | name, FUUID -> pr "  opaque %s[32];\n" name
5483                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5484                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5485                    | name, FOptPercent -> pr "  float %s;\n" name
5486                   ) cols;
5487         pr "};\n";
5488         pr "\n";
5489         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5490         pr "\n";
5491   ) structs;
5492
5493   List.iter (
5494     fun (shortname, style, _, _, _, _, _) ->
5495       let name = "guestfs_" ^ shortname in
5496
5497       (match snd style with
5498        | [] -> ()
5499        | args ->
5500            pr "struct %s_args {\n" name;
5501            List.iter (
5502              function
5503              | Pathname n | Device n | Dev_or_Path n | String n ->
5504                  pr "  string %s<>;\n" n
5505              | OptString n -> pr "  str *%s;\n" n
5506              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5507              | Bool n -> pr "  bool %s;\n" n
5508              | Int n -> pr "  int %s;\n" n
5509              | Int64 n -> pr "  hyper %s;\n" n
5510              | FileIn _ | FileOut _ -> ()
5511            ) args;
5512            pr "};\n\n"
5513       );
5514       (match fst style with
5515        | RErr -> ()
5516        | RInt n ->
5517            pr "struct %s_ret {\n" name;
5518            pr "  int %s;\n" n;
5519            pr "};\n\n"
5520        | RInt64 n ->
5521            pr "struct %s_ret {\n" name;
5522            pr "  hyper %s;\n" n;
5523            pr "};\n\n"
5524        | RBool n ->
5525            pr "struct %s_ret {\n" name;
5526            pr "  bool %s;\n" n;
5527            pr "};\n\n"
5528        | RConstString _ | RConstOptString _ ->
5529            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5530        | RString n ->
5531            pr "struct %s_ret {\n" name;
5532            pr "  string %s<>;\n" n;
5533            pr "};\n\n"
5534        | RStringList n ->
5535            pr "struct %s_ret {\n" name;
5536            pr "  str %s<>;\n" n;
5537            pr "};\n\n"
5538        | RStruct (n, typ) ->
5539            pr "struct %s_ret {\n" name;
5540            pr "  guestfs_int_%s %s;\n" typ n;
5541            pr "};\n\n"
5542        | RStructList (n, typ) ->
5543            pr "struct %s_ret {\n" name;
5544            pr "  guestfs_int_%s_list %s;\n" typ n;
5545            pr "};\n\n"
5546        | RHashtable n ->
5547            pr "struct %s_ret {\n" name;
5548            pr "  str %s<>;\n" n;
5549            pr "};\n\n"
5550        | RBufferOut n ->
5551            pr "struct %s_ret {\n" name;
5552            pr "  opaque %s<>;\n" n;
5553            pr "};\n\n"
5554       );
5555   ) daemon_functions;
5556
5557   (* Table of procedure numbers. *)
5558   pr "enum guestfs_procedure {\n";
5559   List.iter (
5560     fun (shortname, _, proc_nr, _, _, _, _) ->
5561       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5562   ) daemon_functions;
5563   pr "  GUESTFS_PROC_NR_PROCS\n";
5564   pr "};\n";
5565   pr "\n";
5566
5567   (* Having to choose a maximum message size is annoying for several
5568    * reasons (it limits what we can do in the API), but it (a) makes
5569    * the protocol a lot simpler, and (b) provides a bound on the size
5570    * of the daemon which operates in limited memory space.
5571    *)
5572   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5573   pr "\n";
5574
5575   (* Message header, etc. *)
5576   pr "\
5577 /* The communication protocol is now documented in the guestfs(3)
5578  * manpage.
5579  */
5580
5581 const GUESTFS_PROGRAM = 0x2000F5F5;
5582 const GUESTFS_PROTOCOL_VERSION = 1;
5583
5584 /* These constants must be larger than any possible message length. */
5585 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5586 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5587
5588 enum guestfs_message_direction {
5589   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5590   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5591 };
5592
5593 enum guestfs_message_status {
5594   GUESTFS_STATUS_OK = 0,
5595   GUESTFS_STATUS_ERROR = 1
5596 };
5597
5598 const GUESTFS_ERROR_LEN = 256;
5599
5600 struct guestfs_message_error {
5601   string error_message<GUESTFS_ERROR_LEN>;
5602 };
5603
5604 struct guestfs_message_header {
5605   unsigned prog;                     /* GUESTFS_PROGRAM */
5606   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5607   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5608   guestfs_message_direction direction;
5609   unsigned serial;                   /* message serial number */
5610   guestfs_message_status status;
5611 };
5612
5613 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5614
5615 struct guestfs_chunk {
5616   int cancel;                        /* if non-zero, transfer is cancelled */
5617   /* data size is 0 bytes if the transfer has finished successfully */
5618   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5619 };
5620 "
5621
5622 (* Generate the guestfs-structs.h file. *)
5623 and generate_structs_h () =
5624   generate_header CStyle LGPLv2plus;
5625
5626   (* This is a public exported header file containing various
5627    * structures.  The structures are carefully written to have
5628    * exactly the same in-memory format as the XDR structures that
5629    * we use on the wire to the daemon.  The reason for creating
5630    * copies of these structures here is just so we don't have to
5631    * export the whole of guestfs_protocol.h (which includes much
5632    * unrelated and XDR-dependent stuff that we don't want to be
5633    * public, or required by clients).
5634    *
5635    * To reiterate, we will pass these structures to and from the
5636    * client with a simple assignment or memcpy, so the format
5637    * must be identical to what rpcgen / the RFC defines.
5638    *)
5639
5640   (* Public structures. *)
5641   List.iter (
5642     fun (typ, cols) ->
5643       pr "struct guestfs_%s {\n" typ;
5644       List.iter (
5645         function
5646         | name, FChar -> pr "  char %s;\n" name
5647         | name, FString -> pr "  char *%s;\n" name
5648         | name, FBuffer ->
5649             pr "  uint32_t %s_len;\n" name;
5650             pr "  char *%s;\n" name
5651         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5652         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5653         | name, FInt32 -> pr "  int32_t %s;\n" name
5654         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5655         | name, FInt64 -> pr "  int64_t %s;\n" name
5656         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5657       ) cols;
5658       pr "};\n";
5659       pr "\n";
5660       pr "struct guestfs_%s_list {\n" typ;
5661       pr "  uint32_t len;\n";
5662       pr "  struct guestfs_%s *val;\n" typ;
5663       pr "};\n";
5664       pr "\n";
5665       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5666       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5667       pr "\n"
5668   ) structs
5669
5670 (* Generate the guestfs-actions.h file. *)
5671 and generate_actions_h () =
5672   generate_header CStyle LGPLv2plus;
5673   List.iter (
5674     fun (shortname, style, _, _, _, _, _) ->
5675       let name = "guestfs_" ^ shortname in
5676       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5677         name style
5678   ) all_functions
5679
5680 (* Generate the guestfs-internal-actions.h file. *)
5681 and generate_internal_actions_h () =
5682   generate_header CStyle LGPLv2plus;
5683   List.iter (
5684     fun (shortname, style, _, _, _, _, _) ->
5685       let name = "guestfs__" ^ shortname in
5686       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5687         name style
5688   ) non_daemon_functions
5689
5690 (* Generate the client-side dispatch stubs. *)
5691 and generate_client_actions () =
5692   generate_header CStyle LGPLv2plus;
5693
5694   pr "\
5695 #include <stdio.h>
5696 #include <stdlib.h>
5697 #include <stdint.h>
5698 #include <string.h>
5699 #include <inttypes.h>
5700
5701 #include \"guestfs.h\"
5702 #include \"guestfs-internal.h\"
5703 #include \"guestfs-internal-actions.h\"
5704 #include \"guestfs_protocol.h\"
5705
5706 #define error guestfs_error
5707 //#define perrorf guestfs_perrorf
5708 #define safe_malloc guestfs_safe_malloc
5709 #define safe_realloc guestfs_safe_realloc
5710 //#define safe_strdup guestfs_safe_strdup
5711 #define safe_memdup guestfs_safe_memdup
5712
5713 /* Check the return message from a call for validity. */
5714 static int
5715 check_reply_header (guestfs_h *g,
5716                     const struct guestfs_message_header *hdr,
5717                     unsigned int proc_nr, unsigned int serial)
5718 {
5719   if (hdr->prog != GUESTFS_PROGRAM) {
5720     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5721     return -1;
5722   }
5723   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5724     error (g, \"wrong protocol version (%%d/%%d)\",
5725            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5726     return -1;
5727   }
5728   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5729     error (g, \"unexpected message direction (%%d/%%d)\",
5730            hdr->direction, GUESTFS_DIRECTION_REPLY);
5731     return -1;
5732   }
5733   if (hdr->proc != proc_nr) {
5734     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5735     return -1;
5736   }
5737   if (hdr->serial != serial) {
5738     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5739     return -1;
5740   }
5741
5742   return 0;
5743 }
5744
5745 /* Check we are in the right state to run a high-level action. */
5746 static int
5747 check_state (guestfs_h *g, const char *caller)
5748 {
5749   if (!guestfs__is_ready (g)) {
5750     if (guestfs__is_config (g) || guestfs__is_launching (g))
5751       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5752         caller);
5753     else
5754       error (g, \"%%s called from the wrong state, %%d != READY\",
5755         caller, guestfs__get_state (g));
5756     return -1;
5757   }
5758   return 0;
5759 }
5760
5761 ";
5762
5763   (* Generate code to generate guestfish call traces. *)
5764   let trace_call shortname style =
5765     pr "  if (guestfs__get_trace (g)) {\n";
5766
5767     let needs_i =
5768       List.exists (function
5769                    | StringList _ | DeviceList _ -> true
5770                    | _ -> false) (snd style) in
5771     if needs_i then (
5772       pr "    int i;\n";
5773       pr "\n"
5774     );
5775
5776     pr "    printf (\"%s\");\n" shortname;
5777     List.iter (
5778       function
5779       | String n                        (* strings *)
5780       | Device n
5781       | Pathname n
5782       | Dev_or_Path n
5783       | FileIn n
5784       | FileOut n ->
5785           (* guestfish doesn't support string escaping, so neither do we *)
5786           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5787       | OptString n ->                  (* string option *)
5788           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5789           pr "    else printf (\" null\");\n"
5790       | StringList n
5791       | DeviceList n ->                 (* string list *)
5792           pr "    putchar (' ');\n";
5793           pr "    putchar ('\"');\n";
5794           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5795           pr "      if (i > 0) putchar (' ');\n";
5796           pr "      fputs (%s[i], stdout);\n" n;
5797           pr "    }\n";
5798           pr "    putchar ('\"');\n";
5799       | Bool n ->                       (* boolean *)
5800           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5801       | Int n ->                        (* int *)
5802           pr "    printf (\" %%d\", %s);\n" n
5803       | Int64 n ->
5804           pr "    printf (\" %%\" PRIi64, %s);\n" n
5805     ) (snd style);
5806     pr "    putchar ('\\n');\n";
5807     pr "  }\n";
5808     pr "\n";
5809   in
5810
5811   (* For non-daemon functions, generate a wrapper around each function. *)
5812   List.iter (
5813     fun (shortname, style, _, _, _, _, _) ->
5814       let name = "guestfs_" ^ shortname in
5815
5816       generate_prototype ~extern:false ~semicolon:false ~newline:true
5817         ~handle:"g" name style;
5818       pr "{\n";
5819       trace_call shortname style;
5820       pr "  return guestfs__%s " shortname;
5821       generate_c_call_args ~handle:"g" style;
5822       pr ";\n";
5823       pr "}\n";
5824       pr "\n"
5825   ) non_daemon_functions;
5826
5827   (* Client-side stubs for each function. *)
5828   List.iter (
5829     fun (shortname, style, _, _, _, _, _) ->
5830       let name = "guestfs_" ^ shortname in
5831
5832       (* Generate the action stub. *)
5833       generate_prototype ~extern:false ~semicolon:false ~newline:true
5834         ~handle:"g" name style;
5835
5836       let error_code =
5837         match fst style with
5838         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5839         | RConstString _ | RConstOptString _ ->
5840             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5841         | RString _ | RStringList _
5842         | RStruct _ | RStructList _
5843         | RHashtable _ | RBufferOut _ ->
5844             "NULL" in
5845
5846       pr "{\n";
5847
5848       (match snd style with
5849        | [] -> ()
5850        | _ -> pr "  struct %s_args args;\n" name
5851       );
5852
5853       pr "  guestfs_message_header hdr;\n";
5854       pr "  guestfs_message_error err;\n";
5855       let has_ret =
5856         match fst style with
5857         | RErr -> false
5858         | RConstString _ | RConstOptString _ ->
5859             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5860         | RInt _ | RInt64 _
5861         | RBool _ | RString _ | RStringList _
5862         | RStruct _ | RStructList _
5863         | RHashtable _ | RBufferOut _ ->
5864             pr "  struct %s_ret ret;\n" name;
5865             true in
5866
5867       pr "  int serial;\n";
5868       pr "  int r;\n";
5869       pr "\n";
5870       trace_call shortname style;
5871       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5872         shortname error_code;
5873       pr "  guestfs___set_busy (g);\n";
5874       pr "\n";
5875
5876       (* Send the main header and arguments. *)
5877       (match snd style with
5878        | [] ->
5879            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5880              (String.uppercase shortname)
5881        | args ->
5882            List.iter (
5883              function
5884              | Pathname n | Device n | Dev_or_Path n | String n ->
5885                  pr "  args.%s = (char *) %s;\n" n n
5886              | OptString n ->
5887                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5888              | StringList n | DeviceList n ->
5889                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5890                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5891              | Bool n ->
5892                  pr "  args.%s = %s;\n" n n
5893              | Int n ->
5894                  pr "  args.%s = %s;\n" n n
5895              | Int64 n ->
5896                  pr "  args.%s = %s;\n" n n
5897              | FileIn _ | FileOut _ -> ()
5898            ) args;
5899            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5900              (String.uppercase shortname);
5901            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5902              name;
5903       );
5904       pr "  if (serial == -1) {\n";
5905       pr "    guestfs___end_busy (g);\n";
5906       pr "    return %s;\n" error_code;
5907       pr "  }\n";
5908       pr "\n";
5909
5910       (* Send any additional files (FileIn) requested. *)
5911       let need_read_reply_label = ref false in
5912       List.iter (
5913         function
5914         | FileIn n ->
5915             pr "  r = guestfs___send_file (g, %s);\n" n;
5916             pr "  if (r == -1) {\n";
5917             pr "    guestfs___end_busy (g);\n";
5918             pr "    return %s;\n" error_code;
5919             pr "  }\n";
5920             pr "  if (r == -2) /* daemon cancelled */\n";
5921             pr "    goto read_reply;\n";
5922             need_read_reply_label := true;
5923             pr "\n";
5924         | _ -> ()
5925       ) (snd style);
5926
5927       (* Wait for the reply from the remote end. *)
5928       if !need_read_reply_label then pr " read_reply:\n";
5929       pr "  memset (&hdr, 0, sizeof hdr);\n";
5930       pr "  memset (&err, 0, sizeof err);\n";
5931       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5932       pr "\n";
5933       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5934       if not has_ret then
5935         pr "NULL, NULL"
5936       else
5937         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5938       pr ");\n";
5939
5940       pr "  if (r == -1) {\n";
5941       pr "    guestfs___end_busy (g);\n";
5942       pr "    return %s;\n" error_code;
5943       pr "  }\n";
5944       pr "\n";
5945
5946       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5947         (String.uppercase shortname);
5948       pr "    guestfs___end_busy (g);\n";
5949       pr "    return %s;\n" error_code;
5950       pr "  }\n";
5951       pr "\n";
5952
5953       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5954       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5955       pr "    free (err.error_message);\n";
5956       pr "    guestfs___end_busy (g);\n";
5957       pr "    return %s;\n" error_code;
5958       pr "  }\n";
5959       pr "\n";
5960
5961       (* Expecting to receive further files (FileOut)? *)
5962       List.iter (
5963         function
5964         | FileOut n ->
5965             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5966             pr "    guestfs___end_busy (g);\n";
5967             pr "    return %s;\n" error_code;
5968             pr "  }\n";
5969             pr "\n";
5970         | _ -> ()
5971       ) (snd style);
5972
5973       pr "  guestfs___end_busy (g);\n";
5974
5975       (match fst style with
5976        | RErr -> pr "  return 0;\n"
5977        | RInt n | RInt64 n | RBool n ->
5978            pr "  return ret.%s;\n" n
5979        | RConstString _ | RConstOptString _ ->
5980            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5981        | RString n ->
5982            pr "  return ret.%s; /* caller will free */\n" n
5983        | RStringList n | RHashtable n ->
5984            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5985            pr "  ret.%s.%s_val =\n" n n;
5986            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5987            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5988              n n;
5989            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5990            pr "  return ret.%s.%s_val;\n" n n
5991        | RStruct (n, _) ->
5992            pr "  /* caller will free this */\n";
5993            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5994        | RStructList (n, _) ->
5995            pr "  /* caller will free this */\n";
5996            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5997        | RBufferOut n ->
5998            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5999            pr "   * _val might be NULL here.  To make the API saner for\n";
6000            pr "   * callers, we turn this case into a unique pointer (using\n";
6001            pr "   * malloc(1)).\n";
6002            pr "   */\n";
6003            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6004            pr "    *size_r = ret.%s.%s_len;\n" n n;
6005            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6006            pr "  } else {\n";
6007            pr "    free (ret.%s.%s_val);\n" n n;
6008            pr "    char *p = safe_malloc (g, 1);\n";
6009            pr "    *size_r = ret.%s.%s_len;\n" n n;
6010            pr "    return p;\n";
6011            pr "  }\n";
6012       );
6013
6014       pr "}\n\n"
6015   ) daemon_functions;
6016
6017   (* Functions to free structures. *)
6018   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6019   pr " * structure format is identical to the XDR format.  See note in\n";
6020   pr " * generator.ml.\n";
6021   pr " */\n";
6022   pr "\n";
6023
6024   List.iter (
6025     fun (typ, _) ->
6026       pr "void\n";
6027       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6028       pr "{\n";
6029       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6030       pr "  free (x);\n";
6031       pr "}\n";
6032       pr "\n";
6033
6034       pr "void\n";
6035       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6036       pr "{\n";
6037       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6038       pr "  free (x);\n";
6039       pr "}\n";
6040       pr "\n";
6041
6042   ) structs;
6043
6044 (* Generate daemon/actions.h. *)
6045 and generate_daemon_actions_h () =
6046   generate_header CStyle GPLv2plus;
6047
6048   pr "#include \"../src/guestfs_protocol.h\"\n";
6049   pr "\n";
6050
6051   List.iter (
6052     fun (name, style, _, _, _, _, _) ->
6053       generate_prototype
6054         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6055         name style;
6056   ) daemon_functions
6057
6058 (* Generate the linker script which controls the visibility of
6059  * symbols in the public ABI and ensures no other symbols get
6060  * exported accidentally.
6061  *)
6062 and generate_linker_script () =
6063   generate_header HashStyle GPLv2plus;
6064
6065   let globals = [
6066     "guestfs_create";
6067     "guestfs_close";
6068     "guestfs_get_error_handler";
6069     "guestfs_get_out_of_memory_handler";
6070     "guestfs_last_error";
6071     "guestfs_set_error_handler";
6072     "guestfs_set_launch_done_callback";
6073     "guestfs_set_log_message_callback";
6074     "guestfs_set_out_of_memory_handler";
6075     "guestfs_set_subprocess_quit_callback";
6076
6077     (* Unofficial parts of the API: the bindings code use these
6078      * functions, so it is useful to export them.
6079      *)
6080     "guestfs_safe_calloc";
6081     "guestfs_safe_malloc";
6082   ] in
6083   let functions =
6084     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6085       all_functions in
6086   let structs =
6087     List.concat (
6088       List.map (fun (typ, _) ->
6089                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6090         structs
6091     ) in
6092   let globals = List.sort compare (globals @ functions @ structs) in
6093
6094   pr "{\n";
6095   pr "    global:\n";
6096   List.iter (pr "        %s;\n") globals;
6097   pr "\n";
6098
6099   pr "    local:\n";
6100   pr "        *;\n";
6101   pr "};\n"
6102
6103 (* Generate the server-side stubs. *)
6104 and generate_daemon_actions () =
6105   generate_header CStyle GPLv2plus;
6106
6107   pr "#include <config.h>\n";
6108   pr "\n";
6109   pr "#include <stdio.h>\n";
6110   pr "#include <stdlib.h>\n";
6111   pr "#include <string.h>\n";
6112   pr "#include <inttypes.h>\n";
6113   pr "#include <rpc/types.h>\n";
6114   pr "#include <rpc/xdr.h>\n";
6115   pr "\n";
6116   pr "#include \"daemon.h\"\n";
6117   pr "#include \"c-ctype.h\"\n";
6118   pr "#include \"../src/guestfs_protocol.h\"\n";
6119   pr "#include \"actions.h\"\n";
6120   pr "\n";
6121
6122   List.iter (
6123     fun (name, style, _, _, _, _, _) ->
6124       (* Generate server-side stubs. *)
6125       pr "static void %s_stub (XDR *xdr_in)\n" name;
6126       pr "{\n";
6127       let error_code =
6128         match fst style with
6129         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6130         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6131         | RBool _ -> pr "  int r;\n"; "-1"
6132         | RConstString _ | RConstOptString _ ->
6133             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6134         | RString _ -> pr "  char *r;\n"; "NULL"
6135         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6136         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6137         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6138         | RBufferOut _ ->
6139             pr "  size_t size = 1;\n";
6140             pr "  char *r;\n";
6141             "NULL" in
6142
6143       (match snd style with
6144        | [] -> ()
6145        | args ->
6146            pr "  struct guestfs_%s_args args;\n" name;
6147            List.iter (
6148              function
6149              | Device n | Dev_or_Path n
6150              | Pathname n
6151              | String n -> ()
6152              | OptString n -> pr "  char *%s;\n" n
6153              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6154              | Bool n -> pr "  int %s;\n" n
6155              | Int n -> pr "  int %s;\n" n
6156              | Int64 n -> pr "  int64_t %s;\n" n
6157              | FileIn _ | FileOut _ -> ()
6158            ) args
6159       );
6160       pr "\n";
6161
6162       let is_filein =
6163         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6164
6165       (match snd style with
6166        | [] -> ()
6167        | args ->
6168            pr "  memset (&args, 0, sizeof args);\n";
6169            pr "\n";
6170            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6171            if is_filein then
6172              pr "    cancel_receive ();\n";
6173            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6174            pr "    goto done;\n";
6175            pr "  }\n";
6176            let pr_args n =
6177              pr "  char *%s = args.%s;\n" n n
6178            in
6179            let pr_list_handling_code n =
6180              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6181              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6182              pr "  if (%s == NULL) {\n" n;
6183              if is_filein then
6184                pr "    cancel_receive ();\n";
6185              pr "    reply_with_perror (\"realloc\");\n";
6186              pr "    goto done;\n";
6187              pr "  }\n";
6188              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6189              pr "  args.%s.%s_val = %s;\n" n n n;
6190            in
6191            List.iter (
6192              function
6193              | Pathname n ->
6194                  pr_args n;
6195                  pr "  ABS_PATH (%s, %s, goto done);\n"
6196                    n (if is_filein then "cancel_receive ()" else "");
6197              | Device n ->
6198                  pr_args n;
6199                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6200                    n (if is_filein then "cancel_receive ()" else "");
6201              | Dev_or_Path n ->
6202                  pr_args n;
6203                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6204                    n (if is_filein then "cancel_receive ()" else "");
6205              | String n -> pr_args n
6206              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6207              | StringList n ->
6208                  pr_list_handling_code n;
6209              | DeviceList n ->
6210                  pr_list_handling_code n;
6211                  pr "  /* Ensure that each is a device,\n";
6212                  pr "   * and perform device name translation. */\n";
6213                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6214                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6215                    (if is_filein then "cancel_receive ()" else "");
6216                  pr "  }\n";
6217              | Bool n -> pr "  %s = args.%s;\n" n n
6218              | Int n -> pr "  %s = args.%s;\n" n n
6219              | Int64 n -> pr "  %s = args.%s;\n" n n
6220              | FileIn _ | FileOut _ -> ()
6221            ) args;
6222            pr "\n"
6223       );
6224
6225
6226       (* this is used at least for do_equal *)
6227       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6228         (* Emit NEED_ROOT just once, even when there are two or
6229            more Pathname args *)
6230         pr "  NEED_ROOT (%s, goto done);\n"
6231           (if is_filein then "cancel_receive ()" else "");
6232       );
6233
6234       (* Don't want to call the impl with any FileIn or FileOut
6235        * parameters, since these go "outside" the RPC protocol.
6236        *)
6237       let args' =
6238         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6239           (snd style) in
6240       pr "  r = do_%s " name;
6241       generate_c_call_args (fst style, args');
6242       pr ";\n";
6243
6244       (match fst style with
6245        | RErr | RInt _ | RInt64 _ | RBool _
6246        | RConstString _ | RConstOptString _
6247        | RString _ | RStringList _ | RHashtable _
6248        | RStruct (_, _) | RStructList (_, _) ->
6249            pr "  if (r == %s)\n" error_code;
6250            pr "    /* do_%s has already called reply_with_error */\n" name;
6251            pr "    goto done;\n";
6252            pr "\n"
6253        | RBufferOut _ ->
6254            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6255            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6256            pr "   */\n";
6257            pr "  if (size == 1 && r == %s)\n" error_code;
6258            pr "    /* do_%s has already called reply_with_error */\n" name;
6259            pr "    goto done;\n";
6260            pr "\n"
6261       );
6262
6263       (* If there are any FileOut parameters, then the impl must
6264        * send its own reply.
6265        *)
6266       let no_reply =
6267         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6268       if no_reply then
6269         pr "  /* do_%s has already sent a reply */\n" name
6270       else (
6271         match fst style with
6272         | RErr -> pr "  reply (NULL, NULL);\n"
6273         | RInt n | RInt64 n | RBool n ->
6274             pr "  struct guestfs_%s_ret ret;\n" name;
6275             pr "  ret.%s = r;\n" n;
6276             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6277               name
6278         | RConstString _ | RConstOptString _ ->
6279             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6280         | RString n ->
6281             pr "  struct guestfs_%s_ret ret;\n" name;
6282             pr "  ret.%s = r;\n" n;
6283             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6284               name;
6285             pr "  free (r);\n"
6286         | RStringList n | RHashtable n ->
6287             pr "  struct guestfs_%s_ret ret;\n" name;
6288             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6289             pr "  ret.%s.%s_val = r;\n" n n;
6290             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6291               name;
6292             pr "  free_strings (r);\n"
6293         | RStruct (n, _) ->
6294             pr "  struct guestfs_%s_ret ret;\n" name;
6295             pr "  ret.%s = *r;\n" n;
6296             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6297               name;
6298             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6299               name
6300         | RStructList (n, _) ->
6301             pr "  struct guestfs_%s_ret ret;\n" name;
6302             pr "  ret.%s = *r;\n" n;
6303             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6304               name;
6305             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6306               name
6307         | RBufferOut n ->
6308             pr "  struct guestfs_%s_ret ret;\n" name;
6309             pr "  ret.%s.%s_val = r;\n" n n;
6310             pr "  ret.%s.%s_len = size;\n" n n;
6311             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6312               name;
6313             pr "  free (r);\n"
6314       );
6315
6316       (* Free the args. *)
6317       pr "done:\n";
6318       (match snd style with
6319        | [] -> ()
6320        | _ ->
6321            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6322              name
6323       );
6324       pr "  return;\n";
6325       pr "}\n\n";
6326   ) daemon_functions;
6327
6328   (* Dispatch function. *)
6329   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6330   pr "{\n";
6331   pr "  switch (proc_nr) {\n";
6332
6333   List.iter (
6334     fun (name, style, _, _, _, _, _) ->
6335       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6336       pr "      %s_stub (xdr_in);\n" name;
6337       pr "      break;\n"
6338   ) daemon_functions;
6339
6340   pr "    default:\n";
6341   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";
6342   pr "  }\n";
6343   pr "}\n";
6344   pr "\n";
6345
6346   (* LVM columns and tokenization functions. *)
6347   (* XXX This generates crap code.  We should rethink how we
6348    * do this parsing.
6349    *)
6350   List.iter (
6351     function
6352     | typ, cols ->
6353         pr "static const char *lvm_%s_cols = \"%s\";\n"
6354           typ (String.concat "," (List.map fst cols));
6355         pr "\n";
6356
6357         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6358         pr "{\n";
6359         pr "  char *tok, *p, *next;\n";
6360         pr "  int i, j;\n";
6361         pr "\n";
6362         (*
6363           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6364           pr "\n";
6365         *)
6366         pr "  if (!str) {\n";
6367         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6368         pr "    return -1;\n";
6369         pr "  }\n";
6370         pr "  if (!*str || c_isspace (*str)) {\n";
6371         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6372         pr "    return -1;\n";
6373         pr "  }\n";
6374         pr "  tok = str;\n";
6375         List.iter (
6376           fun (name, coltype) ->
6377             pr "  if (!tok) {\n";
6378             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6379             pr "    return -1;\n";
6380             pr "  }\n";
6381             pr "  p = strchrnul (tok, ',');\n";
6382             pr "  if (*p) next = p+1; else next = NULL;\n";
6383             pr "  *p = '\\0';\n";
6384             (match coltype with
6385              | FString ->
6386                  pr "  r->%s = strdup (tok);\n" name;
6387                  pr "  if (r->%s == NULL) {\n" name;
6388                  pr "    perror (\"strdup\");\n";
6389                  pr "    return -1;\n";
6390                  pr "  }\n"
6391              | FUUID ->
6392                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6393                  pr "    if (tok[j] == '\\0') {\n";
6394                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6395                  pr "      return -1;\n";
6396                  pr "    } else if (tok[j] != '-')\n";
6397                  pr "      r->%s[i++] = tok[j];\n" name;
6398                  pr "  }\n";
6399              | FBytes ->
6400                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6401                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6402                  pr "    return -1;\n";
6403                  pr "  }\n";
6404              | FInt64 ->
6405                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6406                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6407                  pr "    return -1;\n";
6408                  pr "  }\n";
6409              | FOptPercent ->
6410                  pr "  if (tok[0] == '\\0')\n";
6411                  pr "    r->%s = -1;\n" name;
6412                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6413                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6414                  pr "    return -1;\n";
6415                  pr "  }\n";
6416              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6417                  assert false (* can never be an LVM column *)
6418             );
6419             pr "  tok = next;\n";
6420         ) cols;
6421
6422         pr "  if (tok != NULL) {\n";
6423         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6424         pr "    return -1;\n";
6425         pr "  }\n";
6426         pr "  return 0;\n";
6427         pr "}\n";
6428         pr "\n";
6429
6430         pr "guestfs_int_lvm_%s_list *\n" typ;
6431         pr "parse_command_line_%ss (void)\n" typ;
6432         pr "{\n";
6433         pr "  char *out, *err;\n";
6434         pr "  char *p, *pend;\n";
6435         pr "  int r, i;\n";
6436         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6437         pr "  void *newp;\n";
6438         pr "\n";
6439         pr "  ret = malloc (sizeof *ret);\n";
6440         pr "  if (!ret) {\n";
6441         pr "    reply_with_perror (\"malloc\");\n";
6442         pr "    return NULL;\n";
6443         pr "  }\n";
6444         pr "\n";
6445         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6446         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6447         pr "\n";
6448         pr "  r = command (&out, &err,\n";
6449         pr "           \"lvm\", \"%ss\",\n" typ;
6450         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6451         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6452         pr "  if (r == -1) {\n";
6453         pr "    reply_with_error (\"%%s\", err);\n";
6454         pr "    free (out);\n";
6455         pr "    free (err);\n";
6456         pr "    free (ret);\n";
6457         pr "    return NULL;\n";
6458         pr "  }\n";
6459         pr "\n";
6460         pr "  free (err);\n";
6461         pr "\n";
6462         pr "  /* Tokenize each line of the output. */\n";
6463         pr "  p = out;\n";
6464         pr "  i = 0;\n";
6465         pr "  while (p) {\n";
6466         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6467         pr "    if (pend) {\n";
6468         pr "      *pend = '\\0';\n";
6469         pr "      pend++;\n";
6470         pr "    }\n";
6471         pr "\n";
6472         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6473         pr "      p++;\n";
6474         pr "\n";
6475         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6476         pr "      p = pend;\n";
6477         pr "      continue;\n";
6478         pr "    }\n";
6479         pr "\n";
6480         pr "    /* Allocate some space to store this next entry. */\n";
6481         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6482         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6483         pr "    if (newp == NULL) {\n";
6484         pr "      reply_with_perror (\"realloc\");\n";
6485         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6486         pr "      free (ret);\n";
6487         pr "      free (out);\n";
6488         pr "      return NULL;\n";
6489         pr "    }\n";
6490         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6491         pr "\n";
6492         pr "    /* Tokenize the next entry. */\n";
6493         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6494         pr "    if (r == -1) {\n";
6495         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6496         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6497         pr "      free (ret);\n";
6498         pr "      free (out);\n";
6499         pr "      return NULL;\n";
6500         pr "    }\n";
6501         pr "\n";
6502         pr "    ++i;\n";
6503         pr "    p = pend;\n";
6504         pr "  }\n";
6505         pr "\n";
6506         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6507         pr "\n";
6508         pr "  free (out);\n";
6509         pr "  return ret;\n";
6510         pr "}\n"
6511
6512   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6513
6514 (* Generate a list of function names, for debugging in the daemon.. *)
6515 and generate_daemon_names () =
6516   generate_header CStyle GPLv2plus;
6517
6518   pr "#include <config.h>\n";
6519   pr "\n";
6520   pr "#include \"daemon.h\"\n";
6521   pr "\n";
6522
6523   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6524   pr "const char *function_names[] = {\n";
6525   List.iter (
6526     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6527   ) daemon_functions;
6528   pr "};\n";
6529
6530 (* Generate the optional groups for the daemon to implement
6531  * guestfs_available.
6532  *)
6533 and generate_daemon_optgroups_c () =
6534   generate_header CStyle GPLv2plus;
6535
6536   pr "#include <config.h>\n";
6537   pr "\n";
6538   pr "#include \"daemon.h\"\n";
6539   pr "#include \"optgroups.h\"\n";
6540   pr "\n";
6541
6542   pr "struct optgroup optgroups[] = {\n";
6543   List.iter (
6544     fun (group, _) ->
6545       pr "  { \"%s\", optgroup_%s_available },\n" group group
6546   ) optgroups;
6547   pr "  { NULL, NULL }\n";
6548   pr "};\n"
6549
6550 and generate_daemon_optgroups_h () =
6551   generate_header CStyle GPLv2plus;
6552
6553   List.iter (
6554     fun (group, _) ->
6555       pr "extern int optgroup_%s_available (void);\n" group
6556   ) optgroups
6557
6558 (* Generate the tests. *)
6559 and generate_tests () =
6560   generate_header CStyle GPLv2plus;
6561
6562   pr "\
6563 #include <stdio.h>
6564 #include <stdlib.h>
6565 #include <string.h>
6566 #include <unistd.h>
6567 #include <sys/types.h>
6568 #include <fcntl.h>
6569
6570 #include \"guestfs.h\"
6571 #include \"guestfs-internal.h\"
6572
6573 static guestfs_h *g;
6574 static int suppress_error = 0;
6575
6576 static void print_error (guestfs_h *g, void *data, const char *msg)
6577 {
6578   if (!suppress_error)
6579     fprintf (stderr, \"%%s\\n\", msg);
6580 }
6581
6582 /* FIXME: nearly identical code appears in fish.c */
6583 static void print_strings (char *const *argv)
6584 {
6585   int argc;
6586
6587   for (argc = 0; argv[argc] != NULL; ++argc)
6588     printf (\"\\t%%s\\n\", argv[argc]);
6589 }
6590
6591 /*
6592 static void print_table (char const *const *argv)
6593 {
6594   int i;
6595
6596   for (i = 0; argv[i] != NULL; i += 2)
6597     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6598 }
6599 */
6600
6601 ";
6602
6603   (* Generate a list of commands which are not tested anywhere. *)
6604   pr "static void no_test_warnings (void)\n";
6605   pr "{\n";
6606
6607   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6608   List.iter (
6609     fun (_, _, _, _, tests, _, _) ->
6610       let tests = filter_map (
6611         function
6612         | (_, (Always|If _|Unless _), test) -> Some test
6613         | (_, Disabled, _) -> None
6614       ) tests in
6615       let seq = List.concat (List.map seq_of_test tests) in
6616       let cmds_tested = List.map List.hd seq in
6617       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6618   ) all_functions;
6619
6620   List.iter (
6621     fun (name, _, _, _, _, _, _) ->
6622       if not (Hashtbl.mem hash name) then
6623         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6624   ) all_functions;
6625
6626   pr "}\n";
6627   pr "\n";
6628
6629   (* Generate the actual tests.  Note that we generate the tests
6630    * in reverse order, deliberately, so that (in general) the
6631    * newest tests run first.  This makes it quicker and easier to
6632    * debug them.
6633    *)
6634   let test_names =
6635     List.map (
6636       fun (name, _, _, flags, tests, _, _) ->
6637         mapi (generate_one_test name flags) tests
6638     ) (List.rev all_functions) in
6639   let test_names = List.concat test_names in
6640   let nr_tests = List.length test_names in
6641
6642   pr "\
6643 int main (int argc, char *argv[])
6644 {
6645   char c = 0;
6646   unsigned long int n_failed = 0;
6647   const char *filename;
6648   int fd;
6649   int nr_tests, test_num = 0;
6650
6651   setbuf (stdout, NULL);
6652
6653   no_test_warnings ();
6654
6655   g = guestfs_create ();
6656   if (g == NULL) {
6657     printf (\"guestfs_create FAILED\\n\");
6658     exit (EXIT_FAILURE);
6659   }
6660
6661   guestfs_set_error_handler (g, print_error, NULL);
6662
6663   guestfs_set_path (g, \"../appliance\");
6664
6665   filename = \"test1.img\";
6666   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6667   if (fd == -1) {
6668     perror (filename);
6669     exit (EXIT_FAILURE);
6670   }
6671   if (lseek (fd, %d, SEEK_SET) == -1) {
6672     perror (\"lseek\");
6673     close (fd);
6674     unlink (filename);
6675     exit (EXIT_FAILURE);
6676   }
6677   if (write (fd, &c, 1) == -1) {
6678     perror (\"write\");
6679     close (fd);
6680     unlink (filename);
6681     exit (EXIT_FAILURE);
6682   }
6683   if (close (fd) == -1) {
6684     perror (filename);
6685     unlink (filename);
6686     exit (EXIT_FAILURE);
6687   }
6688   if (guestfs_add_drive (g, filename) == -1) {
6689     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6690     exit (EXIT_FAILURE);
6691   }
6692
6693   filename = \"test2.img\";
6694   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6695   if (fd == -1) {
6696     perror (filename);
6697     exit (EXIT_FAILURE);
6698   }
6699   if (lseek (fd, %d, SEEK_SET) == -1) {
6700     perror (\"lseek\");
6701     close (fd);
6702     unlink (filename);
6703     exit (EXIT_FAILURE);
6704   }
6705   if (write (fd, &c, 1) == -1) {
6706     perror (\"write\");
6707     close (fd);
6708     unlink (filename);
6709     exit (EXIT_FAILURE);
6710   }
6711   if (close (fd) == -1) {
6712     perror (filename);
6713     unlink (filename);
6714     exit (EXIT_FAILURE);
6715   }
6716   if (guestfs_add_drive (g, filename) == -1) {
6717     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6718     exit (EXIT_FAILURE);
6719   }
6720
6721   filename = \"test3.img\";
6722   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6723   if (fd == -1) {
6724     perror (filename);
6725     exit (EXIT_FAILURE);
6726   }
6727   if (lseek (fd, %d, SEEK_SET) == -1) {
6728     perror (\"lseek\");
6729     close (fd);
6730     unlink (filename);
6731     exit (EXIT_FAILURE);
6732   }
6733   if (write (fd, &c, 1) == -1) {
6734     perror (\"write\");
6735     close (fd);
6736     unlink (filename);
6737     exit (EXIT_FAILURE);
6738   }
6739   if (close (fd) == -1) {
6740     perror (filename);
6741     unlink (filename);
6742     exit (EXIT_FAILURE);
6743   }
6744   if (guestfs_add_drive (g, filename) == -1) {
6745     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6746     exit (EXIT_FAILURE);
6747   }
6748
6749   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6750     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6751     exit (EXIT_FAILURE);
6752   }
6753
6754   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6755   alarm (600);
6756
6757   if (guestfs_launch (g) == -1) {
6758     printf (\"guestfs_launch FAILED\\n\");
6759     exit (EXIT_FAILURE);
6760   }
6761
6762   /* Cancel previous alarm. */
6763   alarm (0);
6764
6765   nr_tests = %d;
6766
6767 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6768
6769   iteri (
6770     fun i test_name ->
6771       pr "  test_num++;\n";
6772       pr "  if (guestfs_get_verbose (g))\n";
6773       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6774       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6775       pr "  if (%s () == -1) {\n" test_name;
6776       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6777       pr "    n_failed++;\n";
6778       pr "  }\n";
6779   ) test_names;
6780   pr "\n";
6781
6782   pr "  guestfs_close (g);\n";
6783   pr "  unlink (\"test1.img\");\n";
6784   pr "  unlink (\"test2.img\");\n";
6785   pr "  unlink (\"test3.img\");\n";
6786   pr "\n";
6787
6788   pr "  if (n_failed > 0) {\n";
6789   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6790   pr "    exit (EXIT_FAILURE);\n";
6791   pr "  }\n";
6792   pr "\n";
6793
6794   pr "  exit (EXIT_SUCCESS);\n";
6795   pr "}\n"
6796
6797 and generate_one_test name flags i (init, prereq, test) =
6798   let test_name = sprintf "test_%s_%d" name i in
6799
6800   pr "\
6801 static int %s_skip (void)
6802 {
6803   const char *str;
6804
6805   str = getenv (\"TEST_ONLY\");
6806   if (str)
6807     return strstr (str, \"%s\") == NULL;
6808   str = getenv (\"SKIP_%s\");
6809   if (str && STREQ (str, \"1\")) return 1;
6810   str = getenv (\"SKIP_TEST_%s\");
6811   if (str && STREQ (str, \"1\")) return 1;
6812   return 0;
6813 }
6814
6815 " test_name name (String.uppercase test_name) (String.uppercase name);
6816
6817   (match prereq with
6818    | Disabled | Always -> ()
6819    | If code | Unless code ->
6820        pr "static int %s_prereq (void)\n" test_name;
6821        pr "{\n";
6822        pr "  %s\n" code;
6823        pr "}\n";
6824        pr "\n";
6825   );
6826
6827   pr "\
6828 static int %s (void)
6829 {
6830   if (%s_skip ()) {
6831     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6832     return 0;
6833   }
6834
6835 " test_name test_name test_name;
6836
6837   (* Optional functions should only be tested if the relevant
6838    * support is available in the daemon.
6839    *)
6840   List.iter (
6841     function
6842     | Optional group ->
6843         pr "  {\n";
6844         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6845         pr "    int r;\n";
6846         pr "    suppress_error = 1;\n";
6847         pr "    r = guestfs_available (g, (char **) groups);\n";
6848         pr "    suppress_error = 0;\n";
6849         pr "    if (r == -1) {\n";
6850         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6851         pr "      return 0;\n";
6852         pr "    }\n";
6853         pr "  }\n";
6854     | _ -> ()
6855   ) flags;
6856
6857   (match prereq with
6858    | Disabled ->
6859        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6860    | If _ ->
6861        pr "  if (! %s_prereq ()) {\n" test_name;
6862        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6863        pr "    return 0;\n";
6864        pr "  }\n";
6865        pr "\n";
6866        generate_one_test_body name i test_name init test;
6867    | Unless _ ->
6868        pr "  if (%s_prereq ()) {\n" test_name;
6869        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6870        pr "    return 0;\n";
6871        pr "  }\n";
6872        pr "\n";
6873        generate_one_test_body name i test_name init test;
6874    | Always ->
6875        generate_one_test_body name i test_name init test
6876   );
6877
6878   pr "  return 0;\n";
6879   pr "}\n";
6880   pr "\n";
6881   test_name
6882
6883 and generate_one_test_body name i test_name init test =
6884   (match init with
6885    | InitNone (* XXX at some point, InitNone and InitEmpty became
6886                * folded together as the same thing.  Really we should
6887                * make InitNone do nothing at all, but the tests may
6888                * need to be checked to make sure this is OK.
6889                *)
6890    | InitEmpty ->
6891        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6892        List.iter (generate_test_command_call test_name)
6893          [["blockdev_setrw"; "/dev/sda"];
6894           ["umount_all"];
6895           ["lvm_remove_all"]]
6896    | InitPartition ->
6897        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6898        List.iter (generate_test_command_call test_name)
6899          [["blockdev_setrw"; "/dev/sda"];
6900           ["umount_all"];
6901           ["lvm_remove_all"];
6902           ["part_disk"; "/dev/sda"; "mbr"]]
6903    | InitBasicFS ->
6904        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\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           ["part_disk"; "/dev/sda"; "mbr"];
6910           ["mkfs"; "ext2"; "/dev/sda1"];
6911           ["mount_options"; ""; "/dev/sda1"; "/"]]
6912    | InitBasicFSonLVM ->
6913        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6914          test_name;
6915        List.iter (generate_test_command_call test_name)
6916          [["blockdev_setrw"; "/dev/sda"];
6917           ["umount_all"];
6918           ["lvm_remove_all"];
6919           ["part_disk"; "/dev/sda"; "mbr"];
6920           ["pvcreate"; "/dev/sda1"];
6921           ["vgcreate"; "VG"; "/dev/sda1"];
6922           ["lvcreate"; "LV"; "VG"; "8"];
6923           ["mkfs"; "ext2"; "/dev/VG/LV"];
6924           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6925    | InitISOFS ->
6926        pr "  /* InitISOFS for %s */\n" test_name;
6927        List.iter (generate_test_command_call test_name)
6928          [["blockdev_setrw"; "/dev/sda"];
6929           ["umount_all"];
6930           ["lvm_remove_all"];
6931           ["mount_ro"; "/dev/sdd"; "/"]]
6932   );
6933
6934   let get_seq_last = function
6935     | [] ->
6936         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6937           test_name
6938     | seq ->
6939         let seq = List.rev seq in
6940         List.rev (List.tl seq), List.hd seq
6941   in
6942
6943   match test with
6944   | TestRun seq ->
6945       pr "  /* TestRun for %s (%d) */\n" name i;
6946       List.iter (generate_test_command_call test_name) seq
6947   | TestOutput (seq, expected) ->
6948       pr "  /* TestOutput for %s (%d) */\n" name i;
6949       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6950       let seq, last = get_seq_last seq in
6951       let test () =
6952         pr "    if (STRNEQ (r, expected)) {\n";
6953         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6954         pr "      return -1;\n";
6955         pr "    }\n"
6956       in
6957       List.iter (generate_test_command_call test_name) seq;
6958       generate_test_command_call ~test test_name last
6959   | TestOutputList (seq, expected) ->
6960       pr "  /* TestOutputList for %s (%d) */\n" name i;
6961       let seq, last = get_seq_last seq in
6962       let test () =
6963         iteri (
6964           fun i str ->
6965             pr "    if (!r[%d]) {\n" i;
6966             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6967             pr "      print_strings (r);\n";
6968             pr "      return -1;\n";
6969             pr "    }\n";
6970             pr "    {\n";
6971             pr "      const char *expected = \"%s\";\n" (c_quote str);
6972             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6973             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6974             pr "        return -1;\n";
6975             pr "      }\n";
6976             pr "    }\n"
6977         ) expected;
6978         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6979         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6980           test_name;
6981         pr "      print_strings (r);\n";
6982         pr "      return -1;\n";
6983         pr "    }\n"
6984       in
6985       List.iter (generate_test_command_call test_name) seq;
6986       generate_test_command_call ~test test_name last
6987   | TestOutputListOfDevices (seq, expected) ->
6988       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6989       let seq, last = get_seq_last seq in
6990       let test () =
6991         iteri (
6992           fun i str ->
6993             pr "    if (!r[%d]) {\n" i;
6994             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6995             pr "      print_strings (r);\n";
6996             pr "      return -1;\n";
6997             pr "    }\n";
6998             pr "    {\n";
6999             pr "      const char *expected = \"%s\";\n" (c_quote str);
7000             pr "      r[%d][5] = 's';\n" i;
7001             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7002             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7003             pr "        return -1;\n";
7004             pr "      }\n";
7005             pr "    }\n"
7006         ) expected;
7007         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7008         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7009           test_name;
7010         pr "      print_strings (r);\n";
7011         pr "      return -1;\n";
7012         pr "    }\n"
7013       in
7014       List.iter (generate_test_command_call test_name) seq;
7015       generate_test_command_call ~test test_name last
7016   | TestOutputInt (seq, expected) ->
7017       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7018       let seq, last = get_seq_last seq in
7019       let test () =
7020         pr "    if (r != %d) {\n" expected;
7021         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7022           test_name expected;
7023         pr "               (int) r);\n";
7024         pr "      return -1;\n";
7025         pr "    }\n"
7026       in
7027       List.iter (generate_test_command_call test_name) seq;
7028       generate_test_command_call ~test test_name last
7029   | TestOutputIntOp (seq, op, expected) ->
7030       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7031       let seq, last = get_seq_last seq in
7032       let test () =
7033         pr "    if (! (r %s %d)) {\n" op expected;
7034         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7035           test_name op expected;
7036         pr "               (int) r);\n";
7037         pr "      return -1;\n";
7038         pr "    }\n"
7039       in
7040       List.iter (generate_test_command_call test_name) seq;
7041       generate_test_command_call ~test test_name last
7042   | TestOutputTrue seq ->
7043       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7044       let seq, last = get_seq_last seq in
7045       let test () =
7046         pr "    if (!r) {\n";
7047         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7048           test_name;
7049         pr "      return -1;\n";
7050         pr "    }\n"
7051       in
7052       List.iter (generate_test_command_call test_name) seq;
7053       generate_test_command_call ~test test_name last
7054   | TestOutputFalse seq ->
7055       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7056       let seq, last = get_seq_last seq in
7057       let test () =
7058         pr "    if (r) {\n";
7059         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7060           test_name;
7061         pr "      return -1;\n";
7062         pr "    }\n"
7063       in
7064       List.iter (generate_test_command_call test_name) seq;
7065       generate_test_command_call ~test test_name last
7066   | TestOutputLength (seq, expected) ->
7067       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7068       let seq, last = get_seq_last seq in
7069       let test () =
7070         pr "    int j;\n";
7071         pr "    for (j = 0; j < %d; ++j)\n" expected;
7072         pr "      if (r[j] == NULL) {\n";
7073         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7074           test_name;
7075         pr "        print_strings (r);\n";
7076         pr "        return -1;\n";
7077         pr "      }\n";
7078         pr "    if (r[j] != NULL) {\n";
7079         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7080           test_name;
7081         pr "      print_strings (r);\n";
7082         pr "      return -1;\n";
7083         pr "    }\n"
7084       in
7085       List.iter (generate_test_command_call test_name) seq;
7086       generate_test_command_call ~test test_name last
7087   | TestOutputBuffer (seq, expected) ->
7088       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7089       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7090       let seq, last = get_seq_last seq in
7091       let len = String.length expected in
7092       let test () =
7093         pr "    if (size != %d) {\n" len;
7094         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7095         pr "      return -1;\n";
7096         pr "    }\n";
7097         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7098         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7099         pr "      return -1;\n";
7100         pr "    }\n"
7101       in
7102       List.iter (generate_test_command_call test_name) seq;
7103       generate_test_command_call ~test test_name last
7104   | TestOutputStruct (seq, checks) ->
7105       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7106       let seq, last = get_seq_last seq in
7107       let test () =
7108         List.iter (
7109           function
7110           | CompareWithInt (field, expected) ->
7111               pr "    if (r->%s != %d) {\n" field expected;
7112               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7113                 test_name field expected;
7114               pr "               (int) r->%s);\n" field;
7115               pr "      return -1;\n";
7116               pr "    }\n"
7117           | CompareWithIntOp (field, op, expected) ->
7118               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7119               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7120                 test_name field op expected;
7121               pr "               (int) r->%s);\n" field;
7122               pr "      return -1;\n";
7123               pr "    }\n"
7124           | CompareWithString (field, expected) ->
7125               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7126               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7127                 test_name field expected;
7128               pr "               r->%s);\n" field;
7129               pr "      return -1;\n";
7130               pr "    }\n"
7131           | CompareFieldsIntEq (field1, field2) ->
7132               pr "    if (r->%s != r->%s) {\n" field1 field2;
7133               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7134                 test_name field1 field2;
7135               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7136               pr "      return -1;\n";
7137               pr "    }\n"
7138           | CompareFieldsStrEq (field1, field2) ->
7139               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7140               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7141                 test_name field1 field2;
7142               pr "               r->%s, r->%s);\n" field1 field2;
7143               pr "      return -1;\n";
7144               pr "    }\n"
7145         ) checks
7146       in
7147       List.iter (generate_test_command_call test_name) seq;
7148       generate_test_command_call ~test test_name last
7149   | TestLastFail seq ->
7150       pr "  /* TestLastFail for %s (%d) */\n" name i;
7151       let seq, last = get_seq_last seq in
7152       List.iter (generate_test_command_call test_name) seq;
7153       generate_test_command_call test_name ~expect_error:true last
7154
7155 (* Generate the code to run a command, leaving the result in 'r'.
7156  * If you expect to get an error then you should set expect_error:true.
7157  *)
7158 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7159   match cmd with
7160   | [] -> assert false
7161   | name :: args ->
7162       (* Look up the command to find out what args/ret it has. *)
7163       let style =
7164         try
7165           let _, style, _, _, _, _, _ =
7166             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7167           style
7168         with Not_found ->
7169           failwithf "%s: in test, command %s was not found" test_name name in
7170
7171       if List.length (snd style) <> List.length args then
7172         failwithf "%s: in test, wrong number of args given to %s"
7173           test_name name;
7174
7175       pr "  {\n";
7176
7177       List.iter (
7178         function
7179         | OptString n, "NULL" -> ()
7180         | Pathname n, arg
7181         | Device n, arg
7182         | Dev_or_Path n, arg
7183         | String n, arg
7184         | OptString n, arg ->
7185             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7186         | Int _, _
7187         | Int64 _, _
7188         | Bool _, _
7189         | FileIn _, _ | FileOut _, _ -> ()
7190         | StringList n, "" | DeviceList n, "" ->
7191             pr "    const char *const %s[1] = { NULL };\n" n
7192         | StringList n, arg | DeviceList n, arg ->
7193             let strs = string_split " " arg in
7194             iteri (
7195               fun i str ->
7196                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7197             ) strs;
7198             pr "    const char *const %s[] = {\n" n;
7199             iteri (
7200               fun i _ -> pr "      %s_%d,\n" n i
7201             ) strs;
7202             pr "      NULL\n";
7203             pr "    };\n";
7204       ) (List.combine (snd style) args);
7205
7206       let error_code =
7207         match fst style with
7208         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7209         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7210         | RConstString _ | RConstOptString _ ->
7211             pr "    const char *r;\n"; "NULL"
7212         | RString _ -> pr "    char *r;\n"; "NULL"
7213         | RStringList _ | RHashtable _ ->
7214             pr "    char **r;\n";
7215             pr "    int i;\n";
7216             "NULL"
7217         | RStruct (_, typ) ->
7218             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7219         | RStructList (_, typ) ->
7220             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7221         | RBufferOut _ ->
7222             pr "    char *r;\n";
7223             pr "    size_t size;\n";
7224             "NULL" in
7225
7226       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7227       pr "    r = guestfs_%s (g" name;
7228
7229       (* Generate the parameters. *)
7230       List.iter (
7231         function
7232         | OptString _, "NULL" -> pr ", NULL"
7233         | Pathname n, _
7234         | Device n, _ | Dev_or_Path n, _
7235         | String n, _
7236         | OptString n, _ ->
7237             pr ", %s" n
7238         | FileIn _, arg | FileOut _, arg ->
7239             pr ", \"%s\"" (c_quote arg)
7240         | StringList n, _ | DeviceList n, _ ->
7241             pr ", (char **) %s" n
7242         | Int _, arg ->
7243             let i =
7244               try int_of_string arg
7245               with Failure "int_of_string" ->
7246                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7247             pr ", %d" i
7248         | Int64 _, arg ->
7249             let i =
7250               try Int64.of_string arg
7251               with Failure "int_of_string" ->
7252                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7253             pr ", %Ld" i
7254         | Bool _, arg ->
7255             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7256       ) (List.combine (snd style) args);
7257
7258       (match fst style with
7259        | RBufferOut _ -> pr ", &size"
7260        | _ -> ()
7261       );
7262
7263       pr ");\n";
7264
7265       if not expect_error then
7266         pr "    if (r == %s)\n" error_code
7267       else
7268         pr "    if (r != %s)\n" error_code;
7269       pr "      return -1;\n";
7270
7271       (* Insert the test code. *)
7272       (match test with
7273        | None -> ()
7274        | Some f -> f ()
7275       );
7276
7277       (match fst style with
7278        | RErr | RInt _ | RInt64 _ | RBool _
7279        | RConstString _ | RConstOptString _ -> ()
7280        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7281        | RStringList _ | RHashtable _ ->
7282            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7283            pr "      free (r[i]);\n";
7284            pr "    free (r);\n"
7285        | RStruct (_, typ) ->
7286            pr "    guestfs_free_%s (r);\n" typ
7287        | RStructList (_, typ) ->
7288            pr "    guestfs_free_%s_list (r);\n" typ
7289       );
7290
7291       pr "  }\n"
7292
7293 and c_quote str =
7294   let str = replace_str str "\r" "\\r" in
7295   let str = replace_str str "\n" "\\n" in
7296   let str = replace_str str "\t" "\\t" in
7297   let str = replace_str str "\000" "\\0" in
7298   str
7299
7300 (* Generate a lot of different functions for guestfish. *)
7301 and generate_fish_cmds () =
7302   generate_header CStyle GPLv2plus;
7303
7304   let all_functions =
7305     List.filter (
7306       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7307     ) all_functions in
7308   let all_functions_sorted =
7309     List.filter (
7310       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7311     ) all_functions_sorted in
7312
7313   pr "#include <config.h>\n";
7314   pr "\n";
7315   pr "#include <stdio.h>\n";
7316   pr "#include <stdlib.h>\n";
7317   pr "#include <string.h>\n";
7318   pr "#include <inttypes.h>\n";
7319   pr "\n";
7320   pr "#include <guestfs.h>\n";
7321   pr "#include \"c-ctype.h\"\n";
7322   pr "#include \"full-write.h\"\n";
7323   pr "#include \"xstrtol.h\"\n";
7324   pr "#include \"fish.h\"\n";
7325   pr "\n";
7326
7327   (* list_commands function, which implements guestfish -h *)
7328   pr "void list_commands (void)\n";
7329   pr "{\n";
7330   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7331   pr "  list_builtin_commands ();\n";
7332   List.iter (
7333     fun (name, _, _, flags, _, shortdesc, _) ->
7334       let name = replace_char name '_' '-' in
7335       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7336         name shortdesc
7337   ) all_functions_sorted;
7338   pr "  printf (\"    %%s\\n\",";
7339   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7340   pr "}\n";
7341   pr "\n";
7342
7343   (* display_command function, which implements guestfish -h cmd *)
7344   pr "void display_command (const char *cmd)\n";
7345   pr "{\n";
7346   List.iter (
7347     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7348       let name2 = replace_char name '_' '-' in
7349       let alias =
7350         try find_map (function FishAlias n -> Some n | _ -> None) flags
7351         with Not_found -> name in
7352       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7353       let synopsis =
7354         match snd style with
7355         | [] -> name2
7356         | args ->
7357             sprintf "%s %s"
7358               name2 (String.concat " " (List.map name_of_argt args)) in
7359
7360       let warnings =
7361         if List.mem ProtocolLimitWarning flags then
7362           ("\n\n" ^ protocol_limit_warning)
7363         else "" in
7364
7365       (* For DangerWillRobinson commands, we should probably have
7366        * guestfish prompt before allowing you to use them (especially
7367        * in interactive mode). XXX
7368        *)
7369       let warnings =
7370         warnings ^
7371           if List.mem DangerWillRobinson flags then
7372             ("\n\n" ^ danger_will_robinson)
7373           else "" in
7374
7375       let warnings =
7376         warnings ^
7377           match deprecation_notice flags with
7378           | None -> ""
7379           | Some txt -> "\n\n" ^ txt in
7380
7381       let describe_alias =
7382         if name <> alias then
7383           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7384         else "" in
7385
7386       pr "  if (";
7387       pr "STRCASEEQ (cmd, \"%s\")" name;
7388       if name <> name2 then
7389         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7390       if name <> alias then
7391         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7392       pr ")\n";
7393       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7394         name2 shortdesc
7395         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7396          "=head1 DESCRIPTION\n\n" ^
7397          longdesc ^ warnings ^ describe_alias);
7398       pr "  else\n"
7399   ) all_functions;
7400   pr "    display_builtin_command (cmd);\n";
7401   pr "}\n";
7402   pr "\n";
7403
7404   let emit_print_list_function typ =
7405     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7406       typ typ typ;
7407     pr "{\n";
7408     pr "  unsigned int i;\n";
7409     pr "\n";
7410     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7411     pr "    printf (\"[%%d] = {\\n\", i);\n";
7412     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7413     pr "    printf (\"}\\n\");\n";
7414     pr "  }\n";
7415     pr "}\n";
7416     pr "\n";
7417   in
7418
7419   (* print_* functions *)
7420   List.iter (
7421     fun (typ, cols) ->
7422       let needs_i =
7423         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7424
7425       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7426       pr "{\n";
7427       if needs_i then (
7428         pr "  unsigned int i;\n";
7429         pr "\n"
7430       );
7431       List.iter (
7432         function
7433         | name, FString ->
7434             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7435         | name, FUUID ->
7436             pr "  printf (\"%%s%s: \", indent);\n" name;
7437             pr "  for (i = 0; i < 32; ++i)\n";
7438             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7439             pr "  printf (\"\\n\");\n"
7440         | name, FBuffer ->
7441             pr "  printf (\"%%s%s: \", indent);\n" name;
7442             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7443             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7444             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7445             pr "    else\n";
7446             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7447             pr "  printf (\"\\n\");\n"
7448         | name, (FUInt64|FBytes) ->
7449             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7450               name typ name
7451         | name, FInt64 ->
7452             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7453               name typ name
7454         | name, FUInt32 ->
7455             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7456               name typ name
7457         | name, FInt32 ->
7458             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7459               name typ name
7460         | name, FChar ->
7461             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7462               name typ name
7463         | name, FOptPercent ->
7464             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7465               typ name name typ name;
7466             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7467       ) cols;
7468       pr "}\n";
7469       pr "\n";
7470   ) structs;
7471
7472   (* Emit a print_TYPE_list function definition only if that function is used. *)
7473   List.iter (
7474     function
7475     | typ, (RStructListOnly | RStructAndList) ->
7476         (* generate the function for typ *)
7477         emit_print_list_function typ
7478     | typ, _ -> () (* empty *)
7479   ) (rstructs_used_by all_functions);
7480
7481   (* Emit a print_TYPE function definition only if that function is used. *)
7482   List.iter (
7483     function
7484     | typ, (RStructOnly | RStructAndList) ->
7485         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7486         pr "{\n";
7487         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7488         pr "}\n";
7489         pr "\n";
7490     | typ, _ -> () (* empty *)
7491   ) (rstructs_used_by all_functions);
7492
7493   (* run_<action> actions *)
7494   List.iter (
7495     fun (name, style, _, flags, _, _, _) ->
7496       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7497       pr "{\n";
7498       (match fst style with
7499        | RErr
7500        | RInt _
7501        | RBool _ -> pr "  int r;\n"
7502        | RInt64 _ -> pr "  int64_t r;\n"
7503        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7504        | RString _ -> pr "  char *r;\n"
7505        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7506        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7507        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7508        | RBufferOut _ ->
7509            pr "  char *r;\n";
7510            pr "  size_t size;\n";
7511       );
7512       List.iter (
7513         function
7514         | Device n
7515         | String n
7516         | OptString n -> pr "  const char *%s;\n" n
7517         | Pathname n
7518         | Dev_or_Path n
7519         | FileIn n
7520         | FileOut n -> pr "  char *%s;\n" n
7521         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7522         | Bool n -> pr "  int %s;\n" n
7523         | Int n -> pr "  int %s;\n" n
7524         | Int64 n -> pr "  int64_t %s;\n" n
7525       ) (snd style);
7526
7527       (* Check and convert parameters. *)
7528       let argc_expected = List.length (snd style) in
7529       pr "  if (argc != %d) {\n" argc_expected;
7530       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7531         argc_expected;
7532       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7533       pr "    return -1;\n";
7534       pr "  }\n";
7535
7536       let parse_integer fn fntyp rtyp range name i =
7537         pr "  {\n";
7538         pr "    strtol_error xerr;\n";
7539         pr "    %s r;\n" fntyp;
7540         pr "\n";
7541         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7542         pr "    if (xerr != LONGINT_OK) {\n";
7543         pr "      fprintf (stderr,\n";
7544         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7545         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7546         pr "      return -1;\n";
7547         pr "    }\n";
7548         (match range with
7549          | None -> ()
7550          | Some (min, max, comment) ->
7551              pr "    /* %s */\n" comment;
7552              pr "    if (r < %s || r > %s) {\n" min max;
7553              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7554                name;
7555              pr "      return -1;\n";
7556              pr "    }\n";
7557              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7558         );
7559         pr "    %s = r;\n" name;
7560         pr "  }\n";
7561       in
7562
7563       iteri (
7564         fun i ->
7565           function
7566           | Device name
7567           | String name ->
7568               pr "  %s = argv[%d];\n" name i
7569           | Pathname name
7570           | Dev_or_Path name ->
7571               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7572               pr "  if (%s == NULL) return -1;\n" name
7573           | OptString name ->
7574               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7575                 name i i
7576           | FileIn name ->
7577               pr "  %s = file_in (argv[%d]);\n" name i;
7578               pr "  if (%s == NULL) return -1;\n" name
7579           | FileOut name ->
7580               pr "  %s = file_out (argv[%d]);\n" name i;
7581               pr "  if (%s == NULL) return -1;\n" name
7582           | StringList name | DeviceList name ->
7583               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7584               pr "  if (%s == NULL) return -1;\n" name;
7585           | Bool name ->
7586               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7587           | Int name ->
7588               let range =
7589                 let min = "(-(2LL<<30))"
7590                 and max = "((2LL<<30)-1)"
7591                 and comment =
7592                   "The Int type in the generator is a signed 31 bit int." in
7593                 Some (min, max, comment) in
7594               parse_integer "xstrtoll" "long long" "int" range name i
7595           | Int64 name ->
7596               parse_integer "xstrtoll" "long long" "int64_t" None name i
7597       ) (snd style);
7598
7599       (* Call C API function. *)
7600       pr "  r = guestfs_%s " name;
7601       generate_c_call_args ~handle:"g" style;
7602       pr ";\n";
7603
7604       List.iter (
7605         function
7606         | Device name | String name
7607         | OptString name | Bool name
7608         | Int name | Int64 name -> ()
7609         | Pathname name | Dev_or_Path name | FileOut name ->
7610             pr "  free (%s);\n" name
7611         | FileIn name ->
7612             pr "  free_file_in (%s);\n" name
7613         | StringList name | DeviceList name ->
7614             pr "  free_strings (%s);\n" name
7615       ) (snd style);
7616
7617       (* Any output flags? *)
7618       let fish_output =
7619         let flags = filter_map (
7620           function FishOutput flag -> Some flag | _ -> None
7621         ) flags in
7622         match flags with
7623         | [] -> None
7624         | [f] -> Some f
7625         | _ ->
7626             failwithf "%s: more than one FishOutput flag is not allowed" name in
7627
7628       (* Check return value for errors and display command results. *)
7629       (match fst style with
7630        | RErr -> pr "  return r;\n"
7631        | RInt _ ->
7632            pr "  if (r == -1) return -1;\n";
7633            (match fish_output with
7634             | None ->
7635                 pr "  printf (\"%%d\\n\", r);\n";
7636             | Some FishOutputOctal ->
7637                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7638             | Some FishOutputHexadecimal ->
7639                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7640            pr "  return 0;\n"
7641        | RInt64 _ ->
7642            pr "  if (r == -1) return -1;\n";
7643            (match fish_output with
7644             | None ->
7645                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7646             | Some FishOutputOctal ->
7647                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7648             | Some FishOutputHexadecimal ->
7649                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7650            pr "  return 0;\n"
7651        | RBool _ ->
7652            pr "  if (r == -1) return -1;\n";
7653            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7654            pr "  return 0;\n"
7655        | RConstString _ ->
7656            pr "  if (r == NULL) return -1;\n";
7657            pr "  printf (\"%%s\\n\", r);\n";
7658            pr "  return 0;\n"
7659        | RConstOptString _ ->
7660            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7661            pr "  return 0;\n"
7662        | RString _ ->
7663            pr "  if (r == NULL) return -1;\n";
7664            pr "  printf (\"%%s\\n\", r);\n";
7665            pr "  free (r);\n";
7666            pr "  return 0;\n"
7667        | RStringList _ ->
7668            pr "  if (r == NULL) return -1;\n";
7669            pr "  print_strings (r);\n";
7670            pr "  free_strings (r);\n";
7671            pr "  return 0;\n"
7672        | RStruct (_, typ) ->
7673            pr "  if (r == NULL) return -1;\n";
7674            pr "  print_%s (r);\n" typ;
7675            pr "  guestfs_free_%s (r);\n" typ;
7676            pr "  return 0;\n"
7677        | RStructList (_, typ) ->
7678            pr "  if (r == NULL) return -1;\n";
7679            pr "  print_%s_list (r);\n" typ;
7680            pr "  guestfs_free_%s_list (r);\n" typ;
7681            pr "  return 0;\n"
7682        | RHashtable _ ->
7683            pr "  if (r == NULL) return -1;\n";
7684            pr "  print_table (r);\n";
7685            pr "  free_strings (r);\n";
7686            pr "  return 0;\n"
7687        | RBufferOut _ ->
7688            pr "  if (r == NULL) return -1;\n";
7689            pr "  if (full_write (1, r, size) != size) {\n";
7690            pr "    perror (\"write\");\n";
7691            pr "    free (r);\n";
7692            pr "    return -1;\n";
7693            pr "  }\n";
7694            pr "  free (r);\n";
7695            pr "  return 0;\n"
7696       );
7697       pr "}\n";
7698       pr "\n"
7699   ) all_functions;
7700
7701   (* run_action function *)
7702   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7703   pr "{\n";
7704   List.iter (
7705     fun (name, _, _, flags, _, _, _) ->
7706       let name2 = replace_char name '_' '-' in
7707       let alias =
7708         try find_map (function FishAlias n -> Some n | _ -> None) flags
7709         with Not_found -> name in
7710       pr "  if (";
7711       pr "STRCASEEQ (cmd, \"%s\")" name;
7712       if name <> name2 then
7713         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7714       if name <> alias then
7715         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7716       pr ")\n";
7717       pr "    return run_%s (cmd, argc, argv);\n" name;
7718       pr "  else\n";
7719   ) all_functions;
7720   pr "    {\n";
7721   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7722   pr "      if (command_num == 1)\n";
7723   pr "        extended_help_message ();\n";
7724   pr "      return -1;\n";
7725   pr "    }\n";
7726   pr "  return 0;\n";
7727   pr "}\n";
7728   pr "\n"
7729
7730 (* Readline completion for guestfish. *)
7731 and generate_fish_completion () =
7732   generate_header CStyle GPLv2plus;
7733
7734   let all_functions =
7735     List.filter (
7736       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7737     ) all_functions in
7738
7739   pr "\
7740 #include <config.h>
7741
7742 #include <stdio.h>
7743 #include <stdlib.h>
7744 #include <string.h>
7745
7746 #ifdef HAVE_LIBREADLINE
7747 #include <readline/readline.h>
7748 #endif
7749
7750 #include \"fish.h\"
7751
7752 #ifdef HAVE_LIBREADLINE
7753
7754 static const char *const commands[] = {
7755   BUILTIN_COMMANDS_FOR_COMPLETION,
7756 ";
7757
7758   (* Get the commands, including the aliases.  They don't need to be
7759    * sorted - the generator() function just does a dumb linear search.
7760    *)
7761   let commands =
7762     List.map (
7763       fun (name, _, _, flags, _, _, _) ->
7764         let name2 = replace_char name '_' '-' in
7765         let alias =
7766           try find_map (function FishAlias n -> Some n | _ -> None) flags
7767           with Not_found -> name in
7768
7769         if name <> alias then [name2; alias] else [name2]
7770     ) all_functions in
7771   let commands = List.flatten commands in
7772
7773   List.iter (pr "  \"%s\",\n") commands;
7774
7775   pr "  NULL
7776 };
7777
7778 static char *
7779 generator (const char *text, int state)
7780 {
7781   static int index, len;
7782   const char *name;
7783
7784   if (!state) {
7785     index = 0;
7786     len = strlen (text);
7787   }
7788
7789   rl_attempted_completion_over = 1;
7790
7791   while ((name = commands[index]) != NULL) {
7792     index++;
7793     if (STRCASEEQLEN (name, text, len))
7794       return strdup (name);
7795   }
7796
7797   return NULL;
7798 }
7799
7800 #endif /* HAVE_LIBREADLINE */
7801
7802 #ifdef HAVE_RL_COMPLETION_MATCHES
7803 #define RL_COMPLETION_MATCHES rl_completion_matches
7804 #else
7805 #ifdef HAVE_COMPLETION_MATCHES
7806 #define RL_COMPLETION_MATCHES completion_matches
7807 #endif
7808 #endif /* else just fail if we don't have either symbol */
7809
7810 char **
7811 do_completion (const char *text, int start, int end)
7812 {
7813   char **matches = NULL;
7814
7815 #ifdef HAVE_LIBREADLINE
7816   rl_completion_append_character = ' ';
7817
7818   if (start == 0)
7819     matches = RL_COMPLETION_MATCHES (text, generator);
7820   else if (complete_dest_paths)
7821     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7822 #endif
7823
7824   return matches;
7825 }
7826 ";
7827
7828 (* Generate the POD documentation for guestfish. *)
7829 and generate_fish_actions_pod () =
7830   let all_functions_sorted =
7831     List.filter (
7832       fun (_, _, _, flags, _, _, _) ->
7833         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7834     ) all_functions_sorted in
7835
7836   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7837
7838   List.iter (
7839     fun (name, style, _, flags, _, _, longdesc) ->
7840       let longdesc =
7841         Str.global_substitute rex (
7842           fun s ->
7843             let sub =
7844               try Str.matched_group 1 s
7845               with Not_found ->
7846                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7847             "C<" ^ replace_char sub '_' '-' ^ ">"
7848         ) longdesc in
7849       let name = replace_char name '_' '-' in
7850       let alias =
7851         try find_map (function FishAlias n -> Some n | _ -> None) flags
7852         with Not_found -> name in
7853
7854       pr "=head2 %s" name;
7855       if name <> alias then
7856         pr " | %s" alias;
7857       pr "\n";
7858       pr "\n";
7859       pr " %s" name;
7860       List.iter (
7861         function
7862         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7863         | OptString n -> pr " %s" n
7864         | StringList n | DeviceList n -> pr " '%s ...'" n
7865         | Bool _ -> pr " true|false"
7866         | Int n -> pr " %s" n
7867         | Int64 n -> pr " %s" n
7868         | FileIn n | FileOut n -> pr " (%s|-)" n
7869       ) (snd style);
7870       pr "\n";
7871       pr "\n";
7872       pr "%s\n\n" longdesc;
7873
7874       if List.exists (function FileIn _ | FileOut _ -> true
7875                       | _ -> false) (snd style) then
7876         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7877
7878       if List.mem ProtocolLimitWarning flags then
7879         pr "%s\n\n" protocol_limit_warning;
7880
7881       if List.mem DangerWillRobinson flags then
7882         pr "%s\n\n" danger_will_robinson;
7883
7884       match deprecation_notice flags with
7885       | None -> ()
7886       | Some txt -> pr "%s\n\n" txt
7887   ) all_functions_sorted
7888
7889 (* Generate a C function prototype. *)
7890 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7891     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7892     ?(prefix = "")
7893     ?handle name style =
7894   if extern then pr "extern ";
7895   if static then pr "static ";
7896   (match fst style with
7897    | RErr -> pr "int "
7898    | RInt _ -> pr "int "
7899    | RInt64 _ -> pr "int64_t "
7900    | RBool _ -> pr "int "
7901    | RConstString _ | RConstOptString _ -> pr "const char *"
7902    | RString _ | RBufferOut _ -> pr "char *"
7903    | RStringList _ | RHashtable _ -> pr "char **"
7904    | RStruct (_, typ) ->
7905        if not in_daemon then pr "struct guestfs_%s *" typ
7906        else pr "guestfs_int_%s *" typ
7907    | RStructList (_, typ) ->
7908        if not in_daemon then pr "struct guestfs_%s_list *" typ
7909        else pr "guestfs_int_%s_list *" typ
7910   );
7911   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7912   pr "%s%s (" prefix name;
7913   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7914     pr "void"
7915   else (
7916     let comma = ref false in
7917     (match handle with
7918      | None -> ()
7919      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7920     );
7921     let next () =
7922       if !comma then (
7923         if single_line then pr ", " else pr ",\n\t\t"
7924       );
7925       comma := true
7926     in
7927     List.iter (
7928       function
7929       | Pathname n
7930       | Device n | Dev_or_Path n
7931       | String n
7932       | OptString n ->
7933           next ();
7934           pr "const char *%s" n
7935       | StringList n | DeviceList n ->
7936           next ();
7937           pr "char *const *%s" n
7938       | Bool n -> next (); pr "int %s" n
7939       | Int n -> next (); pr "int %s" n
7940       | Int64 n -> next (); pr "int64_t %s" n
7941       | FileIn n
7942       | FileOut n ->
7943           if not in_daemon then (next (); pr "const char *%s" n)
7944     ) (snd style);
7945     if is_RBufferOut then (next (); pr "size_t *size_r");
7946   );
7947   pr ")";
7948   if semicolon then pr ";";
7949   if newline then pr "\n"
7950
7951 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7952 and generate_c_call_args ?handle ?(decl = false) style =
7953   pr "(";
7954   let comma = ref false in
7955   let next () =
7956     if !comma then pr ", ";
7957     comma := true
7958   in
7959   (match handle with
7960    | None -> ()
7961    | Some handle -> pr "%s" handle; comma := true
7962   );
7963   List.iter (
7964     fun arg ->
7965       next ();
7966       pr "%s" (name_of_argt arg)
7967   ) (snd style);
7968   (* For RBufferOut calls, add implicit &size parameter. *)
7969   if not decl then (
7970     match fst style with
7971     | RBufferOut _ ->
7972         next ();
7973         pr "&size"
7974     | _ -> ()
7975   );
7976   pr ")"
7977
7978 (* Generate the OCaml bindings interface. *)
7979 and generate_ocaml_mli () =
7980   generate_header OCamlStyle LGPLv2plus;
7981
7982   pr "\
7983 (** For API documentation you should refer to the C API
7984     in the guestfs(3) manual page.  The OCaml API uses almost
7985     exactly the same calls. *)
7986
7987 type t
7988 (** A [guestfs_h] handle. *)
7989
7990 exception Error of string
7991 (** This exception is raised when there is an error. *)
7992
7993 exception Handle_closed of string
7994 (** This exception is raised if you use a {!Guestfs.t} handle
7995     after calling {!close} on it.  The string is the name of
7996     the function. *)
7997
7998 val create : unit -> t
7999 (** Create a {!Guestfs.t} handle. *)
8000
8001 val close : t -> unit
8002 (** Close the {!Guestfs.t} handle and free up all resources used
8003     by it immediately.
8004
8005     Handles are closed by the garbage collector when they become
8006     unreferenced, but callers can call this in order to provide
8007     predictable cleanup. *)
8008
8009 ";
8010   generate_ocaml_structure_decls ();
8011
8012   (* The actions. *)
8013   List.iter (
8014     fun (name, style, _, _, _, shortdesc, _) ->
8015       generate_ocaml_prototype name style;
8016       pr "(** %s *)\n" shortdesc;
8017       pr "\n"
8018   ) all_functions_sorted
8019
8020 (* Generate the OCaml bindings implementation. *)
8021 and generate_ocaml_ml () =
8022   generate_header OCamlStyle LGPLv2plus;
8023
8024   pr "\
8025 type t
8026
8027 exception Error of string
8028 exception Handle_closed of string
8029
8030 external create : unit -> t = \"ocaml_guestfs_create\"
8031 external close : t -> unit = \"ocaml_guestfs_close\"
8032
8033 (* Give the exceptions names, so they can be raised from the C code. *)
8034 let () =
8035   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8036   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8037
8038 ";
8039
8040   generate_ocaml_structure_decls ();
8041
8042   (* The actions. *)
8043   List.iter (
8044     fun (name, style, _, _, _, shortdesc, _) ->
8045       generate_ocaml_prototype ~is_external:true name style;
8046   ) all_functions_sorted
8047
8048 (* Generate the OCaml bindings C implementation. *)
8049 and generate_ocaml_c () =
8050   generate_header CStyle LGPLv2plus;
8051
8052   pr "\
8053 #include <stdio.h>
8054 #include <stdlib.h>
8055 #include <string.h>
8056
8057 #include <caml/config.h>
8058 #include <caml/alloc.h>
8059 #include <caml/callback.h>
8060 #include <caml/fail.h>
8061 #include <caml/memory.h>
8062 #include <caml/mlvalues.h>
8063 #include <caml/signals.h>
8064
8065 #include <guestfs.h>
8066
8067 #include \"guestfs_c.h\"
8068
8069 /* Copy a hashtable of string pairs into an assoc-list.  We return
8070  * the list in reverse order, but hashtables aren't supposed to be
8071  * ordered anyway.
8072  */
8073 static CAMLprim value
8074 copy_table (char * const * argv)
8075 {
8076   CAMLparam0 ();
8077   CAMLlocal5 (rv, pairv, kv, vv, cons);
8078   int i;
8079
8080   rv = Val_int (0);
8081   for (i = 0; argv[i] != NULL; i += 2) {
8082     kv = caml_copy_string (argv[i]);
8083     vv = caml_copy_string (argv[i+1]);
8084     pairv = caml_alloc (2, 0);
8085     Store_field (pairv, 0, kv);
8086     Store_field (pairv, 1, vv);
8087     cons = caml_alloc (2, 0);
8088     Store_field (cons, 1, rv);
8089     rv = cons;
8090     Store_field (cons, 0, pairv);
8091   }
8092
8093   CAMLreturn (rv);
8094 }
8095
8096 ";
8097
8098   (* Struct copy functions. *)
8099
8100   let emit_ocaml_copy_list_function typ =
8101     pr "static CAMLprim value\n";
8102     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8103     pr "{\n";
8104     pr "  CAMLparam0 ();\n";
8105     pr "  CAMLlocal2 (rv, v);\n";
8106     pr "  unsigned int i;\n";
8107     pr "\n";
8108     pr "  if (%ss->len == 0)\n" typ;
8109     pr "    CAMLreturn (Atom (0));\n";
8110     pr "  else {\n";
8111     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8112     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8113     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8114     pr "      caml_modify (&Field (rv, i), v);\n";
8115     pr "    }\n";
8116     pr "    CAMLreturn (rv);\n";
8117     pr "  }\n";
8118     pr "}\n";
8119     pr "\n";
8120   in
8121
8122   List.iter (
8123     fun (typ, cols) ->
8124       let has_optpercent_col =
8125         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8126
8127       pr "static CAMLprim value\n";
8128       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8129       pr "{\n";
8130       pr "  CAMLparam0 ();\n";
8131       if has_optpercent_col then
8132         pr "  CAMLlocal3 (rv, v, v2);\n"
8133       else
8134         pr "  CAMLlocal2 (rv, v);\n";
8135       pr "\n";
8136       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8137       iteri (
8138         fun i col ->
8139           (match col with
8140            | name, FString ->
8141                pr "  v = caml_copy_string (%s->%s);\n" typ name
8142            | name, FBuffer ->
8143                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8144                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8145                  typ name typ name
8146            | name, FUUID ->
8147                pr "  v = caml_alloc_string (32);\n";
8148                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8149            | name, (FBytes|FInt64|FUInt64) ->
8150                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8151            | name, (FInt32|FUInt32) ->
8152                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8153            | name, FOptPercent ->
8154                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8155                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8156                pr "    v = caml_alloc (1, 0);\n";
8157                pr "    Store_field (v, 0, v2);\n";
8158                pr "  } else /* None */\n";
8159                pr "    v = Val_int (0);\n";
8160            | name, FChar ->
8161                pr "  v = Val_int (%s->%s);\n" typ name
8162           );
8163           pr "  Store_field (rv, %d, v);\n" i
8164       ) cols;
8165       pr "  CAMLreturn (rv);\n";
8166       pr "}\n";
8167       pr "\n";
8168   ) structs;
8169
8170   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8171   List.iter (
8172     function
8173     | typ, (RStructListOnly | RStructAndList) ->
8174         (* generate the function for typ *)
8175         emit_ocaml_copy_list_function typ
8176     | typ, _ -> () (* empty *)
8177   ) (rstructs_used_by all_functions);
8178
8179   (* The wrappers. *)
8180   List.iter (
8181     fun (name, style, _, _, _, _, _) ->
8182       pr "/* Automatically generated wrapper for function\n";
8183       pr " * ";
8184       generate_ocaml_prototype name style;
8185       pr " */\n";
8186       pr "\n";
8187
8188       let params =
8189         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8190
8191       let needs_extra_vs =
8192         match fst style with RConstOptString _ -> true | _ -> false in
8193
8194       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8195       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8196       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8197       pr "\n";
8198
8199       pr "CAMLprim value\n";
8200       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8201       List.iter (pr ", value %s") (List.tl params);
8202       pr ")\n";
8203       pr "{\n";
8204
8205       (match params with
8206        | [p1; p2; p3; p4; p5] ->
8207            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8208        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8209            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8210            pr "  CAMLxparam%d (%s);\n"
8211              (List.length rest) (String.concat ", " rest)
8212        | ps ->
8213            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8214       );
8215       if not needs_extra_vs then
8216         pr "  CAMLlocal1 (rv);\n"
8217       else
8218         pr "  CAMLlocal3 (rv, v, v2);\n";
8219       pr "\n";
8220
8221       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8222       pr "  if (g == NULL)\n";
8223       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8224       pr "\n";
8225
8226       List.iter (
8227         function
8228         | Pathname n
8229         | Device n | Dev_or_Path n
8230         | String n
8231         | FileIn n
8232         | FileOut n ->
8233             pr "  const char *%s = String_val (%sv);\n" n n
8234         | OptString n ->
8235             pr "  const char *%s =\n" n;
8236             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8237               n n
8238         | StringList n | DeviceList n ->
8239             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8240         | Bool n ->
8241             pr "  int %s = Bool_val (%sv);\n" n n
8242         | Int n ->
8243             pr "  int %s = Int_val (%sv);\n" n n
8244         | Int64 n ->
8245             pr "  int64_t %s = Int64_val (%sv);\n" n n
8246       ) (snd style);
8247       let error_code =
8248         match fst style with
8249         | RErr -> pr "  int r;\n"; "-1"
8250         | RInt _ -> pr "  int r;\n"; "-1"
8251         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8252         | RBool _ -> pr "  int r;\n"; "-1"
8253         | RConstString _ | RConstOptString _ ->
8254             pr "  const char *r;\n"; "NULL"
8255         | RString _ -> pr "  char *r;\n"; "NULL"
8256         | RStringList _ ->
8257             pr "  int i;\n";
8258             pr "  char **r;\n";
8259             "NULL"
8260         | RStruct (_, typ) ->
8261             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8262         | RStructList (_, typ) ->
8263             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8264         | RHashtable _ ->
8265             pr "  int i;\n";
8266             pr "  char **r;\n";
8267             "NULL"
8268         | RBufferOut _ ->
8269             pr "  char *r;\n";
8270             pr "  size_t size;\n";
8271             "NULL" in
8272       pr "\n";
8273
8274       pr "  caml_enter_blocking_section ();\n";
8275       pr "  r = guestfs_%s " name;
8276       generate_c_call_args ~handle:"g" style;
8277       pr ";\n";
8278       pr "  caml_leave_blocking_section ();\n";
8279
8280       List.iter (
8281         function
8282         | StringList n | DeviceList n ->
8283             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8284         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8285         | Bool _ | Int _ | Int64 _
8286         | FileIn _ | FileOut _ -> ()
8287       ) (snd style);
8288
8289       pr "  if (r == %s)\n" error_code;
8290       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8291       pr "\n";
8292
8293       (match fst style with
8294        | RErr -> pr "  rv = Val_unit;\n"
8295        | RInt _ -> pr "  rv = Val_int (r);\n"
8296        | RInt64 _ ->
8297            pr "  rv = caml_copy_int64 (r);\n"
8298        | RBool _ -> pr "  rv = Val_bool (r);\n"
8299        | RConstString _ ->
8300            pr "  rv = caml_copy_string (r);\n"
8301        | RConstOptString _ ->
8302            pr "  if (r) { /* Some string */\n";
8303            pr "    v = caml_alloc (1, 0);\n";
8304            pr "    v2 = caml_copy_string (r);\n";
8305            pr "    Store_field (v, 0, v2);\n";
8306            pr "  } else /* None */\n";
8307            pr "    v = Val_int (0);\n";
8308        | RString _ ->
8309            pr "  rv = caml_copy_string (r);\n";
8310            pr "  free (r);\n"
8311        | RStringList _ ->
8312            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8313            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8314            pr "  free (r);\n"
8315        | RStruct (_, typ) ->
8316            pr "  rv = copy_%s (r);\n" typ;
8317            pr "  guestfs_free_%s (r);\n" typ;
8318        | RStructList (_, typ) ->
8319            pr "  rv = copy_%s_list (r);\n" typ;
8320            pr "  guestfs_free_%s_list (r);\n" typ;
8321        | RHashtable _ ->
8322            pr "  rv = copy_table (r);\n";
8323            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8324            pr "  free (r);\n";
8325        | RBufferOut _ ->
8326            pr "  rv = caml_alloc_string (size);\n";
8327            pr "  memcpy (String_val (rv), r, size);\n";
8328       );
8329
8330       pr "  CAMLreturn (rv);\n";
8331       pr "}\n";
8332       pr "\n";
8333
8334       if List.length params > 5 then (
8335         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8336         pr "CAMLprim value ";
8337         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8338         pr "CAMLprim value\n";
8339         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8340         pr "{\n";
8341         pr "  return ocaml_guestfs_%s (argv[0]" name;
8342         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8343         pr ");\n";
8344         pr "}\n";
8345         pr "\n"
8346       )
8347   ) all_functions_sorted
8348
8349 and generate_ocaml_structure_decls () =
8350   List.iter (
8351     fun (typ, cols) ->
8352       pr "type %s = {\n" typ;
8353       List.iter (
8354         function
8355         | name, FString -> pr "  %s : string;\n" name
8356         | name, FBuffer -> pr "  %s : string;\n" name
8357         | name, FUUID -> pr "  %s : string;\n" name
8358         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8359         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8360         | name, FChar -> pr "  %s : char;\n" name
8361         | name, FOptPercent -> pr "  %s : float option;\n" name
8362       ) cols;
8363       pr "}\n";
8364       pr "\n"
8365   ) structs
8366
8367 and generate_ocaml_prototype ?(is_external = false) name style =
8368   if is_external then pr "external " else pr "val ";
8369   pr "%s : t -> " name;
8370   List.iter (
8371     function
8372     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8373     | OptString _ -> pr "string option -> "
8374     | StringList _ | DeviceList _ -> pr "string array -> "
8375     | Bool _ -> pr "bool -> "
8376     | Int _ -> pr "int -> "
8377     | Int64 _ -> pr "int64 -> "
8378   ) (snd style);
8379   (match fst style with
8380    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8381    | RInt _ -> pr "int"
8382    | RInt64 _ -> pr "int64"
8383    | RBool _ -> pr "bool"
8384    | RConstString _ -> pr "string"
8385    | RConstOptString _ -> pr "string option"
8386    | RString _ | RBufferOut _ -> pr "string"
8387    | RStringList _ -> pr "string array"
8388    | RStruct (_, typ) -> pr "%s" typ
8389    | RStructList (_, typ) -> pr "%s array" typ
8390    | RHashtable _ -> pr "(string * string) list"
8391   );
8392   if is_external then (
8393     pr " = ";
8394     if List.length (snd style) + 1 > 5 then
8395       pr "\"ocaml_guestfs_%s_byte\" " name;
8396     pr "\"ocaml_guestfs_%s\"" name
8397   );
8398   pr "\n"
8399
8400 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8401 and generate_perl_xs () =
8402   generate_header CStyle LGPLv2plus;
8403
8404   pr "\
8405 #include \"EXTERN.h\"
8406 #include \"perl.h\"
8407 #include \"XSUB.h\"
8408
8409 #include <guestfs.h>
8410
8411 #ifndef PRId64
8412 #define PRId64 \"lld\"
8413 #endif
8414
8415 static SV *
8416 my_newSVll(long long val) {
8417 #ifdef USE_64_BIT_ALL
8418   return newSViv(val);
8419 #else
8420   char buf[100];
8421   int len;
8422   len = snprintf(buf, 100, \"%%\" PRId64, val);
8423   return newSVpv(buf, len);
8424 #endif
8425 }
8426
8427 #ifndef PRIu64
8428 #define PRIu64 \"llu\"
8429 #endif
8430
8431 static SV *
8432 my_newSVull(unsigned long long val) {
8433 #ifdef USE_64_BIT_ALL
8434   return newSVuv(val);
8435 #else
8436   char buf[100];
8437   int len;
8438   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8439   return newSVpv(buf, len);
8440 #endif
8441 }
8442
8443 /* http://www.perlmonks.org/?node_id=680842 */
8444 static char **
8445 XS_unpack_charPtrPtr (SV *arg) {
8446   char **ret;
8447   AV *av;
8448   I32 i;
8449
8450   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8451     croak (\"array reference expected\");
8452
8453   av = (AV *)SvRV (arg);
8454   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8455   if (!ret)
8456     croak (\"malloc failed\");
8457
8458   for (i = 0; i <= av_len (av); i++) {
8459     SV **elem = av_fetch (av, i, 0);
8460
8461     if (!elem || !*elem)
8462       croak (\"missing element in list\");
8463
8464     ret[i] = SvPV_nolen (*elem);
8465   }
8466
8467   ret[i] = NULL;
8468
8469   return ret;
8470 }
8471
8472 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8473
8474 PROTOTYPES: ENABLE
8475
8476 guestfs_h *
8477 _create ()
8478    CODE:
8479       RETVAL = guestfs_create ();
8480       if (!RETVAL)
8481         croak (\"could not create guestfs handle\");
8482       guestfs_set_error_handler (RETVAL, NULL, NULL);
8483  OUTPUT:
8484       RETVAL
8485
8486 void
8487 DESTROY (g)
8488       guestfs_h *g;
8489  PPCODE:
8490       guestfs_close (g);
8491
8492 ";
8493
8494   List.iter (
8495     fun (name, style, _, _, _, _, _) ->
8496       (match fst style with
8497        | RErr -> pr "void\n"
8498        | RInt _ -> pr "SV *\n"
8499        | RInt64 _ -> pr "SV *\n"
8500        | RBool _ -> pr "SV *\n"
8501        | RConstString _ -> pr "SV *\n"
8502        | RConstOptString _ -> pr "SV *\n"
8503        | RString _ -> pr "SV *\n"
8504        | RBufferOut _ -> pr "SV *\n"
8505        | RStringList _
8506        | RStruct _ | RStructList _
8507        | RHashtable _ ->
8508            pr "void\n" (* all lists returned implictly on the stack *)
8509       );
8510       (* Call and arguments. *)
8511       pr "%s " name;
8512       generate_c_call_args ~handle:"g" ~decl:true style;
8513       pr "\n";
8514       pr "      guestfs_h *g;\n";
8515       iteri (
8516         fun i ->
8517           function
8518           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8519               pr "      char *%s;\n" n
8520           | OptString n ->
8521               (* http://www.perlmonks.org/?node_id=554277
8522                * Note that the implicit handle argument means we have
8523                * to add 1 to the ST(x) operator.
8524                *)
8525               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8526           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8527           | Bool n -> pr "      int %s;\n" n
8528           | Int n -> pr "      int %s;\n" n
8529           | Int64 n -> pr "      int64_t %s;\n" n
8530       ) (snd style);
8531
8532       let do_cleanups () =
8533         List.iter (
8534           function
8535           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8536           | Bool _ | Int _ | Int64 _
8537           | FileIn _ | FileOut _ -> ()
8538           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8539         ) (snd style)
8540       in
8541
8542       (* Code. *)
8543       (match fst style with
8544        | RErr ->
8545            pr "PREINIT:\n";
8546            pr "      int r;\n";
8547            pr " PPCODE:\n";
8548            pr "      r = guestfs_%s " name;
8549            generate_c_call_args ~handle:"g" style;
8550            pr ";\n";
8551            do_cleanups ();
8552            pr "      if (r == -1)\n";
8553            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8554        | RInt n
8555        | RBool n ->
8556            pr "PREINIT:\n";
8557            pr "      int %s;\n" n;
8558            pr "   CODE:\n";
8559            pr "      %s = guestfs_%s " n name;
8560            generate_c_call_args ~handle:"g" style;
8561            pr ";\n";
8562            do_cleanups ();
8563            pr "      if (%s == -1)\n" n;
8564            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8565            pr "      RETVAL = newSViv (%s);\n" n;
8566            pr " OUTPUT:\n";
8567            pr "      RETVAL\n"
8568        | RInt64 n ->
8569            pr "PREINIT:\n";
8570            pr "      int64_t %s;\n" n;
8571            pr "   CODE:\n";
8572            pr "      %s = guestfs_%s " n name;
8573            generate_c_call_args ~handle:"g" style;
8574            pr ";\n";
8575            do_cleanups ();
8576            pr "      if (%s == -1)\n" n;
8577            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8578            pr "      RETVAL = my_newSVll (%s);\n" n;
8579            pr " OUTPUT:\n";
8580            pr "      RETVAL\n"
8581        | RConstString n ->
8582            pr "PREINIT:\n";
8583            pr "      const char *%s;\n" n;
8584            pr "   CODE:\n";
8585            pr "      %s = guestfs_%s " n name;
8586            generate_c_call_args ~handle:"g" style;
8587            pr ";\n";
8588            do_cleanups ();
8589            pr "      if (%s == NULL)\n" n;
8590            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8591            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8592            pr " OUTPUT:\n";
8593            pr "      RETVAL\n"
8594        | RConstOptString n ->
8595            pr "PREINIT:\n";
8596            pr "      const char *%s;\n" n;
8597            pr "   CODE:\n";
8598            pr "      %s = guestfs_%s " n name;
8599            generate_c_call_args ~handle:"g" style;
8600            pr ";\n";
8601            do_cleanups ();
8602            pr "      if (%s == NULL)\n" n;
8603            pr "        RETVAL = &PL_sv_undef;\n";
8604            pr "      else\n";
8605            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8606            pr " OUTPUT:\n";
8607            pr "      RETVAL\n"
8608        | RString n ->
8609            pr "PREINIT:\n";
8610            pr "      char *%s;\n" n;
8611            pr "   CODE:\n";
8612            pr "      %s = guestfs_%s " n name;
8613            generate_c_call_args ~handle:"g" style;
8614            pr ";\n";
8615            do_cleanups ();
8616            pr "      if (%s == NULL)\n" n;
8617            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8618            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8619            pr "      free (%s);\n" n;
8620            pr " OUTPUT:\n";
8621            pr "      RETVAL\n"
8622        | RStringList n | RHashtable n ->
8623            pr "PREINIT:\n";
8624            pr "      char **%s;\n" n;
8625            pr "      int i, n;\n";
8626            pr " PPCODE:\n";
8627            pr "      %s = guestfs_%s " n name;
8628            generate_c_call_args ~handle:"g" style;
8629            pr ";\n";
8630            do_cleanups ();
8631            pr "      if (%s == NULL)\n" n;
8632            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8633            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8634            pr "      EXTEND (SP, n);\n";
8635            pr "      for (i = 0; i < n; ++i) {\n";
8636            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8637            pr "        free (%s[i]);\n" n;
8638            pr "      }\n";
8639            pr "      free (%s);\n" n;
8640        | RStruct (n, typ) ->
8641            let cols = cols_of_struct typ in
8642            generate_perl_struct_code typ cols name style n do_cleanups
8643        | RStructList (n, typ) ->
8644            let cols = cols_of_struct typ in
8645            generate_perl_struct_list_code typ cols name style n do_cleanups
8646        | RBufferOut n ->
8647            pr "PREINIT:\n";
8648            pr "      char *%s;\n" n;
8649            pr "      size_t size;\n";
8650            pr "   CODE:\n";
8651            pr "      %s = guestfs_%s " n name;
8652            generate_c_call_args ~handle:"g" style;
8653            pr ";\n";
8654            do_cleanups ();
8655            pr "      if (%s == NULL)\n" n;
8656            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8657            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8658            pr "      free (%s);\n" n;
8659            pr " OUTPUT:\n";
8660            pr "      RETVAL\n"
8661       );
8662
8663       pr "\n"
8664   ) all_functions
8665
8666 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8667   pr "PREINIT:\n";
8668   pr "      struct guestfs_%s_list *%s;\n" typ n;
8669   pr "      int i;\n";
8670   pr "      HV *hv;\n";
8671   pr " PPCODE:\n";
8672   pr "      %s = guestfs_%s " n name;
8673   generate_c_call_args ~handle:"g" style;
8674   pr ";\n";
8675   do_cleanups ();
8676   pr "      if (%s == NULL)\n" n;
8677   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8678   pr "      EXTEND (SP, %s->len);\n" n;
8679   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8680   pr "        hv = newHV ();\n";
8681   List.iter (
8682     function
8683     | name, FString ->
8684         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8685           name (String.length name) n name
8686     | name, FUUID ->
8687         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8688           name (String.length name) n name
8689     | name, FBuffer ->
8690         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8691           name (String.length name) n name n name
8692     | name, (FBytes|FUInt64) ->
8693         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8694           name (String.length name) n name
8695     | name, FInt64 ->
8696         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8697           name (String.length name) n name
8698     | name, (FInt32|FUInt32) ->
8699         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8700           name (String.length name) n name
8701     | name, FChar ->
8702         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8703           name (String.length name) n name
8704     | name, FOptPercent ->
8705         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8706           name (String.length name) n name
8707   ) cols;
8708   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8709   pr "      }\n";
8710   pr "      guestfs_free_%s_list (%s);\n" typ n
8711
8712 and generate_perl_struct_code typ cols name style n do_cleanups =
8713   pr "PREINIT:\n";
8714   pr "      struct guestfs_%s *%s;\n" typ n;
8715   pr " PPCODE:\n";
8716   pr "      %s = guestfs_%s " n name;
8717   generate_c_call_args ~handle:"g" style;
8718   pr ";\n";
8719   do_cleanups ();
8720   pr "      if (%s == NULL)\n" n;
8721   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8722   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8723   List.iter (
8724     fun ((name, _) as col) ->
8725       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8726
8727       match col with
8728       | name, FString ->
8729           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8730             n name
8731       | name, FBuffer ->
8732           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8733             n name n name
8734       | name, FUUID ->
8735           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8736             n name
8737       | name, (FBytes|FUInt64) ->
8738           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8739             n name
8740       | name, FInt64 ->
8741           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8742             n name
8743       | name, (FInt32|FUInt32) ->
8744           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8745             n name
8746       | name, FChar ->
8747           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8748             n name
8749       | name, FOptPercent ->
8750           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8751             n name
8752   ) cols;
8753   pr "      free (%s);\n" n
8754
8755 (* Generate Sys/Guestfs.pm. *)
8756 and generate_perl_pm () =
8757   generate_header HashStyle LGPLv2plus;
8758
8759   pr "\
8760 =pod
8761
8762 =head1 NAME
8763
8764 Sys::Guestfs - Perl bindings for libguestfs
8765
8766 =head1 SYNOPSIS
8767
8768  use Sys::Guestfs;
8769
8770  my $h = Sys::Guestfs->new ();
8771  $h->add_drive ('guest.img');
8772  $h->launch ();
8773  $h->mount ('/dev/sda1', '/');
8774  $h->touch ('/hello');
8775  $h->sync ();
8776
8777 =head1 DESCRIPTION
8778
8779 The C<Sys::Guestfs> module provides a Perl XS binding to the
8780 libguestfs API for examining and modifying virtual machine
8781 disk images.
8782
8783 Amongst the things this is good for: making batch configuration
8784 changes to guests, getting disk used/free statistics (see also:
8785 virt-df), migrating between virtualization systems (see also:
8786 virt-p2v), performing partial backups, performing partial guest
8787 clones, cloning guests and changing registry/UUID/hostname info, and
8788 much else besides.
8789
8790 Libguestfs uses Linux kernel and qemu code, and can access any type of
8791 guest filesystem that Linux and qemu can, including but not limited
8792 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8793 schemes, qcow, qcow2, vmdk.
8794
8795 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8796 LVs, what filesystem is in each LV, etc.).  It can also run commands
8797 in the context of the guest.  Also you can access filesystems over
8798 FUSE.
8799
8800 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8801 functions for using libguestfs from Perl, including integration
8802 with libvirt.
8803
8804 =head1 ERRORS
8805
8806 All errors turn into calls to C<croak> (see L<Carp(3)>).
8807
8808 =head1 METHODS
8809
8810 =over 4
8811
8812 =cut
8813
8814 package Sys::Guestfs;
8815
8816 use strict;
8817 use warnings;
8818
8819 # This version number changes whenever a new function
8820 # is added to the libguestfs API.  It is not directly
8821 # related to the libguestfs version number.
8822 use vars qw($VERSION);
8823 $VERSION = '0.%d';
8824
8825 require XSLoader;
8826 XSLoader::load ('Sys::Guestfs');
8827
8828 =item $h = Sys::Guestfs->new ();
8829
8830 Create a new guestfs handle.
8831
8832 =cut
8833
8834 sub new {
8835   my $proto = shift;
8836   my $class = ref ($proto) || $proto;
8837
8838   my $self = Sys::Guestfs::_create ();
8839   bless $self, $class;
8840   return $self;
8841 }
8842
8843 " max_proc_nr;
8844
8845   (* Actions.  We only need to print documentation for these as
8846    * they are pulled in from the XS code automatically.
8847    *)
8848   List.iter (
8849     fun (name, style, _, flags, _, _, longdesc) ->
8850       if not (List.mem NotInDocs flags) then (
8851         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8852         pr "=item ";
8853         generate_perl_prototype name style;
8854         pr "\n\n";
8855         pr "%s\n\n" longdesc;
8856         if List.mem ProtocolLimitWarning flags then
8857           pr "%s\n\n" protocol_limit_warning;
8858         if List.mem DangerWillRobinson flags then
8859           pr "%s\n\n" danger_will_robinson;
8860         match deprecation_notice flags with
8861         | None -> ()
8862         | Some txt -> pr "%s\n\n" txt
8863       )
8864   ) all_functions_sorted;
8865
8866   (* End of file. *)
8867   pr "\
8868 =cut
8869
8870 1;
8871
8872 =back
8873
8874 =head1 COPYRIGHT
8875
8876 Copyright (C) %s Red Hat Inc.
8877
8878 =head1 LICENSE
8879
8880 Please see the file COPYING.LIB for the full license.
8881
8882 =head1 SEE ALSO
8883
8884 L<guestfs(3)>,
8885 L<guestfish(1)>,
8886 L<http://libguestfs.org>,
8887 L<Sys::Guestfs::Lib(3)>.
8888
8889 =cut
8890 " copyright_years
8891
8892 and generate_perl_prototype name style =
8893   (match fst style with
8894    | RErr -> ()
8895    | RBool n
8896    | RInt n
8897    | RInt64 n
8898    | RConstString n
8899    | RConstOptString n
8900    | RString n
8901    | RBufferOut n -> pr "$%s = " n
8902    | RStruct (n,_)
8903    | RHashtable n -> pr "%%%s = " n
8904    | RStringList n
8905    | RStructList (n,_) -> pr "@%s = " n
8906   );
8907   pr "$h->%s (" name;
8908   let comma = ref false in
8909   List.iter (
8910     fun arg ->
8911       if !comma then pr ", ";
8912       comma := true;
8913       match arg with
8914       | Pathname n | Device n | Dev_or_Path n | String n
8915       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8916           pr "$%s" n
8917       | StringList n | DeviceList n ->
8918           pr "\\@%s" n
8919   ) (snd style);
8920   pr ");"
8921
8922 (* Generate Python C module. *)
8923 and generate_python_c () =
8924   generate_header CStyle LGPLv2plus;
8925
8926   pr "\
8927 #include <Python.h>
8928
8929 #include <stdio.h>
8930 #include <stdlib.h>
8931 #include <assert.h>
8932
8933 #include \"guestfs.h\"
8934
8935 typedef struct {
8936   PyObject_HEAD
8937   guestfs_h *g;
8938 } Pyguestfs_Object;
8939
8940 static guestfs_h *
8941 get_handle (PyObject *obj)
8942 {
8943   assert (obj);
8944   assert (obj != Py_None);
8945   return ((Pyguestfs_Object *) obj)->g;
8946 }
8947
8948 static PyObject *
8949 put_handle (guestfs_h *g)
8950 {
8951   assert (g);
8952   return
8953     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8954 }
8955
8956 /* This list should be freed (but not the strings) after use. */
8957 static char **
8958 get_string_list (PyObject *obj)
8959 {
8960   int i, len;
8961   char **r;
8962
8963   assert (obj);
8964
8965   if (!PyList_Check (obj)) {
8966     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8967     return NULL;
8968   }
8969
8970   len = PyList_Size (obj);
8971   r = malloc (sizeof (char *) * (len+1));
8972   if (r == NULL) {
8973     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8974     return NULL;
8975   }
8976
8977   for (i = 0; i < len; ++i)
8978     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8979   r[len] = NULL;
8980
8981   return r;
8982 }
8983
8984 static PyObject *
8985 put_string_list (char * const * const argv)
8986 {
8987   PyObject *list;
8988   int argc, i;
8989
8990   for (argc = 0; argv[argc] != NULL; ++argc)
8991     ;
8992
8993   list = PyList_New (argc);
8994   for (i = 0; i < argc; ++i)
8995     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8996
8997   return list;
8998 }
8999
9000 static PyObject *
9001 put_table (char * const * const argv)
9002 {
9003   PyObject *list, *item;
9004   int argc, i;
9005
9006   for (argc = 0; argv[argc] != NULL; ++argc)
9007     ;
9008
9009   list = PyList_New (argc >> 1);
9010   for (i = 0; i < argc; i += 2) {
9011     item = PyTuple_New (2);
9012     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9013     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9014     PyList_SetItem (list, i >> 1, item);
9015   }
9016
9017   return list;
9018 }
9019
9020 static void
9021 free_strings (char **argv)
9022 {
9023   int argc;
9024
9025   for (argc = 0; argv[argc] != NULL; ++argc)
9026     free (argv[argc]);
9027   free (argv);
9028 }
9029
9030 static PyObject *
9031 py_guestfs_create (PyObject *self, PyObject *args)
9032 {
9033   guestfs_h *g;
9034
9035   g = guestfs_create ();
9036   if (g == NULL) {
9037     PyErr_SetString (PyExc_RuntimeError,
9038                      \"guestfs.create: failed to allocate handle\");
9039     return NULL;
9040   }
9041   guestfs_set_error_handler (g, NULL, NULL);
9042   return put_handle (g);
9043 }
9044
9045 static PyObject *
9046 py_guestfs_close (PyObject *self, PyObject *args)
9047 {
9048   PyObject *py_g;
9049   guestfs_h *g;
9050
9051   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9052     return NULL;
9053   g = get_handle (py_g);
9054
9055   guestfs_close (g);
9056
9057   Py_INCREF (Py_None);
9058   return Py_None;
9059 }
9060
9061 ";
9062
9063   let emit_put_list_function typ =
9064     pr "static PyObject *\n";
9065     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9066     pr "{\n";
9067     pr "  PyObject *list;\n";
9068     pr "  int i;\n";
9069     pr "\n";
9070     pr "  list = PyList_New (%ss->len);\n" typ;
9071     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9072     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9073     pr "  return list;\n";
9074     pr "};\n";
9075     pr "\n"
9076   in
9077
9078   (* Structures, turned into Python dictionaries. *)
9079   List.iter (
9080     fun (typ, cols) ->
9081       pr "static PyObject *\n";
9082       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9083       pr "{\n";
9084       pr "  PyObject *dict;\n";
9085       pr "\n";
9086       pr "  dict = PyDict_New ();\n";
9087       List.iter (
9088         function
9089         | name, FString ->
9090             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9091             pr "                        PyString_FromString (%s->%s));\n"
9092               typ name
9093         | name, FBuffer ->
9094             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9095             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9096               typ name typ name
9097         | name, FUUID ->
9098             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9099             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9100               typ name
9101         | name, (FBytes|FUInt64) ->
9102             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9103             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9104               typ name
9105         | name, FInt64 ->
9106             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9107             pr "                        PyLong_FromLongLong (%s->%s));\n"
9108               typ name
9109         | name, FUInt32 ->
9110             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9111             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9112               typ name
9113         | name, FInt32 ->
9114             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9115             pr "                        PyLong_FromLong (%s->%s));\n"
9116               typ name
9117         | name, FOptPercent ->
9118             pr "  if (%s->%s >= 0)\n" typ name;
9119             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9120             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9121               typ name;
9122             pr "  else {\n";
9123             pr "    Py_INCREF (Py_None);\n";
9124             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9125             pr "  }\n"
9126         | name, FChar ->
9127             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9128             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9129       ) cols;
9130       pr "  return dict;\n";
9131       pr "};\n";
9132       pr "\n";
9133
9134   ) structs;
9135
9136   (* Emit a put_TYPE_list function definition only if that function is used. *)
9137   List.iter (
9138     function
9139     | typ, (RStructListOnly | RStructAndList) ->
9140         (* generate the function for typ *)
9141         emit_put_list_function typ
9142     | typ, _ -> () (* empty *)
9143   ) (rstructs_used_by all_functions);
9144
9145   (* Python wrapper functions. *)
9146   List.iter (
9147     fun (name, style, _, _, _, _, _) ->
9148       pr "static PyObject *\n";
9149       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9150       pr "{\n";
9151
9152       pr "  PyObject *py_g;\n";
9153       pr "  guestfs_h *g;\n";
9154       pr "  PyObject *py_r;\n";
9155
9156       let error_code =
9157         match fst style with
9158         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9159         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9160         | RConstString _ | RConstOptString _ ->
9161             pr "  const char *r;\n"; "NULL"
9162         | RString _ -> pr "  char *r;\n"; "NULL"
9163         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9164         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9165         | RStructList (_, typ) ->
9166             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9167         | RBufferOut _ ->
9168             pr "  char *r;\n";
9169             pr "  size_t size;\n";
9170             "NULL" in
9171
9172       List.iter (
9173         function
9174         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9175             pr "  const char *%s;\n" n
9176         | OptString n -> pr "  const char *%s;\n" n
9177         | StringList n | DeviceList n ->
9178             pr "  PyObject *py_%s;\n" n;
9179             pr "  char **%s;\n" n
9180         | Bool n -> pr "  int %s;\n" n
9181         | Int n -> pr "  int %s;\n" n
9182         | Int64 n -> pr "  long long %s;\n" n
9183       ) (snd style);
9184
9185       pr "\n";
9186
9187       (* Convert the parameters. *)
9188       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9189       List.iter (
9190         function
9191         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9192         | OptString _ -> pr "z"
9193         | StringList _ | DeviceList _ -> pr "O"
9194         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9195         | Int _ -> pr "i"
9196         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9197                              * emulate C's int/long/long long in Python?
9198                              *)
9199       ) (snd style);
9200       pr ":guestfs_%s\",\n" name;
9201       pr "                         &py_g";
9202       List.iter (
9203         function
9204         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9205         | OptString n -> pr ", &%s" n
9206         | StringList n | DeviceList n -> pr ", &py_%s" n
9207         | Bool n -> pr ", &%s" n
9208         | Int n -> pr ", &%s" n
9209         | Int64 n -> pr ", &%s" n
9210       ) (snd style);
9211
9212       pr "))\n";
9213       pr "    return NULL;\n";
9214
9215       pr "  g = get_handle (py_g);\n";
9216       List.iter (
9217         function
9218         | Pathname _ | Device _ | Dev_or_Path _ | String _
9219         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9220         | StringList n | DeviceList n ->
9221             pr "  %s = get_string_list (py_%s);\n" n n;
9222             pr "  if (!%s) return NULL;\n" n
9223       ) (snd style);
9224
9225       pr "\n";
9226
9227       pr "  r = guestfs_%s " name;
9228       generate_c_call_args ~handle:"g" style;
9229       pr ";\n";
9230
9231       List.iter (
9232         function
9233         | Pathname _ | Device _ | Dev_or_Path _ | String _
9234         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9235         | StringList n | DeviceList n ->
9236             pr "  free (%s);\n" n
9237       ) (snd style);
9238
9239       pr "  if (r == %s) {\n" error_code;
9240       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9241       pr "    return NULL;\n";
9242       pr "  }\n";
9243       pr "\n";
9244
9245       (match fst style with
9246        | RErr ->
9247            pr "  Py_INCREF (Py_None);\n";
9248            pr "  py_r = Py_None;\n"
9249        | RInt _
9250        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9251        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9252        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9253        | RConstOptString _ ->
9254            pr "  if (r)\n";
9255            pr "    py_r = PyString_FromString (r);\n";
9256            pr "  else {\n";
9257            pr "    Py_INCREF (Py_None);\n";
9258            pr "    py_r = Py_None;\n";
9259            pr "  }\n"
9260        | RString _ ->
9261            pr "  py_r = PyString_FromString (r);\n";
9262            pr "  free (r);\n"
9263        | RStringList _ ->
9264            pr "  py_r = put_string_list (r);\n";
9265            pr "  free_strings (r);\n"
9266        | RStruct (_, typ) ->
9267            pr "  py_r = put_%s (r);\n" typ;
9268            pr "  guestfs_free_%s (r);\n" typ
9269        | RStructList (_, typ) ->
9270            pr "  py_r = put_%s_list (r);\n" typ;
9271            pr "  guestfs_free_%s_list (r);\n" typ
9272        | RHashtable n ->
9273            pr "  py_r = put_table (r);\n";
9274            pr "  free_strings (r);\n"
9275        | RBufferOut _ ->
9276            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9277            pr "  free (r);\n"
9278       );
9279
9280       pr "  return py_r;\n";
9281       pr "}\n";
9282       pr "\n"
9283   ) all_functions;
9284
9285   (* Table of functions. *)
9286   pr "static PyMethodDef methods[] = {\n";
9287   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9288   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9289   List.iter (
9290     fun (name, _, _, _, _, _, _) ->
9291       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9292         name name
9293   ) all_functions;
9294   pr "  { NULL, NULL, 0, NULL }\n";
9295   pr "};\n";
9296   pr "\n";
9297
9298   (* Init function. *)
9299   pr "\
9300 void
9301 initlibguestfsmod (void)
9302 {
9303   static int initialized = 0;
9304
9305   if (initialized) return;
9306   Py_InitModule ((char *) \"libguestfsmod\", methods);
9307   initialized = 1;
9308 }
9309 "
9310
9311 (* Generate Python module. *)
9312 and generate_python_py () =
9313   generate_header HashStyle LGPLv2plus;
9314
9315   pr "\
9316 u\"\"\"Python bindings for libguestfs
9317
9318 import guestfs
9319 g = guestfs.GuestFS ()
9320 g.add_drive (\"guest.img\")
9321 g.launch ()
9322 parts = g.list_partitions ()
9323
9324 The guestfs module provides a Python binding to the libguestfs API
9325 for examining and modifying virtual machine disk images.
9326
9327 Amongst the things this is good for: making batch configuration
9328 changes to guests, getting disk used/free statistics (see also:
9329 virt-df), migrating between virtualization systems (see also:
9330 virt-p2v), performing partial backups, performing partial guest
9331 clones, cloning guests and changing registry/UUID/hostname info, and
9332 much else besides.
9333
9334 Libguestfs uses Linux kernel and qemu code, and can access any type of
9335 guest filesystem that Linux and qemu can, including but not limited
9336 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9337 schemes, qcow, qcow2, vmdk.
9338
9339 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9340 LVs, what filesystem is in each LV, etc.).  It can also run commands
9341 in the context of the guest.  Also you can access filesystems over
9342 FUSE.
9343
9344 Errors which happen while using the API are turned into Python
9345 RuntimeError exceptions.
9346
9347 To create a guestfs handle you usually have to perform the following
9348 sequence of calls:
9349
9350 # Create the handle, call add_drive at least once, and possibly
9351 # several times if the guest has multiple block devices:
9352 g = guestfs.GuestFS ()
9353 g.add_drive (\"guest.img\")
9354
9355 # Launch the qemu subprocess and wait for it to become ready:
9356 g.launch ()
9357
9358 # Now you can issue commands, for example:
9359 logvols = g.lvs ()
9360
9361 \"\"\"
9362
9363 import libguestfsmod
9364
9365 class GuestFS:
9366     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9367
9368     def __init__ (self):
9369         \"\"\"Create a new libguestfs handle.\"\"\"
9370         self._o = libguestfsmod.create ()
9371
9372     def __del__ (self):
9373         libguestfsmod.close (self._o)
9374
9375 ";
9376
9377   List.iter (
9378     fun (name, style, _, flags, _, _, longdesc) ->
9379       pr "    def %s " name;
9380       generate_py_call_args ~handle:"self" (snd style);
9381       pr ":\n";
9382
9383       if not (List.mem NotInDocs flags) then (
9384         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9385         let doc =
9386           match fst style with
9387           | RErr | RInt _ | RInt64 _ | RBool _
9388           | RConstOptString _ | RConstString _
9389           | RString _ | RBufferOut _ -> doc
9390           | RStringList _ ->
9391               doc ^ "\n\nThis function returns a list of strings."
9392           | RStruct (_, typ) ->
9393               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9394           | RStructList (_, typ) ->
9395               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9396           | RHashtable _ ->
9397               doc ^ "\n\nThis function returns a dictionary." in
9398         let doc =
9399           if List.mem ProtocolLimitWarning flags then
9400             doc ^ "\n\n" ^ protocol_limit_warning
9401           else doc in
9402         let doc =
9403           if List.mem DangerWillRobinson flags then
9404             doc ^ "\n\n" ^ danger_will_robinson
9405           else doc in
9406         let doc =
9407           match deprecation_notice flags with
9408           | None -> doc
9409           | Some txt -> doc ^ "\n\n" ^ txt in
9410         let doc = pod2text ~width:60 name doc in
9411         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9412         let doc = String.concat "\n        " doc in
9413         pr "        u\"\"\"%s\"\"\"\n" doc;
9414       );
9415       pr "        return libguestfsmod.%s " name;
9416       generate_py_call_args ~handle:"self._o" (snd style);
9417       pr "\n";
9418       pr "\n";
9419   ) all_functions
9420
9421 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9422 and generate_py_call_args ~handle args =
9423   pr "(%s" handle;
9424   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9425   pr ")"
9426
9427 (* Useful if you need the longdesc POD text as plain text.  Returns a
9428  * list of lines.
9429  *
9430  * Because this is very slow (the slowest part of autogeneration),
9431  * we memoize the results.
9432  *)
9433 and pod2text ~width name longdesc =
9434   let key = width, name, longdesc in
9435   try Hashtbl.find pod2text_memo key
9436   with Not_found ->
9437     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9438     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9439     close_out chan;
9440     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9441     let chan = open_process_in cmd in
9442     let lines = ref [] in
9443     let rec loop i =
9444       let line = input_line chan in
9445       if i = 1 then             (* discard the first line of output *)
9446         loop (i+1)
9447       else (
9448         let line = triml line in
9449         lines := line :: !lines;
9450         loop (i+1)
9451       ) in
9452     let lines = try loop 1 with End_of_file -> List.rev !lines in
9453     unlink filename;
9454     (match close_process_in chan with
9455      | WEXITED 0 -> ()
9456      | WEXITED i ->
9457          failwithf "pod2text: process exited with non-zero status (%d)" i
9458      | WSIGNALED i | WSTOPPED i ->
9459          failwithf "pod2text: process signalled or stopped by signal %d" i
9460     );
9461     Hashtbl.add pod2text_memo key lines;
9462     pod2text_memo_updated ();
9463     lines
9464
9465 (* Generate ruby bindings. *)
9466 and generate_ruby_c () =
9467   generate_header CStyle LGPLv2plus;
9468
9469   pr "\
9470 #include <stdio.h>
9471 #include <stdlib.h>
9472
9473 #include <ruby.h>
9474
9475 #include \"guestfs.h\"
9476
9477 #include \"extconf.h\"
9478
9479 /* For Ruby < 1.9 */
9480 #ifndef RARRAY_LEN
9481 #define RARRAY_LEN(r) (RARRAY((r))->len)
9482 #endif
9483
9484 static VALUE m_guestfs;                 /* guestfs module */
9485 static VALUE c_guestfs;                 /* guestfs_h handle */
9486 static VALUE e_Error;                   /* used for all errors */
9487
9488 static void ruby_guestfs_free (void *p)
9489 {
9490   if (!p) return;
9491   guestfs_close ((guestfs_h *) p);
9492 }
9493
9494 static VALUE ruby_guestfs_create (VALUE m)
9495 {
9496   guestfs_h *g;
9497
9498   g = guestfs_create ();
9499   if (!g)
9500     rb_raise (e_Error, \"failed to create guestfs handle\");
9501
9502   /* Don't print error messages to stderr by default. */
9503   guestfs_set_error_handler (g, NULL, NULL);
9504
9505   /* Wrap it, and make sure the close function is called when the
9506    * handle goes away.
9507    */
9508   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9509 }
9510
9511 static VALUE ruby_guestfs_close (VALUE gv)
9512 {
9513   guestfs_h *g;
9514   Data_Get_Struct (gv, guestfs_h, g);
9515
9516   ruby_guestfs_free (g);
9517   DATA_PTR (gv) = NULL;
9518
9519   return Qnil;
9520 }
9521
9522 ";
9523
9524   List.iter (
9525     fun (name, style, _, _, _, _, _) ->
9526       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9527       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9528       pr ")\n";
9529       pr "{\n";
9530       pr "  guestfs_h *g;\n";
9531       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9532       pr "  if (!g)\n";
9533       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9534         name;
9535       pr "\n";
9536
9537       List.iter (
9538         function
9539         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9540             pr "  Check_Type (%sv, T_STRING);\n" n;
9541             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9542             pr "  if (!%s)\n" n;
9543             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9544             pr "              \"%s\", \"%s\");\n" n name
9545         | OptString n ->
9546             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9547         | StringList n | DeviceList n ->
9548             pr "  char **%s;\n" n;
9549             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9550             pr "  {\n";
9551             pr "    int i, len;\n";
9552             pr "    len = RARRAY_LEN (%sv);\n" n;
9553             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9554               n;
9555             pr "    for (i = 0; i < len; ++i) {\n";
9556             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9557             pr "      %s[i] = StringValueCStr (v);\n" n;
9558             pr "    }\n";
9559             pr "    %s[len] = NULL;\n" n;
9560             pr "  }\n";
9561         | Bool n ->
9562             pr "  int %s = RTEST (%sv);\n" n n
9563         | Int n ->
9564             pr "  int %s = NUM2INT (%sv);\n" n n
9565         | Int64 n ->
9566             pr "  long long %s = NUM2LL (%sv);\n" n n
9567       ) (snd style);
9568       pr "\n";
9569
9570       let error_code =
9571         match fst style with
9572         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9573         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9574         | RConstString _ | RConstOptString _ ->
9575             pr "  const char *r;\n"; "NULL"
9576         | RString _ -> pr "  char *r;\n"; "NULL"
9577         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9578         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9579         | RStructList (_, typ) ->
9580             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9581         | RBufferOut _ ->
9582             pr "  char *r;\n";
9583             pr "  size_t size;\n";
9584             "NULL" in
9585       pr "\n";
9586
9587       pr "  r = guestfs_%s " name;
9588       generate_c_call_args ~handle:"g" style;
9589       pr ";\n";
9590
9591       List.iter (
9592         function
9593         | Pathname _ | Device _ | Dev_or_Path _ | String _
9594         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9595         | StringList n | DeviceList n ->
9596             pr "  free (%s);\n" n
9597       ) (snd style);
9598
9599       pr "  if (r == %s)\n" error_code;
9600       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9601       pr "\n";
9602
9603       (match fst style with
9604        | RErr ->
9605            pr "  return Qnil;\n"
9606        | RInt _ | RBool _ ->
9607            pr "  return INT2NUM (r);\n"
9608        | RInt64 _ ->
9609            pr "  return ULL2NUM (r);\n"
9610        | RConstString _ ->
9611            pr "  return rb_str_new2 (r);\n";
9612        | RConstOptString _ ->
9613            pr "  if (r)\n";
9614            pr "    return rb_str_new2 (r);\n";
9615            pr "  else\n";
9616            pr "    return Qnil;\n";
9617        | RString _ ->
9618            pr "  VALUE rv = rb_str_new2 (r);\n";
9619            pr "  free (r);\n";
9620            pr "  return rv;\n";
9621        | RStringList _ ->
9622            pr "  int i, len = 0;\n";
9623            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9624            pr "  VALUE rv = rb_ary_new2 (len);\n";
9625            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9626            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9627            pr "    free (r[i]);\n";
9628            pr "  }\n";
9629            pr "  free (r);\n";
9630            pr "  return rv;\n"
9631        | RStruct (_, typ) ->
9632            let cols = cols_of_struct typ in
9633            generate_ruby_struct_code typ cols
9634        | RStructList (_, typ) ->
9635            let cols = cols_of_struct typ in
9636            generate_ruby_struct_list_code typ cols
9637        | RHashtable _ ->
9638            pr "  VALUE rv = rb_hash_new ();\n";
9639            pr "  int i;\n";
9640            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9641            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9642            pr "    free (r[i]);\n";
9643            pr "    free (r[i+1]);\n";
9644            pr "  }\n";
9645            pr "  free (r);\n";
9646            pr "  return rv;\n"
9647        | RBufferOut _ ->
9648            pr "  VALUE rv = rb_str_new (r, size);\n";
9649            pr "  free (r);\n";
9650            pr "  return rv;\n";
9651       );
9652
9653       pr "}\n";
9654       pr "\n"
9655   ) all_functions;
9656
9657   pr "\
9658 /* Initialize the module. */
9659 void Init__guestfs ()
9660 {
9661   m_guestfs = rb_define_module (\"Guestfs\");
9662   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9663   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9664
9665   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9666   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9667
9668 ";
9669   (* Define the rest of the methods. *)
9670   List.iter (
9671     fun (name, style, _, _, _, _, _) ->
9672       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9673       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9674   ) all_functions;
9675
9676   pr "}\n"
9677
9678 (* Ruby code to return a struct. *)
9679 and generate_ruby_struct_code typ cols =
9680   pr "  VALUE rv = rb_hash_new ();\n";
9681   List.iter (
9682     function
9683     | name, FString ->
9684         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9685     | name, FBuffer ->
9686         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9687     | name, FUUID ->
9688         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9689     | name, (FBytes|FUInt64) ->
9690         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9691     | name, FInt64 ->
9692         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9693     | name, FUInt32 ->
9694         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9695     | name, FInt32 ->
9696         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9697     | name, FOptPercent ->
9698         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9699     | name, FChar -> (* XXX wrong? *)
9700         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9701   ) cols;
9702   pr "  guestfs_free_%s (r);\n" typ;
9703   pr "  return rv;\n"
9704
9705 (* Ruby code to return a struct list. *)
9706 and generate_ruby_struct_list_code typ cols =
9707   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9708   pr "  int i;\n";
9709   pr "  for (i = 0; i < r->len; ++i) {\n";
9710   pr "    VALUE hv = rb_hash_new ();\n";
9711   List.iter (
9712     function
9713     | name, FString ->
9714         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9715     | name, FBuffer ->
9716         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
9717     | name, FUUID ->
9718         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9719     | name, (FBytes|FUInt64) ->
9720         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9721     | name, FInt64 ->
9722         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9723     | name, FUInt32 ->
9724         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9725     | name, FInt32 ->
9726         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9727     | name, FOptPercent ->
9728         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9729     | name, FChar -> (* XXX wrong? *)
9730         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9731   ) cols;
9732   pr "    rb_ary_push (rv, hv);\n";
9733   pr "  }\n";
9734   pr "  guestfs_free_%s_list (r);\n" typ;
9735   pr "  return rv;\n"
9736
9737 (* Generate Java bindings GuestFS.java file. *)
9738 and generate_java_java () =
9739   generate_header CStyle LGPLv2plus;
9740
9741   pr "\
9742 package com.redhat.et.libguestfs;
9743
9744 import java.util.HashMap;
9745 import com.redhat.et.libguestfs.LibGuestFSException;
9746 import com.redhat.et.libguestfs.PV;
9747 import com.redhat.et.libguestfs.VG;
9748 import com.redhat.et.libguestfs.LV;
9749 import com.redhat.et.libguestfs.Stat;
9750 import com.redhat.et.libguestfs.StatVFS;
9751 import com.redhat.et.libguestfs.IntBool;
9752 import com.redhat.et.libguestfs.Dirent;
9753
9754 /**
9755  * The GuestFS object is a libguestfs handle.
9756  *
9757  * @author rjones
9758  */
9759 public class GuestFS {
9760   // Load the native code.
9761   static {
9762     System.loadLibrary (\"guestfs_jni\");
9763   }
9764
9765   /**
9766    * The native guestfs_h pointer.
9767    */
9768   long g;
9769
9770   /**
9771    * Create a libguestfs handle.
9772    *
9773    * @throws LibGuestFSException
9774    */
9775   public GuestFS () throws LibGuestFSException
9776   {
9777     g = _create ();
9778   }
9779   private native long _create () throws LibGuestFSException;
9780
9781   /**
9782    * Close a libguestfs handle.
9783    *
9784    * You can also leave handles to be collected by the garbage
9785    * collector, but this method ensures that the resources used
9786    * by the handle are freed up immediately.  If you call any
9787    * other methods after closing the handle, you will get an
9788    * exception.
9789    *
9790    * @throws LibGuestFSException
9791    */
9792   public void close () throws LibGuestFSException
9793   {
9794     if (g != 0)
9795       _close (g);
9796     g = 0;
9797   }
9798   private native void _close (long g) throws LibGuestFSException;
9799
9800   public void finalize () throws LibGuestFSException
9801   {
9802     close ();
9803   }
9804
9805 ";
9806
9807   List.iter (
9808     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9809       if not (List.mem NotInDocs flags); then (
9810         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9811         let doc =
9812           if List.mem ProtocolLimitWarning flags then
9813             doc ^ "\n\n" ^ protocol_limit_warning
9814           else doc in
9815         let doc =
9816           if List.mem DangerWillRobinson flags then
9817             doc ^ "\n\n" ^ danger_will_robinson
9818           else doc in
9819         let doc =
9820           match deprecation_notice flags with
9821           | None -> doc
9822           | Some txt -> doc ^ "\n\n" ^ txt in
9823         let doc = pod2text ~width:60 name doc in
9824         let doc = List.map (            (* RHBZ#501883 *)
9825           function
9826           | "" -> "<p>"
9827           | nonempty -> nonempty
9828         ) doc in
9829         let doc = String.concat "\n   * " doc in
9830
9831         pr "  /**\n";
9832         pr "   * %s\n" shortdesc;
9833         pr "   * <p>\n";
9834         pr "   * %s\n" doc;
9835         pr "   * @throws LibGuestFSException\n";
9836         pr "   */\n";
9837         pr "  ";
9838       );
9839       generate_java_prototype ~public:true ~semicolon:false name style;
9840       pr "\n";
9841       pr "  {\n";
9842       pr "    if (g == 0)\n";
9843       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9844         name;
9845       pr "    ";
9846       if fst style <> RErr then pr "return ";
9847       pr "_%s " name;
9848       generate_java_call_args ~handle:"g" (snd style);
9849       pr ";\n";
9850       pr "  }\n";
9851       pr "  ";
9852       generate_java_prototype ~privat:true ~native:true name style;
9853       pr "\n";
9854       pr "\n";
9855   ) all_functions;
9856
9857   pr "}\n"
9858
9859 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9860 and generate_java_call_args ~handle args =
9861   pr "(%s" handle;
9862   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9863   pr ")"
9864
9865 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9866     ?(semicolon=true) name style =
9867   if privat then pr "private ";
9868   if public then pr "public ";
9869   if native then pr "native ";
9870
9871   (* return type *)
9872   (match fst style with
9873    | RErr -> pr "void ";
9874    | RInt _ -> pr "int ";
9875    | RInt64 _ -> pr "long ";
9876    | RBool _ -> pr "boolean ";
9877    | RConstString _ | RConstOptString _ | RString _
9878    | RBufferOut _ -> pr "String ";
9879    | RStringList _ -> pr "String[] ";
9880    | RStruct (_, typ) ->
9881        let name = java_name_of_struct typ in
9882        pr "%s " name;
9883    | RStructList (_, typ) ->
9884        let name = java_name_of_struct typ in
9885        pr "%s[] " name;
9886    | RHashtable _ -> pr "HashMap<String,String> ";
9887   );
9888
9889   if native then pr "_%s " name else pr "%s " name;
9890   pr "(";
9891   let needs_comma = ref false in
9892   if native then (
9893     pr "long g";
9894     needs_comma := true
9895   );
9896
9897   (* args *)
9898   List.iter (
9899     fun arg ->
9900       if !needs_comma then pr ", ";
9901       needs_comma := true;
9902
9903       match arg with
9904       | Pathname n
9905       | Device n | Dev_or_Path n
9906       | String n
9907       | OptString n
9908       | FileIn n
9909       | FileOut n ->
9910           pr "String %s" n
9911       | StringList n | DeviceList n ->
9912           pr "String[] %s" n
9913       | Bool n ->
9914           pr "boolean %s" n
9915       | Int n ->
9916           pr "int %s" n
9917       | Int64 n ->
9918           pr "long %s" n
9919   ) (snd style);
9920
9921   pr ")\n";
9922   pr "    throws LibGuestFSException";
9923   if semicolon then pr ";"
9924
9925 and generate_java_struct jtyp cols () =
9926   generate_header CStyle LGPLv2plus;
9927
9928   pr "\
9929 package com.redhat.et.libguestfs;
9930
9931 /**
9932  * Libguestfs %s structure.
9933  *
9934  * @author rjones
9935  * @see GuestFS
9936  */
9937 public class %s {
9938 " jtyp jtyp;
9939
9940   List.iter (
9941     function
9942     | name, FString
9943     | name, FUUID
9944     | name, FBuffer -> pr "  public String %s;\n" name
9945     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9946     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9947     | name, FChar -> pr "  public char %s;\n" name
9948     | name, FOptPercent ->
9949         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9950         pr "  public float %s;\n" name
9951   ) cols;
9952
9953   pr "}\n"
9954
9955 and generate_java_c () =
9956   generate_header CStyle LGPLv2plus;
9957
9958   pr "\
9959 #include <stdio.h>
9960 #include <stdlib.h>
9961 #include <string.h>
9962
9963 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9964 #include \"guestfs.h\"
9965
9966 /* Note that this function returns.  The exception is not thrown
9967  * until after the wrapper function returns.
9968  */
9969 static void
9970 throw_exception (JNIEnv *env, const char *msg)
9971 {
9972   jclass cl;
9973   cl = (*env)->FindClass (env,
9974                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9975   (*env)->ThrowNew (env, cl, msg);
9976 }
9977
9978 JNIEXPORT jlong JNICALL
9979 Java_com_redhat_et_libguestfs_GuestFS__1create
9980   (JNIEnv *env, jobject obj)
9981 {
9982   guestfs_h *g;
9983
9984   g = guestfs_create ();
9985   if (g == NULL) {
9986     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9987     return 0;
9988   }
9989   guestfs_set_error_handler (g, NULL, NULL);
9990   return (jlong) (long) g;
9991 }
9992
9993 JNIEXPORT void JNICALL
9994 Java_com_redhat_et_libguestfs_GuestFS__1close
9995   (JNIEnv *env, jobject obj, jlong jg)
9996 {
9997   guestfs_h *g = (guestfs_h *) (long) jg;
9998   guestfs_close (g);
9999 }
10000
10001 ";
10002
10003   List.iter (
10004     fun (name, style, _, _, _, _, _) ->
10005       pr "JNIEXPORT ";
10006       (match fst style with
10007        | RErr -> pr "void ";
10008        | RInt _ -> pr "jint ";
10009        | RInt64 _ -> pr "jlong ";
10010        | RBool _ -> pr "jboolean ";
10011        | RConstString _ | RConstOptString _ | RString _
10012        | RBufferOut _ -> pr "jstring ";
10013        | RStruct _ | RHashtable _ ->
10014            pr "jobject ";
10015        | RStringList _ | RStructList _ ->
10016            pr "jobjectArray ";
10017       );
10018       pr "JNICALL\n";
10019       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10020       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10021       pr "\n";
10022       pr "  (JNIEnv *env, jobject obj, jlong jg";
10023       List.iter (
10024         function
10025         | Pathname n
10026         | Device n | Dev_or_Path n
10027         | String n
10028         | OptString n
10029         | FileIn n
10030         | FileOut n ->
10031             pr ", jstring j%s" n
10032         | StringList n | DeviceList n ->
10033             pr ", jobjectArray j%s" n
10034         | Bool n ->
10035             pr ", jboolean j%s" n
10036         | Int n ->
10037             pr ", jint j%s" n
10038         | Int64 n ->
10039             pr ", jlong j%s" n
10040       ) (snd style);
10041       pr ")\n";
10042       pr "{\n";
10043       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10044       let error_code, no_ret =
10045         match fst style with
10046         | RErr -> pr "  int r;\n"; "-1", ""
10047         | RBool _
10048         | RInt _ -> pr "  int r;\n"; "-1", "0"
10049         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10050         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10051         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10052         | RString _ ->
10053             pr "  jstring jr;\n";
10054             pr "  char *r;\n"; "NULL", "NULL"
10055         | RStringList _ ->
10056             pr "  jobjectArray jr;\n";
10057             pr "  int r_len;\n";
10058             pr "  jclass cl;\n";
10059             pr "  jstring jstr;\n";
10060             pr "  char **r;\n"; "NULL", "NULL"
10061         | RStruct (_, typ) ->
10062             pr "  jobject jr;\n";
10063             pr "  jclass cl;\n";
10064             pr "  jfieldID fl;\n";
10065             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10066         | RStructList (_, typ) ->
10067             pr "  jobjectArray jr;\n";
10068             pr "  jclass cl;\n";
10069             pr "  jfieldID fl;\n";
10070             pr "  jobject jfl;\n";
10071             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10072         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10073         | RBufferOut _ ->
10074             pr "  jstring jr;\n";
10075             pr "  char *r;\n";
10076             pr "  size_t size;\n";
10077             "NULL", "NULL" in
10078       List.iter (
10079         function
10080         | Pathname n
10081         | Device n | Dev_or_Path n
10082         | String n
10083         | OptString n
10084         | FileIn n
10085         | FileOut n ->
10086             pr "  const char *%s;\n" n
10087         | StringList n | DeviceList n ->
10088             pr "  int %s_len;\n" n;
10089             pr "  const char **%s;\n" n
10090         | Bool n
10091         | Int n ->
10092             pr "  int %s;\n" n
10093         | Int64 n ->
10094             pr "  int64_t %s;\n" n
10095       ) (snd style);
10096
10097       let needs_i =
10098         (match fst style with
10099          | RStringList _ | RStructList _ -> true
10100          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10101          | RConstOptString _
10102          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10103           List.exists (function
10104                        | StringList _ -> true
10105                        | DeviceList _ -> true
10106                        | _ -> false) (snd style) in
10107       if needs_i then
10108         pr "  int i;\n";
10109
10110       pr "\n";
10111
10112       (* Get the parameters. *)
10113       List.iter (
10114         function
10115         | Pathname n
10116         | Device n | Dev_or_Path n
10117         | String n
10118         | FileIn n
10119         | FileOut n ->
10120             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10121         | OptString n ->
10122             (* This is completely undocumented, but Java null becomes
10123              * a NULL parameter.
10124              *)
10125             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10126         | StringList n | DeviceList n ->
10127             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10128             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10129             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10130             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10131               n;
10132             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10133             pr "  }\n";
10134             pr "  %s[%s_len] = NULL;\n" n n;
10135         | Bool n
10136         | Int n
10137         | Int64 n ->
10138             pr "  %s = j%s;\n" n n
10139       ) (snd style);
10140
10141       (* Make the call. *)
10142       pr "  r = guestfs_%s " name;
10143       generate_c_call_args ~handle:"g" style;
10144       pr ";\n";
10145
10146       (* Release the parameters. *)
10147       List.iter (
10148         function
10149         | Pathname n
10150         | Device n | Dev_or_Path n
10151         | String n
10152         | FileIn n
10153         | FileOut n ->
10154             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10155         | OptString n ->
10156             pr "  if (j%s)\n" n;
10157             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10158         | StringList n | DeviceList n ->
10159             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10160             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10161               n;
10162             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10163             pr "  }\n";
10164             pr "  free (%s);\n" n
10165         | Bool n
10166         | Int n
10167         | Int64 n -> ()
10168       ) (snd style);
10169
10170       (* Check for errors. *)
10171       pr "  if (r == %s) {\n" error_code;
10172       pr "    throw_exception (env, guestfs_last_error (g));\n";
10173       pr "    return %s;\n" no_ret;
10174       pr "  }\n";
10175
10176       (* Return value. *)
10177       (match fst style with
10178        | RErr -> ()
10179        | RInt _ -> pr "  return (jint) r;\n"
10180        | RBool _ -> pr "  return (jboolean) r;\n"
10181        | RInt64 _ -> pr "  return (jlong) r;\n"
10182        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10183        | RConstOptString _ ->
10184            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10185        | RString _ ->
10186            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10187            pr "  free (r);\n";
10188            pr "  return jr;\n"
10189        | RStringList _ ->
10190            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10191            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10192            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10193            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10194            pr "  for (i = 0; i < r_len; ++i) {\n";
10195            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10196            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10197            pr "    free (r[i]);\n";
10198            pr "  }\n";
10199            pr "  free (r);\n";
10200            pr "  return jr;\n"
10201        | RStruct (_, typ) ->
10202            let jtyp = java_name_of_struct typ in
10203            let cols = cols_of_struct typ in
10204            generate_java_struct_return typ jtyp cols
10205        | RStructList (_, typ) ->
10206            let jtyp = java_name_of_struct typ in
10207            let cols = cols_of_struct typ in
10208            generate_java_struct_list_return typ jtyp cols
10209        | RHashtable _ ->
10210            (* XXX *)
10211            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10212            pr "  return NULL;\n"
10213        | RBufferOut _ ->
10214            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10215            pr "  free (r);\n";
10216            pr "  return jr;\n"
10217       );
10218
10219       pr "}\n";
10220       pr "\n"
10221   ) all_functions
10222
10223 and generate_java_struct_return typ jtyp cols =
10224   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10225   pr "  jr = (*env)->AllocObject (env, cl);\n";
10226   List.iter (
10227     function
10228     | name, FString ->
10229         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10230         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10231     | name, FUUID ->
10232         pr "  {\n";
10233         pr "    char s[33];\n";
10234         pr "    memcpy (s, r->%s, 32);\n" name;
10235         pr "    s[32] = 0;\n";
10236         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10237         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10238         pr "  }\n";
10239     | name, FBuffer ->
10240         pr "  {\n";
10241         pr "    int len = r->%s_len;\n" name;
10242         pr "    char s[len+1];\n";
10243         pr "    memcpy (s, r->%s, len);\n" name;
10244         pr "    s[len] = 0;\n";
10245         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10246         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10247         pr "  }\n";
10248     | name, (FBytes|FUInt64|FInt64) ->
10249         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10250         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10251     | name, (FUInt32|FInt32) ->
10252         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10253         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10254     | name, FOptPercent ->
10255         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10256         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10257     | name, FChar ->
10258         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10259         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10260   ) cols;
10261   pr "  free (r);\n";
10262   pr "  return jr;\n"
10263
10264 and generate_java_struct_list_return typ jtyp cols =
10265   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10266   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10267   pr "  for (i = 0; i < r->len; ++i) {\n";
10268   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10269   List.iter (
10270     function
10271     | name, FString ->
10272         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10273         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10274     | name, FUUID ->
10275         pr "    {\n";
10276         pr "      char s[33];\n";
10277         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10278         pr "      s[32] = 0;\n";
10279         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10280         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10281         pr "    }\n";
10282     | name, FBuffer ->
10283         pr "    {\n";
10284         pr "      int len = r->val[i].%s_len;\n" name;
10285         pr "      char s[len+1];\n";
10286         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10287         pr "      s[len] = 0;\n";
10288         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10289         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10290         pr "    }\n";
10291     | name, (FBytes|FUInt64|FInt64) ->
10292         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10293         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10294     | name, (FUInt32|FInt32) ->
10295         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10296         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10297     | name, FOptPercent ->
10298         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10299         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10300     | name, FChar ->
10301         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10302         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10303   ) cols;
10304   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10305   pr "  }\n";
10306   pr "  guestfs_free_%s_list (r);\n" typ;
10307   pr "  return jr;\n"
10308
10309 and generate_java_makefile_inc () =
10310   generate_header HashStyle GPLv2plus;
10311
10312   pr "java_built_sources = \\\n";
10313   List.iter (
10314     fun (typ, jtyp) ->
10315         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10316   ) java_structs;
10317   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10318
10319 and generate_haskell_hs () =
10320   generate_header HaskellStyle LGPLv2plus;
10321
10322   (* XXX We only know how to generate partial FFI for Haskell
10323    * at the moment.  Please help out!
10324    *)
10325   let can_generate style =
10326     match style with
10327     | RErr, _
10328     | RInt _, _
10329     | RInt64 _, _ -> true
10330     | RBool _, _
10331     | RConstString _, _
10332     | RConstOptString _, _
10333     | RString _, _
10334     | RStringList _, _
10335     | RStruct _, _
10336     | RStructList _, _
10337     | RHashtable _, _
10338     | RBufferOut _, _ -> false in
10339
10340   pr "\
10341 {-# INCLUDE <guestfs.h> #-}
10342 {-# LANGUAGE ForeignFunctionInterface #-}
10343
10344 module Guestfs (
10345   create";
10346
10347   (* List out the names of the actions we want to export. *)
10348   List.iter (
10349     fun (name, style, _, _, _, _, _) ->
10350       if can_generate style then pr ",\n  %s" name
10351   ) all_functions;
10352
10353   pr "
10354   ) where
10355
10356 -- Unfortunately some symbols duplicate ones already present
10357 -- in Prelude.  We don't know which, so we hard-code a list
10358 -- here.
10359 import Prelude hiding (truncate)
10360
10361 import Foreign
10362 import Foreign.C
10363 import Foreign.C.Types
10364 import IO
10365 import Control.Exception
10366 import Data.Typeable
10367
10368 data GuestfsS = GuestfsS            -- represents the opaque C struct
10369 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10370 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10371
10372 -- XXX define properly later XXX
10373 data PV = PV
10374 data VG = VG
10375 data LV = LV
10376 data IntBool = IntBool
10377 data Stat = Stat
10378 data StatVFS = StatVFS
10379 data Hashtable = Hashtable
10380
10381 foreign import ccall unsafe \"guestfs_create\" c_create
10382   :: IO GuestfsP
10383 foreign import ccall unsafe \"&guestfs_close\" c_close
10384   :: FunPtr (GuestfsP -> IO ())
10385 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10386   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10387
10388 create :: IO GuestfsH
10389 create = do
10390   p <- c_create
10391   c_set_error_handler p nullPtr nullPtr
10392   h <- newForeignPtr c_close p
10393   return h
10394
10395 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10396   :: GuestfsP -> IO CString
10397
10398 -- last_error :: GuestfsH -> IO (Maybe String)
10399 -- last_error h = do
10400 --   str <- withForeignPtr h (\\p -> c_last_error p)
10401 --   maybePeek peekCString str
10402
10403 last_error :: GuestfsH -> IO (String)
10404 last_error h = do
10405   str <- withForeignPtr h (\\p -> c_last_error p)
10406   if (str == nullPtr)
10407     then return \"no error\"
10408     else peekCString str
10409
10410 ";
10411
10412   (* Generate wrappers for each foreign function. *)
10413   List.iter (
10414     fun (name, style, _, _, _, _, _) ->
10415       if can_generate style then (
10416         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10417         pr "  :: ";
10418         generate_haskell_prototype ~handle:"GuestfsP" style;
10419         pr "\n";
10420         pr "\n";
10421         pr "%s :: " name;
10422         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10423         pr "\n";
10424         pr "%s %s = do\n" name
10425           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10426         pr "  r <- ";
10427         (* Convert pointer arguments using with* functions. *)
10428         List.iter (
10429           function
10430           | FileIn n
10431           | FileOut n
10432           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10433           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10434           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10435           | Bool _ | Int _ | Int64 _ -> ()
10436         ) (snd style);
10437         (* Convert integer arguments. *)
10438         let args =
10439           List.map (
10440             function
10441             | Bool n -> sprintf "(fromBool %s)" n
10442             | Int n -> sprintf "(fromIntegral %s)" n
10443             | Int64 n -> sprintf "(fromIntegral %s)" n
10444             | FileIn n | FileOut n
10445             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10446           ) (snd style) in
10447         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10448           (String.concat " " ("p" :: args));
10449         (match fst style with
10450          | RErr | RInt _ | RInt64 _ | RBool _ ->
10451              pr "  if (r == -1)\n";
10452              pr "    then do\n";
10453              pr "      err <- last_error h\n";
10454              pr "      fail err\n";
10455          | RConstString _ | RConstOptString _ | RString _
10456          | RStringList _ | RStruct _
10457          | RStructList _ | RHashtable _ | RBufferOut _ ->
10458              pr "  if (r == nullPtr)\n";
10459              pr "    then do\n";
10460              pr "      err <- last_error h\n";
10461              pr "      fail err\n";
10462         );
10463         (match fst style with
10464          | RErr ->
10465              pr "    else return ()\n"
10466          | RInt _ ->
10467              pr "    else return (fromIntegral r)\n"
10468          | RInt64 _ ->
10469              pr "    else return (fromIntegral r)\n"
10470          | RBool _ ->
10471              pr "    else return (toBool r)\n"
10472          | RConstString _
10473          | RConstOptString _
10474          | RString _
10475          | RStringList _
10476          | RStruct _
10477          | RStructList _
10478          | RHashtable _
10479          | RBufferOut _ ->
10480              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10481         );
10482         pr "\n";
10483       )
10484   ) all_functions
10485
10486 and generate_haskell_prototype ~handle ?(hs = false) style =
10487   pr "%s -> " handle;
10488   let string = if hs then "String" else "CString" in
10489   let int = if hs then "Int" else "CInt" in
10490   let bool = if hs then "Bool" else "CInt" in
10491   let int64 = if hs then "Integer" else "Int64" in
10492   List.iter (
10493     fun arg ->
10494       (match arg with
10495        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10496        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10497        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10498        | Bool _ -> pr "%s" bool
10499        | Int _ -> pr "%s" int
10500        | Int64 _ -> pr "%s" int
10501        | FileIn _ -> pr "%s" string
10502        | FileOut _ -> pr "%s" string
10503       );
10504       pr " -> ";
10505   ) (snd style);
10506   pr "IO (";
10507   (match fst style with
10508    | RErr -> if not hs then pr "CInt"
10509    | RInt _ -> pr "%s" int
10510    | RInt64 _ -> pr "%s" int64
10511    | RBool _ -> pr "%s" bool
10512    | RConstString _ -> pr "%s" string
10513    | RConstOptString _ -> pr "Maybe %s" string
10514    | RString _ -> pr "%s" string
10515    | RStringList _ -> pr "[%s]" string
10516    | RStruct (_, typ) ->
10517        let name = java_name_of_struct typ in
10518        pr "%s" name
10519    | RStructList (_, typ) ->
10520        let name = java_name_of_struct typ in
10521        pr "[%s]" name
10522    | RHashtable _ -> pr "Hashtable"
10523    | RBufferOut _ -> pr "%s" string
10524   );
10525   pr ")"
10526
10527 and generate_csharp () =
10528   generate_header CPlusPlusStyle LGPLv2plus;
10529
10530   (* XXX Make this configurable by the C# assembly users. *)
10531   let library = "libguestfs.so.0" in
10532
10533   pr "\
10534 // These C# bindings are highly experimental at present.
10535 //
10536 // Firstly they only work on Linux (ie. Mono).  In order to get them
10537 // to work on Windows (ie. .Net) you would need to port the library
10538 // itself to Windows first.
10539 //
10540 // The second issue is that some calls are known to be incorrect and
10541 // can cause Mono to segfault.  Particularly: calls which pass or
10542 // return string[], or return any structure value.  This is because
10543 // we haven't worked out the correct way to do this from C#.
10544 //
10545 // The third issue is that when compiling you get a lot of warnings.
10546 // We are not sure whether the warnings are important or not.
10547 //
10548 // Fourthly we do not routinely build or test these bindings as part
10549 // of the make && make check cycle, which means that regressions might
10550 // go unnoticed.
10551 //
10552 // Suggestions and patches are welcome.
10553
10554 // To compile:
10555 //
10556 // gmcs Libguestfs.cs
10557 // mono Libguestfs.exe
10558 //
10559 // (You'll probably want to add a Test class / static main function
10560 // otherwise this won't do anything useful).
10561
10562 using System;
10563 using System.IO;
10564 using System.Runtime.InteropServices;
10565 using System.Runtime.Serialization;
10566 using System.Collections;
10567
10568 namespace Guestfs
10569 {
10570   class Error : System.ApplicationException
10571   {
10572     public Error (string message) : base (message) {}
10573     protected Error (SerializationInfo info, StreamingContext context) {}
10574   }
10575
10576   class Guestfs
10577   {
10578     IntPtr _handle;
10579
10580     [DllImport (\"%s\")]
10581     static extern IntPtr guestfs_create ();
10582
10583     public Guestfs ()
10584     {
10585       _handle = guestfs_create ();
10586       if (_handle == IntPtr.Zero)
10587         throw new Error (\"could not create guestfs handle\");
10588     }
10589
10590     [DllImport (\"%s\")]
10591     static extern void guestfs_close (IntPtr h);
10592
10593     ~Guestfs ()
10594     {
10595       guestfs_close (_handle);
10596     }
10597
10598     [DllImport (\"%s\")]
10599     static extern string guestfs_last_error (IntPtr h);
10600
10601 " library library library;
10602
10603   (* Generate C# structure bindings.  We prefix struct names with
10604    * underscore because C# cannot have conflicting struct names and
10605    * method names (eg. "class stat" and "stat").
10606    *)
10607   List.iter (
10608     fun (typ, cols) ->
10609       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10610       pr "    public class _%s {\n" typ;
10611       List.iter (
10612         function
10613         | name, FChar -> pr "      char %s;\n" name
10614         | name, FString -> pr "      string %s;\n" name
10615         | name, FBuffer ->
10616             pr "      uint %s_len;\n" name;
10617             pr "      string %s;\n" name
10618         | name, FUUID ->
10619             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10620             pr "      string %s;\n" name
10621         | name, FUInt32 -> pr "      uint %s;\n" name
10622         | name, FInt32 -> pr "      int %s;\n" name
10623         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10624         | name, FInt64 -> pr "      long %s;\n" name
10625         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10626       ) cols;
10627       pr "    }\n";
10628       pr "\n"
10629   ) structs;
10630
10631   (* Generate C# function bindings. *)
10632   List.iter (
10633     fun (name, style, _, _, _, shortdesc, _) ->
10634       let rec csharp_return_type () =
10635         match fst style with
10636         | RErr -> "void"
10637         | RBool n -> "bool"
10638         | RInt n -> "int"
10639         | RInt64 n -> "long"
10640         | RConstString n
10641         | RConstOptString n
10642         | RString n
10643         | RBufferOut n -> "string"
10644         | RStruct (_,n) -> "_" ^ n
10645         | RHashtable n -> "Hashtable"
10646         | RStringList n -> "string[]"
10647         | RStructList (_,n) -> sprintf "_%s[]" n
10648
10649       and c_return_type () =
10650         match fst style with
10651         | RErr
10652         | RBool _
10653         | RInt _ -> "int"
10654         | RInt64 _ -> "long"
10655         | RConstString _
10656         | RConstOptString _
10657         | RString _
10658         | RBufferOut _ -> "string"
10659         | RStruct (_,n) -> "_" ^ n
10660         | RHashtable _
10661         | RStringList _ -> "string[]"
10662         | RStructList (_,n) -> sprintf "_%s[]" n
10663
10664       and c_error_comparison () =
10665         match fst style with
10666         | RErr
10667         | RBool _
10668         | RInt _
10669         | RInt64 _ -> "== -1"
10670         | RConstString _
10671         | RConstOptString _
10672         | RString _
10673         | RBufferOut _
10674         | RStruct (_,_)
10675         | RHashtable _
10676         | RStringList _
10677         | RStructList (_,_) -> "== null"
10678
10679       and generate_extern_prototype () =
10680         pr "    static extern %s guestfs_%s (IntPtr h"
10681           (c_return_type ()) name;
10682         List.iter (
10683           function
10684           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10685           | FileIn n | FileOut n ->
10686               pr ", [In] string %s" n
10687           | StringList n | DeviceList n ->
10688               pr ", [In] string[] %s" n
10689           | Bool n ->
10690               pr ", bool %s" n
10691           | Int n ->
10692               pr ", int %s" n
10693           | Int64 n ->
10694               pr ", long %s" n
10695         ) (snd style);
10696         pr ");\n"
10697
10698       and generate_public_prototype () =
10699         pr "    public %s %s (" (csharp_return_type ()) name;
10700         let comma = ref false in
10701         let next () =
10702           if !comma then pr ", ";
10703           comma := true
10704         in
10705         List.iter (
10706           function
10707           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10708           | FileIn n | FileOut n ->
10709               next (); pr "string %s" n
10710           | StringList n | DeviceList n ->
10711               next (); pr "string[] %s" n
10712           | Bool n ->
10713               next (); pr "bool %s" n
10714           | Int n ->
10715               next (); pr "int %s" n
10716           | Int64 n ->
10717               next (); pr "long %s" n
10718         ) (snd style);
10719         pr ")\n"
10720
10721       and generate_call () =
10722         pr "guestfs_%s (_handle" name;
10723         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10724         pr ");\n";
10725       in
10726
10727       pr "    [DllImport (\"%s\")]\n" library;
10728       generate_extern_prototype ();
10729       pr "\n";
10730       pr "    /// <summary>\n";
10731       pr "    /// %s\n" shortdesc;
10732       pr "    /// </summary>\n";
10733       generate_public_prototype ();
10734       pr "    {\n";
10735       pr "      %s r;\n" (c_return_type ());
10736       pr "      r = ";
10737       generate_call ();
10738       pr "      if (r %s)\n" (c_error_comparison ());
10739       pr "        throw new Error (guestfs_last_error (_handle));\n";
10740       (match fst style with
10741        | RErr -> ()
10742        | RBool _ ->
10743            pr "      return r != 0 ? true : false;\n"
10744        | RHashtable _ ->
10745            pr "      Hashtable rr = new Hashtable ();\n";
10746            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10747            pr "        rr.Add (r[i], r[i+1]);\n";
10748            pr "      return rr;\n"
10749        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10750        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10751        | RStructList _ ->
10752            pr "      return r;\n"
10753       );
10754       pr "    }\n";
10755       pr "\n";
10756   ) all_functions_sorted;
10757
10758   pr "  }
10759 }
10760 "
10761
10762 and generate_bindtests () =
10763   generate_header CStyle LGPLv2plus;
10764
10765   pr "\
10766 #include <stdio.h>
10767 #include <stdlib.h>
10768 #include <inttypes.h>
10769 #include <string.h>
10770
10771 #include \"guestfs.h\"
10772 #include \"guestfs-internal.h\"
10773 #include \"guestfs-internal-actions.h\"
10774 #include \"guestfs_protocol.h\"
10775
10776 #define error guestfs_error
10777 #define safe_calloc guestfs_safe_calloc
10778 #define safe_malloc guestfs_safe_malloc
10779
10780 static void
10781 print_strings (char *const *argv)
10782 {
10783   int argc;
10784
10785   printf (\"[\");
10786   for (argc = 0; argv[argc] != NULL; ++argc) {
10787     if (argc > 0) printf (\", \");
10788     printf (\"\\\"%%s\\\"\", argv[argc]);
10789   }
10790   printf (\"]\\n\");
10791 }
10792
10793 /* The test0 function prints its parameters to stdout. */
10794 ";
10795
10796   let test0, tests =
10797     match test_functions with
10798     | [] -> assert false
10799     | test0 :: tests -> test0, tests in
10800
10801   let () =
10802     let (name, style, _, _, _, _, _) = test0 in
10803     generate_prototype ~extern:false ~semicolon:false ~newline:true
10804       ~handle:"g" ~prefix:"guestfs__" name style;
10805     pr "{\n";
10806     List.iter (
10807       function
10808       | Pathname n
10809       | Device n | Dev_or_Path n
10810       | String n
10811       | FileIn n
10812       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10813       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10814       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10815       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10816       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10817       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10818     ) (snd style);
10819     pr "  /* Java changes stdout line buffering so we need this: */\n";
10820     pr "  fflush (stdout);\n";
10821     pr "  return 0;\n";
10822     pr "}\n";
10823     pr "\n" in
10824
10825   List.iter (
10826     fun (name, style, _, _, _, _, _) ->
10827       if String.sub name (String.length name - 3) 3 <> "err" then (
10828         pr "/* Test normal return. */\n";
10829         generate_prototype ~extern:false ~semicolon:false ~newline:true
10830           ~handle:"g" ~prefix:"guestfs__" name style;
10831         pr "{\n";
10832         (match fst style with
10833          | RErr ->
10834              pr "  return 0;\n"
10835          | RInt _ ->
10836              pr "  int r;\n";
10837              pr "  sscanf (val, \"%%d\", &r);\n";
10838              pr "  return r;\n"
10839          | RInt64 _ ->
10840              pr "  int64_t r;\n";
10841              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10842              pr "  return r;\n"
10843          | RBool _ ->
10844              pr "  return STREQ (val, \"true\");\n"
10845          | RConstString _
10846          | RConstOptString _ ->
10847              (* Can't return the input string here.  Return a static
10848               * string so we ensure we get a segfault if the caller
10849               * tries to free it.
10850               *)
10851              pr "  return \"static string\";\n"
10852          | RString _ ->
10853              pr "  return strdup (val);\n"
10854          | RStringList _ ->
10855              pr "  char **strs;\n";
10856              pr "  int n, i;\n";
10857              pr "  sscanf (val, \"%%d\", &n);\n";
10858              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10859              pr "  for (i = 0; i < n; ++i) {\n";
10860              pr "    strs[i] = safe_malloc (g, 16);\n";
10861              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10862              pr "  }\n";
10863              pr "  strs[n] = NULL;\n";
10864              pr "  return strs;\n"
10865          | RStruct (_, typ) ->
10866              pr "  struct guestfs_%s *r;\n" typ;
10867              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10868              pr "  return r;\n"
10869          | RStructList (_, typ) ->
10870              pr "  struct guestfs_%s_list *r;\n" typ;
10871              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10872              pr "  sscanf (val, \"%%d\", &r->len);\n";
10873              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10874              pr "  return r;\n"
10875          | RHashtable _ ->
10876              pr "  char **strs;\n";
10877              pr "  int n, i;\n";
10878              pr "  sscanf (val, \"%%d\", &n);\n";
10879              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10880              pr "  for (i = 0; i < n; ++i) {\n";
10881              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10882              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10883              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10884              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10885              pr "  }\n";
10886              pr "  strs[n*2] = NULL;\n";
10887              pr "  return strs;\n"
10888          | RBufferOut _ ->
10889              pr "  return strdup (val);\n"
10890         );
10891         pr "}\n";
10892         pr "\n"
10893       ) else (
10894         pr "/* Test error return. */\n";
10895         generate_prototype ~extern:false ~semicolon:false ~newline:true
10896           ~handle:"g" ~prefix:"guestfs__" name style;
10897         pr "{\n";
10898         pr "  error (g, \"error\");\n";
10899         (match fst style with
10900          | RErr | RInt _ | RInt64 _ | RBool _ ->
10901              pr "  return -1;\n"
10902          | RConstString _ | RConstOptString _
10903          | RString _ | RStringList _ | RStruct _
10904          | RStructList _
10905          | RHashtable _
10906          | RBufferOut _ ->
10907              pr "  return NULL;\n"
10908         );
10909         pr "}\n";
10910         pr "\n"
10911       )
10912   ) tests
10913
10914 and generate_ocaml_bindtests () =
10915   generate_header OCamlStyle GPLv2plus;
10916
10917   pr "\
10918 let () =
10919   let g = Guestfs.create () in
10920 ";
10921
10922   let mkargs args =
10923     String.concat " " (
10924       List.map (
10925         function
10926         | CallString s -> "\"" ^ s ^ "\""
10927         | CallOptString None -> "None"
10928         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10929         | CallStringList xs ->
10930             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10931         | CallInt i when i >= 0 -> string_of_int i
10932         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10933         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10934         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10935         | CallBool b -> string_of_bool b
10936       ) args
10937     )
10938   in
10939
10940   generate_lang_bindtests (
10941     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10942   );
10943
10944   pr "print_endline \"EOF\"\n"
10945
10946 and generate_perl_bindtests () =
10947   pr "#!/usr/bin/perl -w\n";
10948   generate_header HashStyle GPLv2plus;
10949
10950   pr "\
10951 use strict;
10952
10953 use Sys::Guestfs;
10954
10955 my $g = Sys::Guestfs->new ();
10956 ";
10957
10958   let mkargs args =
10959     String.concat ", " (
10960       List.map (
10961         function
10962         | CallString s -> "\"" ^ s ^ "\""
10963         | CallOptString None -> "undef"
10964         | CallOptString (Some s) -> sprintf "\"%s\"" s
10965         | CallStringList xs ->
10966             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10967         | CallInt i -> string_of_int i
10968         | CallInt64 i -> Int64.to_string i
10969         | CallBool b -> if b then "1" else "0"
10970       ) args
10971     )
10972   in
10973
10974   generate_lang_bindtests (
10975     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10976   );
10977
10978   pr "print \"EOF\\n\"\n"
10979
10980 and generate_python_bindtests () =
10981   generate_header HashStyle GPLv2plus;
10982
10983   pr "\
10984 import guestfs
10985
10986 g = guestfs.GuestFS ()
10987 ";
10988
10989   let mkargs args =
10990     String.concat ", " (
10991       List.map (
10992         function
10993         | CallString s -> "\"" ^ s ^ "\""
10994         | CallOptString None -> "None"
10995         | CallOptString (Some s) -> sprintf "\"%s\"" s
10996         | CallStringList xs ->
10997             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10998         | CallInt i -> string_of_int i
10999         | CallInt64 i -> Int64.to_string i
11000         | CallBool b -> if b then "1" else "0"
11001       ) args
11002     )
11003   in
11004
11005   generate_lang_bindtests (
11006     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11007   );
11008
11009   pr "print \"EOF\"\n"
11010
11011 and generate_ruby_bindtests () =
11012   generate_header HashStyle GPLv2plus;
11013
11014   pr "\
11015 require 'guestfs'
11016
11017 g = Guestfs::create()
11018 ";
11019
11020   let mkargs args =
11021     String.concat ", " (
11022       List.map (
11023         function
11024         | CallString s -> "\"" ^ s ^ "\""
11025         | CallOptString None -> "nil"
11026         | CallOptString (Some s) -> sprintf "\"%s\"" s
11027         | CallStringList xs ->
11028             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11029         | CallInt i -> string_of_int i
11030         | CallInt64 i -> Int64.to_string i
11031         | CallBool b -> string_of_bool b
11032       ) args
11033     )
11034   in
11035
11036   generate_lang_bindtests (
11037     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11038   );
11039
11040   pr "print \"EOF\\n\"\n"
11041
11042 and generate_java_bindtests () =
11043   generate_header CStyle GPLv2plus;
11044
11045   pr "\
11046 import com.redhat.et.libguestfs.*;
11047
11048 public class Bindtests {
11049     public static void main (String[] argv)
11050     {
11051         try {
11052             GuestFS g = new GuestFS ();
11053 ";
11054
11055   let mkargs args =
11056     String.concat ", " (
11057       List.map (
11058         function
11059         | CallString s -> "\"" ^ s ^ "\""
11060         | CallOptString None -> "null"
11061         | CallOptString (Some s) -> sprintf "\"%s\"" s
11062         | CallStringList xs ->
11063             "new String[]{" ^
11064               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11065         | CallInt i -> string_of_int i
11066         | CallInt64 i -> Int64.to_string i
11067         | CallBool b -> string_of_bool b
11068       ) args
11069     )
11070   in
11071
11072   generate_lang_bindtests (
11073     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11074   );
11075
11076   pr "
11077             System.out.println (\"EOF\");
11078         }
11079         catch (Exception exn) {
11080             System.err.println (exn);
11081             System.exit (1);
11082         }
11083     }
11084 }
11085 "
11086
11087 and generate_haskell_bindtests () =
11088   generate_header HaskellStyle GPLv2plus;
11089
11090   pr "\
11091 module Bindtests where
11092 import qualified Guestfs
11093
11094 main = do
11095   g <- Guestfs.create
11096 ";
11097
11098   let mkargs args =
11099     String.concat " " (
11100       List.map (
11101         function
11102         | CallString s -> "\"" ^ s ^ "\""
11103         | CallOptString None -> "Nothing"
11104         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11105         | CallStringList xs ->
11106             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11107         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11108         | CallInt i -> string_of_int i
11109         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11110         | CallInt64 i -> Int64.to_string i
11111         | CallBool true -> "True"
11112         | CallBool false -> "False"
11113       ) args
11114     )
11115   in
11116
11117   generate_lang_bindtests (
11118     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11119   );
11120
11121   pr "  putStrLn \"EOF\"\n"
11122
11123 (* Language-independent bindings tests - we do it this way to
11124  * ensure there is parity in testing bindings across all languages.
11125  *)
11126 and generate_lang_bindtests call =
11127   call "test0" [CallString "abc"; CallOptString (Some "def");
11128                 CallStringList []; CallBool false;
11129                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11130   call "test0" [CallString "abc"; CallOptString None;
11131                 CallStringList []; CallBool false;
11132                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11133   call "test0" [CallString ""; CallOptString (Some "def");
11134                 CallStringList []; CallBool false;
11135                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11136   call "test0" [CallString ""; CallOptString (Some "");
11137                 CallStringList []; CallBool false;
11138                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11139   call "test0" [CallString "abc"; CallOptString (Some "def");
11140                 CallStringList ["1"]; CallBool false;
11141                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11142   call "test0" [CallString "abc"; CallOptString (Some "def");
11143                 CallStringList ["1"; "2"]; CallBool false;
11144                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11145   call "test0" [CallString "abc"; CallOptString (Some "def");
11146                 CallStringList ["1"]; CallBool true;
11147                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11148   call "test0" [CallString "abc"; CallOptString (Some "def");
11149                 CallStringList ["1"]; CallBool false;
11150                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11151   call "test0" [CallString "abc"; CallOptString (Some "def");
11152                 CallStringList ["1"]; CallBool false;
11153                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11154   call "test0" [CallString "abc"; CallOptString (Some "def");
11155                 CallStringList ["1"]; CallBool false;
11156                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11157   call "test0" [CallString "abc"; CallOptString (Some "def");
11158                 CallStringList ["1"]; CallBool false;
11159                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11160   call "test0" [CallString "abc"; CallOptString (Some "def");
11161                 CallStringList ["1"]; CallBool false;
11162                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11163   call "test0" [CallString "abc"; CallOptString (Some "def");
11164                 CallStringList ["1"]; CallBool false;
11165                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11166
11167 (* XXX Add here tests of the return and error functions. *)
11168
11169 (* Code to generator bindings for virt-inspector.  Currently only
11170  * implemented for OCaml code (for virt-p2v 2.0).
11171  *)
11172 let rng_input = "inspector/virt-inspector.rng"
11173
11174 (* Read the input file and parse it into internal structures.  This is
11175  * by no means a complete RELAX NG parser, but is just enough to be
11176  * able to parse the specific input file.
11177  *)
11178 type rng =
11179   | Element of string * rng list        (* <element name=name/> *)
11180   | Attribute of string * rng list        (* <attribute name=name/> *)
11181   | Interleave of rng list                (* <interleave/> *)
11182   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11183   | OneOrMore of rng                        (* <oneOrMore/> *)
11184   | Optional of rng                        (* <optional/> *)
11185   | Choice of string list                (* <choice><value/>*</choice> *)
11186   | Value of string                        (* <value>str</value> *)
11187   | Text                                (* <text/> *)
11188
11189 let rec string_of_rng = function
11190   | Element (name, xs) ->
11191       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11192   | Attribute (name, xs) ->
11193       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11194   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11195   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11196   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11197   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11198   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11199   | Value value -> "Value \"" ^ value ^ "\""
11200   | Text -> "Text"
11201
11202 and string_of_rng_list xs =
11203   String.concat ", " (List.map string_of_rng xs)
11204
11205 let rec parse_rng ?defines context = function
11206   | [] -> []
11207   | Xml.Element ("element", ["name", name], children) :: rest ->
11208       Element (name, parse_rng ?defines context children)
11209       :: parse_rng ?defines context rest
11210   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11211       Attribute (name, parse_rng ?defines context children)
11212       :: parse_rng ?defines context rest
11213   | Xml.Element ("interleave", [], children) :: rest ->
11214       Interleave (parse_rng ?defines context children)
11215       :: parse_rng ?defines context rest
11216   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11217       let rng = parse_rng ?defines context [child] in
11218       (match rng with
11219        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11220        | _ ->
11221            failwithf "%s: <zeroOrMore> contains more than one child element"
11222              context
11223       )
11224   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11225       let rng = parse_rng ?defines context [child] in
11226       (match rng with
11227        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11228        | _ ->
11229            failwithf "%s: <oneOrMore> contains more than one child element"
11230              context
11231       )
11232   | Xml.Element ("optional", [], [child]) :: rest ->
11233       let rng = parse_rng ?defines context [child] in
11234       (match rng with
11235        | [child] -> Optional child :: parse_rng ?defines context rest
11236        | _ ->
11237            failwithf "%s: <optional> contains more than one child element"
11238              context
11239       )
11240   | Xml.Element ("choice", [], children) :: rest ->
11241       let values = List.map (
11242         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11243         | _ ->
11244             failwithf "%s: can't handle anything except <value> in <choice>"
11245               context
11246       ) children in
11247       Choice values
11248       :: parse_rng ?defines context rest
11249   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11250       Value value :: parse_rng ?defines context rest
11251   | Xml.Element ("text", [], []) :: rest ->
11252       Text :: parse_rng ?defines context rest
11253   | Xml.Element ("ref", ["name", name], []) :: rest ->
11254       (* Look up the reference.  Because of limitations in this parser,
11255        * we can't handle arbitrarily nested <ref> yet.  You can only
11256        * use <ref> from inside <start>.
11257        *)
11258       (match defines with
11259        | None ->
11260            failwithf "%s: contains <ref>, but no refs are defined yet" context
11261        | Some map ->
11262            let rng = StringMap.find name map in
11263            rng @ parse_rng ?defines context rest
11264       )
11265   | x :: _ ->
11266       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11267
11268 let grammar =
11269   let xml = Xml.parse_file rng_input in
11270   match xml with
11271   | Xml.Element ("grammar", _,
11272                  Xml.Element ("start", _, gram) :: defines) ->
11273       (* The <define/> elements are referenced in the <start> section,
11274        * so build a map of those first.
11275        *)
11276       let defines = List.fold_left (
11277         fun map ->
11278           function Xml.Element ("define", ["name", name], defn) ->
11279             StringMap.add name defn map
11280           | _ ->
11281               failwithf "%s: expected <define name=name/>" rng_input
11282       ) StringMap.empty defines in
11283       let defines = StringMap.mapi parse_rng defines in
11284
11285       (* Parse the <start> clause, passing the defines. *)
11286       parse_rng ~defines "<start>" gram
11287   | _ ->
11288       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11289         rng_input
11290
11291 let name_of_field = function
11292   | Element (name, _) | Attribute (name, _)
11293   | ZeroOrMore (Element (name, _))
11294   | OneOrMore (Element (name, _))
11295   | Optional (Element (name, _)) -> name
11296   | Optional (Attribute (name, _)) -> name
11297   | Text -> (* an unnamed field in an element *)
11298       "data"
11299   | rng ->
11300       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11301
11302 (* At the moment this function only generates OCaml types.  However we
11303  * should parameterize it later so it can generate types/structs in a
11304  * variety of languages.
11305  *)
11306 let generate_types xs =
11307   (* A simple type is one that can be printed out directly, eg.
11308    * "string option".  A complex type is one which has a name and has
11309    * to be defined via another toplevel definition, eg. a struct.
11310    *
11311    * generate_type generates code for either simple or complex types.
11312    * In the simple case, it returns the string ("string option").  In
11313    * the complex case, it returns the name ("mountpoint").  In the
11314    * complex case it has to print out the definition before returning,
11315    * so it should only be called when we are at the beginning of a
11316    * new line (BOL context).
11317    *)
11318   let rec generate_type = function
11319     | Text ->                                (* string *)
11320         "string", true
11321     | Choice values ->                        (* [`val1|`val2|...] *)
11322         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11323     | ZeroOrMore rng ->                        (* <rng> list *)
11324         let t, is_simple = generate_type rng in
11325         t ^ " list (* 0 or more *)", is_simple
11326     | OneOrMore rng ->                        (* <rng> list *)
11327         let t, is_simple = generate_type rng in
11328         t ^ " list (* 1 or more *)", is_simple
11329                                         (* virt-inspector hack: bool *)
11330     | Optional (Attribute (name, [Value "1"])) ->
11331         "bool", true
11332     | Optional rng ->                        (* <rng> list *)
11333         let t, is_simple = generate_type rng in
11334         t ^ " option", is_simple
11335                                         (* type name = { fields ... } *)
11336     | Element (name, fields) when is_attrs_interleave fields ->
11337         generate_type_struct name (get_attrs_interleave fields)
11338     | Element (name, [field])                (* type name = field *)
11339     | Attribute (name, [field]) ->
11340         let t, is_simple = generate_type field in
11341         if is_simple then (t, true)
11342         else (
11343           pr "type %s = %s\n" name t;
11344           name, false
11345         )
11346     | Element (name, fields) ->              (* type name = { fields ... } *)
11347         generate_type_struct name fields
11348     | rng ->
11349         failwithf "generate_type failed at: %s" (string_of_rng rng)
11350
11351   and is_attrs_interleave = function
11352     | [Interleave _] -> true
11353     | Attribute _ :: fields -> is_attrs_interleave fields
11354     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11355     | _ -> false
11356
11357   and get_attrs_interleave = function
11358     | [Interleave fields] -> fields
11359     | ((Attribute _) as field) :: fields
11360     | ((Optional (Attribute _)) as field) :: fields ->
11361         field :: get_attrs_interleave fields
11362     | _ -> assert false
11363
11364   and generate_types xs =
11365     List.iter (fun x -> ignore (generate_type x)) xs
11366
11367   and generate_type_struct name fields =
11368     (* Calculate the types of the fields first.  We have to do this
11369      * before printing anything so we are still in BOL context.
11370      *)
11371     let types = List.map fst (List.map generate_type fields) in
11372
11373     (* Special case of a struct containing just a string and another
11374      * field.  Turn it into an assoc list.
11375      *)
11376     match types with
11377     | ["string"; other] ->
11378         let fname1, fname2 =
11379           match fields with
11380           | [f1; f2] -> name_of_field f1, name_of_field f2
11381           | _ -> assert false in
11382         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11383         name, false
11384
11385     | types ->
11386         pr "type %s = {\n" name;
11387         List.iter (
11388           fun (field, ftype) ->
11389             let fname = name_of_field field in
11390             pr "  %s_%s : %s;\n" name fname ftype
11391         ) (List.combine fields types);
11392         pr "}\n";
11393         (* Return the name of this type, and
11394          * false because it's not a simple type.
11395          *)
11396         name, false
11397   in
11398
11399   generate_types xs
11400
11401 let generate_parsers xs =
11402   (* As for generate_type above, generate_parser makes a parser for
11403    * some type, and returns the name of the parser it has generated.
11404    * Because it (may) need to print something, it should always be
11405    * called in BOL context.
11406    *)
11407   let rec generate_parser = function
11408     | Text ->                                (* string *)
11409         "string_child_or_empty"
11410     | Choice values ->                        (* [`val1|`val2|...] *)
11411         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11412           (String.concat "|"
11413              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11414     | ZeroOrMore rng ->                        (* <rng> list *)
11415         let pa = generate_parser rng in
11416         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11417     | OneOrMore rng ->                        (* <rng> list *)
11418         let pa = generate_parser rng in
11419         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11420                                         (* virt-inspector hack: bool *)
11421     | Optional (Attribute (name, [Value "1"])) ->
11422         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11423     | Optional rng ->                        (* <rng> list *)
11424         let pa = generate_parser rng in
11425         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11426                                         (* type name = { fields ... } *)
11427     | Element (name, fields) when is_attrs_interleave fields ->
11428         generate_parser_struct name (get_attrs_interleave fields)
11429     | Element (name, [field]) ->        (* type name = field *)
11430         let pa = generate_parser field in
11431         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11432         pr "let %s =\n" parser_name;
11433         pr "  %s\n" pa;
11434         pr "let parse_%s = %s\n" name parser_name;
11435         parser_name
11436     | Attribute (name, [field]) ->
11437         let pa = generate_parser field in
11438         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11439         pr "let %s =\n" parser_name;
11440         pr "  %s\n" pa;
11441         pr "let parse_%s = %s\n" name parser_name;
11442         parser_name
11443     | Element (name, fields) ->              (* type name = { fields ... } *)
11444         generate_parser_struct name ([], fields)
11445     | rng ->
11446         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11447
11448   and is_attrs_interleave = function
11449     | [Interleave _] -> true
11450     | Attribute _ :: fields -> is_attrs_interleave fields
11451     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11452     | _ -> false
11453
11454   and get_attrs_interleave = function
11455     | [Interleave fields] -> [], fields
11456     | ((Attribute _) as field) :: fields
11457     | ((Optional (Attribute _)) as field) :: fields ->
11458         let attrs, interleaves = get_attrs_interleave fields in
11459         (field :: attrs), interleaves
11460     | _ -> assert false
11461
11462   and generate_parsers xs =
11463     List.iter (fun x -> ignore (generate_parser x)) xs
11464
11465   and generate_parser_struct name (attrs, interleaves) =
11466     (* Generate parsers for the fields first.  We have to do this
11467      * before printing anything so we are still in BOL context.
11468      *)
11469     let fields = attrs @ interleaves in
11470     let pas = List.map generate_parser fields in
11471
11472     (* Generate an intermediate tuple from all the fields first.
11473      * If the type is just a string + another field, then we will
11474      * return this directly, otherwise it is turned into a record.
11475      *
11476      * RELAX NG note: This code treats <interleave> and plain lists of
11477      * fields the same.  In other words, it doesn't bother enforcing
11478      * any ordering of fields in the XML.
11479      *)
11480     pr "let parse_%s x =\n" name;
11481     pr "  let t = (\n    ";
11482     let comma = ref false in
11483     List.iter (
11484       fun x ->
11485         if !comma then pr ",\n    ";
11486         comma := true;
11487         match x with
11488         | Optional (Attribute (fname, [field])), pa ->
11489             pr "%s x" pa
11490         | Optional (Element (fname, [field])), pa ->
11491             pr "%s (optional_child %S x)" pa fname
11492         | Attribute (fname, [Text]), _ ->
11493             pr "attribute %S x" fname
11494         | (ZeroOrMore _ | OneOrMore _), pa ->
11495             pr "%s x" pa
11496         | Text, pa ->
11497             pr "%s x" pa
11498         | (field, pa) ->
11499             let fname = name_of_field field in
11500             pr "%s (child %S x)" pa fname
11501     ) (List.combine fields pas);
11502     pr "\n  ) in\n";
11503
11504     (match fields with
11505      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11506          pr "  t\n"
11507
11508      | _ ->
11509          pr "  (Obj.magic t : %s)\n" name
11510 (*
11511          List.iter (
11512            function
11513            | (Optional (Attribute (fname, [field])), pa) ->
11514                pr "  %s_%s =\n" name fname;
11515                pr "    %s x;\n" pa
11516            | (Optional (Element (fname, [field])), pa) ->
11517                pr "  %s_%s =\n" name fname;
11518                pr "    (let x = optional_child %S x in\n" fname;
11519                pr "     %s x);\n" pa
11520            | (field, pa) ->
11521                let fname = name_of_field field in
11522                pr "  %s_%s =\n" name fname;
11523                pr "    (let x = child %S x in\n" fname;
11524                pr "     %s x);\n" pa
11525          ) (List.combine fields pas);
11526          pr "}\n"
11527 *)
11528     );
11529     sprintf "parse_%s" name
11530   in
11531
11532   generate_parsers xs
11533
11534 (* Generate ocaml/guestfs_inspector.mli. *)
11535 let generate_ocaml_inspector_mli () =
11536   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11537
11538   pr "\
11539 (** This is an OCaml language binding to the external [virt-inspector]
11540     program.
11541
11542     For more information, please read the man page [virt-inspector(1)].
11543 *)
11544
11545 ";
11546
11547   generate_types grammar;
11548   pr "(** The nested information returned from the {!inspect} function. *)\n";
11549   pr "\n";
11550
11551   pr "\
11552 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11553 (** To inspect a libvirt domain called [name], pass a singleton
11554     list: [inspect [name]].  When using libvirt only, you may
11555     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11556
11557     To inspect a disk image or images, pass a list of the filenames
11558     of the disk images: [inspect filenames]
11559
11560     This function inspects the given guest or disk images and
11561     returns a list of operating system(s) found and a large amount
11562     of information about them.  In the vast majority of cases,
11563     a virtual machine only contains a single operating system.
11564
11565     If the optional [~xml] parameter is given, then this function
11566     skips running the external virt-inspector program and just
11567     parses the given XML directly (which is expected to be XML
11568     produced from a previous run of virt-inspector).  The list of
11569     names and connect URI are ignored in this case.
11570
11571     This function can throw a wide variety of exceptions, for example
11572     if the external virt-inspector program cannot be found, or if
11573     it doesn't generate valid XML.
11574 *)
11575 "
11576
11577 (* Generate ocaml/guestfs_inspector.ml. *)
11578 let generate_ocaml_inspector_ml () =
11579   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11580
11581   pr "open Unix\n";
11582   pr "\n";
11583
11584   generate_types grammar;
11585   pr "\n";
11586
11587   pr "\
11588 (* Misc functions which are used by the parser code below. *)
11589 let first_child = function
11590   | Xml.Element (_, _, c::_) -> c
11591   | Xml.Element (name, _, []) ->
11592       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11593   | Xml.PCData str ->
11594       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11595
11596 let string_child_or_empty = function
11597   | Xml.Element (_, _, [Xml.PCData s]) -> s
11598   | Xml.Element (_, _, []) -> \"\"
11599   | Xml.Element (x, _, _) ->
11600       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11601                 x ^ \" instead\")
11602   | Xml.PCData str ->
11603       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11604
11605 let optional_child name xml =
11606   let children = Xml.children xml in
11607   try
11608     Some (List.find (function
11609                      | Xml.Element (n, _, _) when n = name -> true
11610                      | _ -> false) children)
11611   with
11612     Not_found -> None
11613
11614 let child name xml =
11615   match optional_child name xml with
11616   | Some c -> c
11617   | None ->
11618       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11619
11620 let attribute name xml =
11621   try Xml.attrib xml name
11622   with Xml.No_attribute _ ->
11623     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11624
11625 ";
11626
11627   generate_parsers grammar;
11628   pr "\n";
11629
11630   pr "\
11631 (* Run external virt-inspector, then use parser to parse the XML. *)
11632 let inspect ?connect ?xml names =
11633   let xml =
11634     match xml with
11635     | None ->
11636         if names = [] then invalid_arg \"inspect: no names given\";
11637         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11638           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11639           names in
11640         let cmd = List.map Filename.quote cmd in
11641         let cmd = String.concat \" \" cmd in
11642         let chan = open_process_in cmd in
11643         let xml = Xml.parse_in chan in
11644         (match close_process_in chan with
11645          | WEXITED 0 -> ()
11646          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11647          | WSIGNALED i | WSTOPPED i ->
11648              failwith (\"external virt-inspector command died or stopped on sig \" ^
11649                        string_of_int i)
11650         );
11651         xml
11652     | Some doc ->
11653         Xml.parse_string doc in
11654   parse_operatingsystems xml
11655 "
11656
11657 and generate_max_proc_nr () =
11658   pr "%d\n" max_proc_nr
11659
11660 let output_to filename k =
11661   let filename_new = filename ^ ".new" in
11662   chan := open_out filename_new;
11663   k ();
11664   close_out !chan;
11665   chan := Pervasives.stdout;
11666
11667   (* Is the new file different from the current file? *)
11668   if Sys.file_exists filename && files_equal filename filename_new then
11669     unlink filename_new                 (* same, so skip it *)
11670   else (
11671     (* different, overwrite old one *)
11672     (try chmod filename 0o644 with Unix_error _ -> ());
11673     rename filename_new filename;
11674     chmod filename 0o444;
11675     printf "written %s\n%!" filename;
11676   )
11677
11678 let perror msg = function
11679   | Unix_error (err, _, _) ->
11680       eprintf "%s: %s\n" msg (error_message err)
11681   | exn ->
11682       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11683
11684 (* Main program. *)
11685 let () =
11686   let lock_fd =
11687     try openfile "HACKING" [O_RDWR] 0
11688     with
11689     | Unix_error (ENOENT, _, _) ->
11690         eprintf "\
11691 You are probably running this from the wrong directory.
11692 Run it from the top source directory using the command
11693   src/generator.ml
11694 ";
11695         exit 1
11696     | exn ->
11697         perror "open: HACKING" exn;
11698         exit 1 in
11699
11700   (* Acquire a lock so parallel builds won't try to run the generator
11701    * twice at the same time.  Subsequent builds will wait for the first
11702    * one to finish.  Note the lock is released implicitly when the
11703    * program exits.
11704    *)
11705   (try lockf lock_fd F_LOCK 1
11706    with exn ->
11707      perror "lock: HACKING" exn;
11708      exit 1);
11709
11710   check_functions ();
11711
11712   output_to "src/guestfs_protocol.x" generate_xdr;
11713   output_to "src/guestfs-structs.h" generate_structs_h;
11714   output_to "src/guestfs-actions.h" generate_actions_h;
11715   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11716   output_to "src/guestfs-actions.c" generate_client_actions;
11717   output_to "src/guestfs-bindtests.c" generate_bindtests;
11718   output_to "src/guestfs-structs.pod" generate_structs_pod;
11719   output_to "src/guestfs-actions.pod" generate_actions_pod;
11720   output_to "src/guestfs-availability.pod" generate_availability_pod;
11721   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11722   output_to "src/libguestfs.syms" generate_linker_script;
11723   output_to "daemon/actions.h" generate_daemon_actions_h;
11724   output_to "daemon/stubs.c" generate_daemon_actions;
11725   output_to "daemon/names.c" generate_daemon_names;
11726   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11727   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11728   output_to "capitests/tests.c" generate_tests;
11729   output_to "fish/cmds.c" generate_fish_cmds;
11730   output_to "fish/completion.c" generate_fish_completion;
11731   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11732   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11733   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11734   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11735   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11736   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11737   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11738   output_to "perl/Guestfs.xs" generate_perl_xs;
11739   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11740   output_to "perl/bindtests.pl" generate_perl_bindtests;
11741   output_to "python/guestfs-py.c" generate_python_c;
11742   output_to "python/guestfs.py" generate_python_py;
11743   output_to "python/bindtests.py" generate_python_bindtests;
11744   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11745   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11746   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11747
11748   List.iter (
11749     fun (typ, jtyp) ->
11750       let cols = cols_of_struct typ in
11751       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11752       output_to filename (generate_java_struct jtyp cols);
11753   ) java_structs;
11754
11755   output_to "java/Makefile.inc" generate_java_makefile_inc;
11756   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11757   output_to "java/Bindtests.java" generate_java_bindtests;
11758   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11759   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11760   output_to "csharp/Libguestfs.cs" generate_csharp;
11761
11762   (* Always generate this file last, and unconditionally.  It's used
11763    * by the Makefile to know when we must re-run the generator.
11764    *)
11765   let chan = open_out "src/stamp-generator" in
11766   fprintf chan "1\n";
11767   close_out chan;
11768
11769   printf "generated %d lines of code\n" !lines