New API: fill-pattern for creating files with predefined patterns.
[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 (* Field types for structures. *)
4640 type field =
4641   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4642   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4643   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4644   | FUInt32
4645   | FInt32
4646   | FUInt64
4647   | FInt64
4648   | FBytes                      (* Any int measure that counts bytes. *)
4649   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4650   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4651
4652 (* Because we generate extra parsing code for LVM command line tools,
4653  * we have to pull out the LVM columns separately here.
4654  *)
4655 let lvm_pv_cols = [
4656   "pv_name", FString;
4657   "pv_uuid", FUUID;
4658   "pv_fmt", FString;
4659   "pv_size", FBytes;
4660   "dev_size", FBytes;
4661   "pv_free", FBytes;
4662   "pv_used", FBytes;
4663   "pv_attr", FString (* XXX *);
4664   "pv_pe_count", FInt64;
4665   "pv_pe_alloc_count", FInt64;
4666   "pv_tags", FString;
4667   "pe_start", FBytes;
4668   "pv_mda_count", FInt64;
4669   "pv_mda_free", FBytes;
4670   (* Not in Fedora 10:
4671      "pv_mda_size", FBytes;
4672   *)
4673 ]
4674 let lvm_vg_cols = [
4675   "vg_name", FString;
4676   "vg_uuid", FUUID;
4677   "vg_fmt", FString;
4678   "vg_attr", FString (* XXX *);
4679   "vg_size", FBytes;
4680   "vg_free", FBytes;
4681   "vg_sysid", FString;
4682   "vg_extent_size", FBytes;
4683   "vg_extent_count", FInt64;
4684   "vg_free_count", FInt64;
4685   "max_lv", FInt64;
4686   "max_pv", FInt64;
4687   "pv_count", FInt64;
4688   "lv_count", FInt64;
4689   "snap_count", FInt64;
4690   "vg_seqno", FInt64;
4691   "vg_tags", FString;
4692   "vg_mda_count", FInt64;
4693   "vg_mda_free", FBytes;
4694   (* Not in Fedora 10:
4695      "vg_mda_size", FBytes;
4696   *)
4697 ]
4698 let lvm_lv_cols = [
4699   "lv_name", FString;
4700   "lv_uuid", FUUID;
4701   "lv_attr", FString (* XXX *);
4702   "lv_major", FInt64;
4703   "lv_minor", FInt64;
4704   "lv_kernel_major", FInt64;
4705   "lv_kernel_minor", FInt64;
4706   "lv_size", FBytes;
4707   "seg_count", FInt64;
4708   "origin", FString;
4709   "snap_percent", FOptPercent;
4710   "copy_percent", FOptPercent;
4711   "move_pv", FString;
4712   "lv_tags", FString;
4713   "mirror_log", FString;
4714   "modules", FString;
4715 ]
4716
4717 (* Names and fields in all structures (in RStruct and RStructList)
4718  * that we support.
4719  *)
4720 let structs = [
4721   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4722    * not use this struct in any new code.
4723    *)
4724   "int_bool", [
4725     "i", FInt32;                (* for historical compatibility *)
4726     "b", FInt32;                (* for historical compatibility *)
4727   ];
4728
4729   (* LVM PVs, VGs, LVs. *)
4730   "lvm_pv", lvm_pv_cols;
4731   "lvm_vg", lvm_vg_cols;
4732   "lvm_lv", lvm_lv_cols;
4733
4734   (* Column names and types from stat structures.
4735    * NB. Can't use things like 'st_atime' because glibc header files
4736    * define some of these as macros.  Ugh.
4737    *)
4738   "stat", [
4739     "dev", FInt64;
4740     "ino", FInt64;
4741     "mode", FInt64;
4742     "nlink", FInt64;
4743     "uid", FInt64;
4744     "gid", FInt64;
4745     "rdev", FInt64;
4746     "size", FInt64;
4747     "blksize", FInt64;
4748     "blocks", FInt64;
4749     "atime", FInt64;
4750     "mtime", FInt64;
4751     "ctime", FInt64;
4752   ];
4753   "statvfs", [
4754     "bsize", FInt64;
4755     "frsize", FInt64;
4756     "blocks", FInt64;
4757     "bfree", FInt64;
4758     "bavail", FInt64;
4759     "files", FInt64;
4760     "ffree", FInt64;
4761     "favail", FInt64;
4762     "fsid", FInt64;
4763     "flag", FInt64;
4764     "namemax", FInt64;
4765   ];
4766
4767   (* Column names in dirent structure. *)
4768   "dirent", [
4769     "ino", FInt64;
4770     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4771     "ftyp", FChar;
4772     "name", FString;
4773   ];
4774
4775   (* Version numbers. *)
4776   "version", [
4777     "major", FInt64;
4778     "minor", FInt64;
4779     "release", FInt64;
4780     "extra", FString;
4781   ];
4782
4783   (* Extended attribute. *)
4784   "xattr", [
4785     "attrname", FString;
4786     "attrval", FBuffer;
4787   ];
4788
4789   (* Inotify events. *)
4790   "inotify_event", [
4791     "in_wd", FInt64;
4792     "in_mask", FUInt32;
4793     "in_cookie", FUInt32;
4794     "in_name", FString;
4795   ];
4796
4797   (* Partition table entry. *)
4798   "partition", [
4799     "part_num", FInt32;
4800     "part_start", FBytes;
4801     "part_end", FBytes;
4802     "part_size", FBytes;
4803   ];
4804 ] (* end of structs *)
4805
4806 (* Ugh, Java has to be different ..
4807  * These names are also used by the Haskell bindings.
4808  *)
4809 let java_structs = [
4810   "int_bool", "IntBool";
4811   "lvm_pv", "PV";
4812   "lvm_vg", "VG";
4813   "lvm_lv", "LV";
4814   "stat", "Stat";
4815   "statvfs", "StatVFS";
4816   "dirent", "Dirent";
4817   "version", "Version";
4818   "xattr", "XAttr";
4819   "inotify_event", "INotifyEvent";
4820   "partition", "Partition";
4821 ]
4822
4823 (* What structs are actually returned. *)
4824 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4825
4826 (* Returns a list of RStruct/RStructList structs that are returned
4827  * by any function.  Each element of returned list is a pair:
4828  *
4829  * (structname, RStructOnly)
4830  *    == there exists function which returns RStruct (_, structname)
4831  * (structname, RStructListOnly)
4832  *    == there exists function which returns RStructList (_, structname)
4833  * (structname, RStructAndList)
4834  *    == there are functions returning both RStruct (_, structname)
4835  *                                      and RStructList (_, structname)
4836  *)
4837 let rstructs_used_by functions =
4838   (* ||| is a "logical OR" for rstructs_used_t *)
4839   let (|||) a b =
4840     match a, b with
4841     | RStructAndList, _
4842     | _, RStructAndList -> RStructAndList
4843     | RStructOnly, RStructListOnly
4844     | RStructListOnly, RStructOnly -> RStructAndList
4845     | RStructOnly, RStructOnly -> RStructOnly
4846     | RStructListOnly, RStructListOnly -> RStructListOnly
4847   in
4848
4849   let h = Hashtbl.create 13 in
4850
4851   (* if elem->oldv exists, update entry using ||| operator,
4852    * else just add elem->newv to the hash
4853    *)
4854   let update elem newv =
4855     try  let oldv = Hashtbl.find h elem in
4856          Hashtbl.replace h elem (newv ||| oldv)
4857     with Not_found -> Hashtbl.add h elem newv
4858   in
4859
4860   List.iter (
4861     fun (_, style, _, _, _, _, _) ->
4862       match fst style with
4863       | RStruct (_, structname) -> update structname RStructOnly
4864       | RStructList (_, structname) -> update structname RStructListOnly
4865       | _ -> ()
4866   ) functions;
4867
4868   (* return key->values as a list of (key,value) *)
4869   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4870
4871 (* Used for testing language bindings. *)
4872 type callt =
4873   | CallString of string
4874   | CallOptString of string option
4875   | CallStringList of string list
4876   | CallInt of int
4877   | CallInt64 of int64
4878   | CallBool of bool
4879
4880 (* Used to memoize the result of pod2text. *)
4881 let pod2text_memo_filename = "src/.pod2text.data"
4882 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4883   try
4884     let chan = open_in pod2text_memo_filename in
4885     let v = input_value chan in
4886     close_in chan;
4887     v
4888   with
4889     _ -> Hashtbl.create 13
4890 let pod2text_memo_updated () =
4891   let chan = open_out pod2text_memo_filename in
4892   output_value chan pod2text_memo;
4893   close_out chan
4894
4895 (* Useful functions.
4896  * Note we don't want to use any external OCaml libraries which
4897  * makes this a bit harder than it should be.
4898  *)
4899 module StringMap = Map.Make (String)
4900
4901 let failwithf fs = ksprintf failwith fs
4902
4903 let unique = let i = ref 0 in fun () -> incr i; !i
4904
4905 let replace_char s c1 c2 =
4906   let s2 = String.copy s in
4907   let r = ref false in
4908   for i = 0 to String.length s2 - 1 do
4909     if String.unsafe_get s2 i = c1 then (
4910       String.unsafe_set s2 i c2;
4911       r := true
4912     )
4913   done;
4914   if not !r then s else s2
4915
4916 let isspace c =
4917   c = ' '
4918   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4919
4920 let triml ?(test = isspace) str =
4921   let i = ref 0 in
4922   let n = ref (String.length str) in
4923   while !n > 0 && test str.[!i]; do
4924     decr n;
4925     incr i
4926   done;
4927   if !i = 0 then str
4928   else String.sub str !i !n
4929
4930 let trimr ?(test = isspace) str =
4931   let n = ref (String.length str) in
4932   while !n > 0 && test str.[!n-1]; do
4933     decr n
4934   done;
4935   if !n = String.length str then str
4936   else String.sub str 0 !n
4937
4938 let trim ?(test = isspace) str =
4939   trimr ~test (triml ~test str)
4940
4941 let rec find s sub =
4942   let len = String.length s in
4943   let sublen = String.length sub in
4944   let rec loop i =
4945     if i <= len-sublen then (
4946       let rec loop2 j =
4947         if j < sublen then (
4948           if s.[i+j] = sub.[j] then loop2 (j+1)
4949           else -1
4950         ) else
4951           i (* found *)
4952       in
4953       let r = loop2 0 in
4954       if r = -1 then loop (i+1) else r
4955     ) else
4956       -1 (* not found *)
4957   in
4958   loop 0
4959
4960 let rec replace_str s s1 s2 =
4961   let len = String.length s in
4962   let sublen = String.length s1 in
4963   let i = find s s1 in
4964   if i = -1 then s
4965   else (
4966     let s' = String.sub s 0 i in
4967     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4968     s' ^ s2 ^ replace_str s'' s1 s2
4969   )
4970
4971 let rec string_split sep str =
4972   let len = String.length str in
4973   let seplen = String.length sep in
4974   let i = find str sep in
4975   if i = -1 then [str]
4976   else (
4977     let s' = String.sub str 0 i in
4978     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4979     s' :: string_split sep s''
4980   )
4981
4982 let files_equal n1 n2 =
4983   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4984   match Sys.command cmd with
4985   | 0 -> true
4986   | 1 -> false
4987   | i -> failwithf "%s: failed with error code %d" cmd i
4988
4989 let rec filter_map f = function
4990   | [] -> []
4991   | x :: xs ->
4992       match f x with
4993       | Some y -> y :: filter_map f xs
4994       | None -> filter_map f xs
4995
4996 let rec find_map f = function
4997   | [] -> raise Not_found
4998   | x :: xs ->
4999       match f x with
5000       | Some y -> y
5001       | None -> find_map f xs
5002
5003 let iteri f xs =
5004   let rec loop i = function
5005     | [] -> ()
5006     | x :: xs -> f i x; loop (i+1) xs
5007   in
5008   loop 0 xs
5009
5010 let mapi f xs =
5011   let rec loop i = function
5012     | [] -> []
5013     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5014   in
5015   loop 0 xs
5016
5017 let count_chars c str =
5018   let count = ref 0 in
5019   for i = 0 to String.length str - 1 do
5020     if c = String.unsafe_get str i then incr count
5021   done;
5022   !count
5023
5024 let name_of_argt = function
5025   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5026   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5027   | FileIn n | FileOut n -> n
5028
5029 let java_name_of_struct typ =
5030   try List.assoc typ java_structs
5031   with Not_found ->
5032     failwithf
5033       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5034
5035 let cols_of_struct typ =
5036   try List.assoc typ structs
5037   with Not_found ->
5038     failwithf "cols_of_struct: unknown struct %s" typ
5039
5040 let seq_of_test = function
5041   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5042   | TestOutputListOfDevices (s, _)
5043   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5044   | TestOutputTrue s | TestOutputFalse s
5045   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5046   | TestOutputStruct (s, _)
5047   | TestLastFail s -> s
5048
5049 (* Handling for function flags. *)
5050 let protocol_limit_warning =
5051   "Because of the message protocol, there is a transfer limit
5052 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5053
5054 let danger_will_robinson =
5055   "B<This command is dangerous.  Without careful use you
5056 can easily destroy all your data>."
5057
5058 let deprecation_notice flags =
5059   try
5060     let alt =
5061       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5062     let txt =
5063       sprintf "This function is deprecated.
5064 In new code, use the C<%s> call instead.
5065
5066 Deprecated functions will not be removed from the API, but the
5067 fact that they are deprecated indicates that there are problems
5068 with correct use of these functions." alt in
5069     Some txt
5070   with
5071     Not_found -> None
5072
5073 (* Create list of optional groups. *)
5074 let optgroups =
5075   let h = Hashtbl.create 13 in
5076   List.iter (
5077     fun (name, _, _, flags, _, _, _) ->
5078       List.iter (
5079         function
5080         | Optional group ->
5081             let names = try Hashtbl.find h group with Not_found -> [] in
5082             Hashtbl.replace h group (name :: names)
5083         | _ -> ()
5084       ) flags
5085   ) daemon_functions;
5086   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5087   let groups =
5088     List.map (
5089       fun group -> group, List.sort compare (Hashtbl.find h group)
5090     ) groups in
5091   List.sort (fun x y -> compare (fst x) (fst y)) groups
5092
5093 (* Check function names etc. for consistency. *)
5094 let check_functions () =
5095   let contains_uppercase str =
5096     let len = String.length str in
5097     let rec loop i =
5098       if i >= len then false
5099       else (
5100         let c = str.[i] in
5101         if c >= 'A' && c <= 'Z' then true
5102         else loop (i+1)
5103       )
5104     in
5105     loop 0
5106   in
5107
5108   (* Check function names. *)
5109   List.iter (
5110     fun (name, _, _, _, _, _, _) ->
5111       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5112         failwithf "function name %s does not need 'guestfs' prefix" name;
5113       if name = "" then
5114         failwithf "function name is empty";
5115       if name.[0] < 'a' || name.[0] > 'z' then
5116         failwithf "function name %s must start with lowercase a-z" name;
5117       if String.contains name '-' then
5118         failwithf "function name %s should not contain '-', use '_' instead."
5119           name
5120   ) all_functions;
5121
5122   (* Check function parameter/return names. *)
5123   List.iter (
5124     fun (name, style, _, _, _, _, _) ->
5125       let check_arg_ret_name n =
5126         if contains_uppercase n then
5127           failwithf "%s param/ret %s should not contain uppercase chars"
5128             name n;
5129         if String.contains n '-' || String.contains n '_' then
5130           failwithf "%s param/ret %s should not contain '-' or '_'"
5131             name n;
5132         if n = "value" then
5133           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;
5134         if n = "int" || n = "char" || n = "short" || n = "long" then
5135           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5136         if n = "i" || n = "n" then
5137           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5138         if n = "argv" || n = "args" then
5139           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5140
5141         (* List Haskell, OCaml and C keywords here.
5142          * http://www.haskell.org/haskellwiki/Keywords
5143          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5144          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5145          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5146          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5147          * Omitting _-containing words, since they're handled above.
5148          * Omitting the OCaml reserved word, "val", is ok,
5149          * and saves us from renaming several parameters.
5150          *)
5151         let reserved = [
5152           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5153           "char"; "class"; "const"; "constraint"; "continue"; "data";
5154           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5155           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5156           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5157           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5158           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5159           "interface";
5160           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5161           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5162           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5163           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5164           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5165           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5166           "volatile"; "when"; "where"; "while";
5167           ] in
5168         if List.mem n reserved then
5169           failwithf "%s has param/ret using reserved word %s" name n;
5170       in
5171
5172       (match fst style with
5173        | RErr -> ()
5174        | RInt n | RInt64 n | RBool n
5175        | RConstString n | RConstOptString n | RString n
5176        | RStringList n | RStruct (n, _) | RStructList (n, _)
5177        | RHashtable n | RBufferOut n ->
5178            check_arg_ret_name n
5179       );
5180       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5181   ) all_functions;
5182
5183   (* Check short descriptions. *)
5184   List.iter (
5185     fun (name, _, _, _, _, shortdesc, _) ->
5186       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5187         failwithf "short description of %s should begin with lowercase." name;
5188       let c = shortdesc.[String.length shortdesc-1] in
5189       if c = '\n' || c = '.' then
5190         failwithf "short description of %s should not end with . or \\n." name
5191   ) all_functions;
5192
5193   (* Check long descriptions. *)
5194   List.iter (
5195     fun (name, _, _, _, _, _, longdesc) ->
5196       if longdesc.[String.length longdesc-1] = '\n' then
5197         failwithf "long description of %s should not end with \\n." name
5198   ) all_functions;
5199
5200   (* Check proc_nrs. *)
5201   List.iter (
5202     fun (name, _, proc_nr, _, _, _, _) ->
5203       if proc_nr <= 0 then
5204         failwithf "daemon function %s should have proc_nr > 0" name
5205   ) daemon_functions;
5206
5207   List.iter (
5208     fun (name, _, proc_nr, _, _, _, _) ->
5209       if proc_nr <> -1 then
5210         failwithf "non-daemon function %s should have proc_nr -1" name
5211   ) non_daemon_functions;
5212
5213   let proc_nrs =
5214     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5215       daemon_functions in
5216   let proc_nrs =
5217     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5218   let rec loop = function
5219     | [] -> ()
5220     | [_] -> ()
5221     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5222         loop rest
5223     | (name1,nr1) :: (name2,nr2) :: _ ->
5224         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5225           name1 name2 nr1 nr2
5226   in
5227   loop proc_nrs;
5228
5229   (* Check tests. *)
5230   List.iter (
5231     function
5232       (* Ignore functions that have no tests.  We generate a
5233        * warning when the user does 'make check' instead.
5234        *)
5235     | name, _, _, _, [], _, _ -> ()
5236     | name, _, _, _, tests, _, _ ->
5237         let funcs =
5238           List.map (
5239             fun (_, _, test) ->
5240               match seq_of_test test with
5241               | [] ->
5242                   failwithf "%s has a test containing an empty sequence" name
5243               | cmds -> List.map List.hd cmds
5244           ) tests in
5245         let funcs = List.flatten funcs in
5246
5247         let tested = List.mem name funcs in
5248
5249         if not tested then
5250           failwithf "function %s has tests but does not test itself" name
5251   ) all_functions
5252
5253 (* 'pr' prints to the current output file. *)
5254 let chan = ref Pervasives.stdout
5255 let lines = ref 0
5256 let pr fs =
5257   ksprintf
5258     (fun str ->
5259        let i = count_chars '\n' str in
5260        lines := !lines + i;
5261        output_string !chan str
5262     ) fs
5263
5264 let copyright_years =
5265   let this_year = 1900 + (localtime (time ())).tm_year in
5266   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5267
5268 (* Generate a header block in a number of standard styles. *)
5269 type comment_style =
5270     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5271 type license = GPLv2plus | LGPLv2plus
5272
5273 let generate_header ?(extra_inputs = []) comment license =
5274   let inputs = "src/generator.ml" :: extra_inputs in
5275   let c = match comment with
5276     | CStyle ->         pr "/* "; " *"
5277     | CPlusPlusStyle -> pr "// "; "//"
5278     | HashStyle ->      pr "# ";  "#"
5279     | OCamlStyle ->     pr "(* "; " *"
5280     | HaskellStyle ->   pr "{- "; "  " in
5281   pr "libguestfs generated file\n";
5282   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5283   List.iter (pr "%s   %s\n" c) inputs;
5284   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5285   pr "%s\n" c;
5286   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5287   pr "%s\n" c;
5288   (match license with
5289    | GPLv2plus ->
5290        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5291        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5292        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5293        pr "%s (at your option) any later version.\n" c;
5294        pr "%s\n" c;
5295        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5296        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5297        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5298        pr "%s GNU General Public License for more details.\n" c;
5299        pr "%s\n" c;
5300        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5301        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5302        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5303
5304    | LGPLv2plus ->
5305        pr "%s This library is free software; you can redistribute it and/or\n" c;
5306        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5307        pr "%s License as published by the Free Software Foundation; either\n" c;
5308        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5309        pr "%s\n" c;
5310        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5311        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5312        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5313        pr "%s Lesser General Public License for more details.\n" c;
5314        pr "%s\n" c;
5315        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5316        pr "%s License along with this library; if not, write to the Free Software\n" c;
5317        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5318   );
5319   (match comment with
5320    | CStyle -> pr " */\n"
5321    | CPlusPlusStyle
5322    | HashStyle -> ()
5323    | OCamlStyle -> pr " *)\n"
5324    | HaskellStyle -> pr "-}\n"
5325   );
5326   pr "\n"
5327
5328 (* Start of main code generation functions below this line. *)
5329
5330 (* Generate the pod documentation for the C API. *)
5331 let rec generate_actions_pod () =
5332   List.iter (
5333     fun (shortname, style, _, flags, _, _, longdesc) ->
5334       if not (List.mem NotInDocs flags) then (
5335         let name = "guestfs_" ^ shortname in
5336         pr "=head2 %s\n\n" name;
5337         pr " ";
5338         generate_prototype ~extern:false ~handle:"g" name style;
5339         pr "\n\n";
5340         pr "%s\n\n" longdesc;
5341         (match fst style with
5342          | RErr ->
5343              pr "This function returns 0 on success or -1 on error.\n\n"
5344          | RInt _ ->
5345              pr "On error this function returns -1.\n\n"
5346          | RInt64 _ ->
5347              pr "On error this function returns -1.\n\n"
5348          | RBool _ ->
5349              pr "This function returns a C truth value on success or -1 on error.\n\n"
5350          | RConstString _ ->
5351              pr "This function returns a string, or NULL on error.
5352 The string is owned by the guest handle and must I<not> be freed.\n\n"
5353          | RConstOptString _ ->
5354              pr "This function returns a string which may be NULL.
5355 There is way to return an error from this function.
5356 The string is owned by the guest handle and must I<not> be freed.\n\n"
5357          | RString _ ->
5358              pr "This function returns a string, or NULL on error.
5359 I<The caller must free the returned string after use>.\n\n"
5360          | RStringList _ ->
5361              pr "This function returns a NULL-terminated array of strings
5362 (like L<environ(3)>), or NULL if there was an error.
5363 I<The caller must free the strings and the array after use>.\n\n"
5364          | RStruct (_, typ) ->
5365              pr "This function returns a C<struct guestfs_%s *>,
5366 or NULL if there was an error.
5367 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5368          | RStructList (_, typ) ->
5369              pr "This function returns a C<struct guestfs_%s_list *>
5370 (see E<lt>guestfs-structs.hE<gt>),
5371 or NULL if there was an error.
5372 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5373          | RHashtable _ ->
5374              pr "This function returns a NULL-terminated array of
5375 strings, or NULL if there was an error.
5376 The array of strings will always have length C<2n+1>, where
5377 C<n> keys and values alternate, followed by the trailing NULL entry.
5378 I<The caller must free the strings and the array after use>.\n\n"
5379          | RBufferOut _ ->
5380              pr "This function returns a buffer, or NULL on error.
5381 The size of the returned buffer is written to C<*size_r>.
5382 I<The caller must free the returned buffer after use>.\n\n"
5383         );
5384         if List.mem ProtocolLimitWarning flags then
5385           pr "%s\n\n" protocol_limit_warning;
5386         if List.mem DangerWillRobinson flags then
5387           pr "%s\n\n" danger_will_robinson;
5388         match deprecation_notice flags with
5389         | None -> ()
5390         | Some txt -> pr "%s\n\n" txt
5391       )
5392   ) all_functions_sorted
5393
5394 and generate_structs_pod () =
5395   (* Structs documentation. *)
5396   List.iter (
5397     fun (typ, cols) ->
5398       pr "=head2 guestfs_%s\n" typ;
5399       pr "\n";
5400       pr " struct guestfs_%s {\n" typ;
5401       List.iter (
5402         function
5403         | name, FChar -> pr "   char %s;\n" name
5404         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5405         | name, FInt32 -> pr "   int32_t %s;\n" name
5406         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5407         | name, FInt64 -> pr "   int64_t %s;\n" name
5408         | name, FString -> pr "   char *%s;\n" name
5409         | name, FBuffer ->
5410             pr "   /* The next two fields describe a byte array. */\n";
5411             pr "   uint32_t %s_len;\n" name;
5412             pr "   char *%s;\n" name
5413         | name, FUUID ->
5414             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5415             pr "   char %s[32];\n" name
5416         | name, FOptPercent ->
5417             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5418             pr "   float %s;\n" name
5419       ) cols;
5420       pr " };\n";
5421       pr " \n";
5422       pr " struct guestfs_%s_list {\n" typ;
5423       pr "   uint32_t len; /* Number of elements in list. */\n";
5424       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5425       pr " };\n";
5426       pr " \n";
5427       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5428       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5429         typ typ;
5430       pr "\n"
5431   ) structs
5432
5433 and generate_availability_pod () =
5434   (* Availability documentation. *)
5435   pr "=over 4\n";
5436   pr "\n";
5437   List.iter (
5438     fun (group, functions) ->
5439       pr "=item B<%s>\n" group;
5440       pr "\n";
5441       pr "The following functions:\n";
5442       List.iter (pr "L</guestfs_%s>\n") functions;
5443       pr "\n"
5444   ) optgroups;
5445   pr "=back\n";
5446   pr "\n"
5447
5448 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5449  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5450  *
5451  * We have to use an underscore instead of a dash because otherwise
5452  * rpcgen generates incorrect code.
5453  *
5454  * This header is NOT exported to clients, but see also generate_structs_h.
5455  *)
5456 and generate_xdr () =
5457   generate_header CStyle LGPLv2plus;
5458
5459   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5460   pr "typedef string str<>;\n";
5461   pr "\n";
5462
5463   (* Internal structures. *)
5464   List.iter (
5465     function
5466     | typ, cols ->
5467         pr "struct guestfs_int_%s {\n" typ;
5468         List.iter (function
5469                    | name, FChar -> pr "  char %s;\n" name
5470                    | name, FString -> pr "  string %s<>;\n" name
5471                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5472                    | name, FUUID -> pr "  opaque %s[32];\n" name
5473                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5474                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5475                    | name, FOptPercent -> pr "  float %s;\n" name
5476                   ) cols;
5477         pr "};\n";
5478         pr "\n";
5479         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5480         pr "\n";
5481   ) structs;
5482
5483   List.iter (
5484     fun (shortname, style, _, _, _, _, _) ->
5485       let name = "guestfs_" ^ shortname in
5486
5487       (match snd style with
5488        | [] -> ()
5489        | args ->
5490            pr "struct %s_args {\n" name;
5491            List.iter (
5492              function
5493              | Pathname n | Device n | Dev_or_Path n | String n ->
5494                  pr "  string %s<>;\n" n
5495              | OptString n -> pr "  str *%s;\n" n
5496              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5497              | Bool n -> pr "  bool %s;\n" n
5498              | Int n -> pr "  int %s;\n" n
5499              | Int64 n -> pr "  hyper %s;\n" n
5500              | FileIn _ | FileOut _ -> ()
5501            ) args;
5502            pr "};\n\n"
5503       );
5504       (match fst style with
5505        | RErr -> ()
5506        | RInt n ->
5507            pr "struct %s_ret {\n" name;
5508            pr "  int %s;\n" n;
5509            pr "};\n\n"
5510        | RInt64 n ->
5511            pr "struct %s_ret {\n" name;
5512            pr "  hyper %s;\n" n;
5513            pr "};\n\n"
5514        | RBool n ->
5515            pr "struct %s_ret {\n" name;
5516            pr "  bool %s;\n" n;
5517            pr "};\n\n"
5518        | RConstString _ | RConstOptString _ ->
5519            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5520        | RString n ->
5521            pr "struct %s_ret {\n" name;
5522            pr "  string %s<>;\n" n;
5523            pr "};\n\n"
5524        | RStringList n ->
5525            pr "struct %s_ret {\n" name;
5526            pr "  str %s<>;\n" n;
5527            pr "};\n\n"
5528        | RStruct (n, typ) ->
5529            pr "struct %s_ret {\n" name;
5530            pr "  guestfs_int_%s %s;\n" typ n;
5531            pr "};\n\n"
5532        | RStructList (n, typ) ->
5533            pr "struct %s_ret {\n" name;
5534            pr "  guestfs_int_%s_list %s;\n" typ n;
5535            pr "};\n\n"
5536        | RHashtable n ->
5537            pr "struct %s_ret {\n" name;
5538            pr "  str %s<>;\n" n;
5539            pr "};\n\n"
5540        | RBufferOut n ->
5541            pr "struct %s_ret {\n" name;
5542            pr "  opaque %s<>;\n" n;
5543            pr "};\n\n"
5544       );
5545   ) daemon_functions;
5546
5547   (* Table of procedure numbers. *)
5548   pr "enum guestfs_procedure {\n";
5549   List.iter (
5550     fun (shortname, _, proc_nr, _, _, _, _) ->
5551       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5552   ) daemon_functions;
5553   pr "  GUESTFS_PROC_NR_PROCS\n";
5554   pr "};\n";
5555   pr "\n";
5556
5557   (* Having to choose a maximum message size is annoying for several
5558    * reasons (it limits what we can do in the API), but it (a) makes
5559    * the protocol a lot simpler, and (b) provides a bound on the size
5560    * of the daemon which operates in limited memory space.
5561    *)
5562   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5563   pr "\n";
5564
5565   (* Message header, etc. *)
5566   pr "\
5567 /* The communication protocol is now documented in the guestfs(3)
5568  * manpage.
5569  */
5570
5571 const GUESTFS_PROGRAM = 0x2000F5F5;
5572 const GUESTFS_PROTOCOL_VERSION = 1;
5573
5574 /* These constants must be larger than any possible message length. */
5575 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5576 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5577
5578 enum guestfs_message_direction {
5579   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5580   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5581 };
5582
5583 enum guestfs_message_status {
5584   GUESTFS_STATUS_OK = 0,
5585   GUESTFS_STATUS_ERROR = 1
5586 };
5587
5588 const GUESTFS_ERROR_LEN = 256;
5589
5590 struct guestfs_message_error {
5591   string error_message<GUESTFS_ERROR_LEN>;
5592 };
5593
5594 struct guestfs_message_header {
5595   unsigned prog;                     /* GUESTFS_PROGRAM */
5596   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5597   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5598   guestfs_message_direction direction;
5599   unsigned serial;                   /* message serial number */
5600   guestfs_message_status status;
5601 };
5602
5603 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5604
5605 struct guestfs_chunk {
5606   int cancel;                        /* if non-zero, transfer is cancelled */
5607   /* data size is 0 bytes if the transfer has finished successfully */
5608   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5609 };
5610 "
5611
5612 (* Generate the guestfs-structs.h file. *)
5613 and generate_structs_h () =
5614   generate_header CStyle LGPLv2plus;
5615
5616   (* This is a public exported header file containing various
5617    * structures.  The structures are carefully written to have
5618    * exactly the same in-memory format as the XDR structures that
5619    * we use on the wire to the daemon.  The reason for creating
5620    * copies of these structures here is just so we don't have to
5621    * export the whole of guestfs_protocol.h (which includes much
5622    * unrelated and XDR-dependent stuff that we don't want to be
5623    * public, or required by clients).
5624    *
5625    * To reiterate, we will pass these structures to and from the
5626    * client with a simple assignment or memcpy, so the format
5627    * must be identical to what rpcgen / the RFC defines.
5628    *)
5629
5630   (* Public structures. *)
5631   List.iter (
5632     fun (typ, cols) ->
5633       pr "struct guestfs_%s {\n" typ;
5634       List.iter (
5635         function
5636         | name, FChar -> pr "  char %s;\n" name
5637         | name, FString -> pr "  char *%s;\n" name
5638         | name, FBuffer ->
5639             pr "  uint32_t %s_len;\n" name;
5640             pr "  char *%s;\n" name
5641         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5642         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5643         | name, FInt32 -> pr "  int32_t %s;\n" name
5644         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5645         | name, FInt64 -> pr "  int64_t %s;\n" name
5646         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5647       ) cols;
5648       pr "};\n";
5649       pr "\n";
5650       pr "struct guestfs_%s_list {\n" typ;
5651       pr "  uint32_t len;\n";
5652       pr "  struct guestfs_%s *val;\n" typ;
5653       pr "};\n";
5654       pr "\n";
5655       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5656       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5657       pr "\n"
5658   ) structs
5659
5660 (* Generate the guestfs-actions.h file. *)
5661 and generate_actions_h () =
5662   generate_header CStyle LGPLv2plus;
5663   List.iter (
5664     fun (shortname, style, _, _, _, _, _) ->
5665       let name = "guestfs_" ^ shortname in
5666       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5667         name style
5668   ) all_functions
5669
5670 (* Generate the guestfs-internal-actions.h file. *)
5671 and generate_internal_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   ) non_daemon_functions
5679
5680 (* Generate the client-side dispatch stubs. *)
5681 and generate_client_actions () =
5682   generate_header CStyle LGPLv2plus;
5683
5684   pr "\
5685 #include <stdio.h>
5686 #include <stdlib.h>
5687 #include <stdint.h>
5688 #include <string.h>
5689 #include <inttypes.h>
5690
5691 #include \"guestfs.h\"
5692 #include \"guestfs-internal.h\"
5693 #include \"guestfs-internal-actions.h\"
5694 #include \"guestfs_protocol.h\"
5695
5696 #define error guestfs_error
5697 //#define perrorf guestfs_perrorf
5698 #define safe_malloc guestfs_safe_malloc
5699 #define safe_realloc guestfs_safe_realloc
5700 //#define safe_strdup guestfs_safe_strdup
5701 #define safe_memdup guestfs_safe_memdup
5702
5703 /* Check the return message from a call for validity. */
5704 static int
5705 check_reply_header (guestfs_h *g,
5706                     const struct guestfs_message_header *hdr,
5707                     unsigned int proc_nr, unsigned int serial)
5708 {
5709   if (hdr->prog != GUESTFS_PROGRAM) {
5710     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5711     return -1;
5712   }
5713   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5714     error (g, \"wrong protocol version (%%d/%%d)\",
5715            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5716     return -1;
5717   }
5718   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5719     error (g, \"unexpected message direction (%%d/%%d)\",
5720            hdr->direction, GUESTFS_DIRECTION_REPLY);
5721     return -1;
5722   }
5723   if (hdr->proc != proc_nr) {
5724     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5725     return -1;
5726   }
5727   if (hdr->serial != serial) {
5728     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5729     return -1;
5730   }
5731
5732   return 0;
5733 }
5734
5735 /* Check we are in the right state to run a high-level action. */
5736 static int
5737 check_state (guestfs_h *g, const char *caller)
5738 {
5739   if (!guestfs__is_ready (g)) {
5740     if (guestfs__is_config (g) || guestfs__is_launching (g))
5741       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5742         caller);
5743     else
5744       error (g, \"%%s called from the wrong state, %%d != READY\",
5745         caller, guestfs__get_state (g));
5746     return -1;
5747   }
5748   return 0;
5749 }
5750
5751 ";
5752
5753   (* Generate code to generate guestfish call traces. *)
5754   let trace_call shortname style =
5755     pr "  if (guestfs__get_trace (g)) {\n";
5756
5757     let needs_i =
5758       List.exists (function
5759                    | StringList _ | DeviceList _ -> true
5760                    | _ -> false) (snd style) in
5761     if needs_i then (
5762       pr "    int i;\n";
5763       pr "\n"
5764     );
5765
5766     pr "    printf (\"%s\");\n" shortname;
5767     List.iter (
5768       function
5769       | String n                        (* strings *)
5770       | Device n
5771       | Pathname n
5772       | Dev_or_Path n
5773       | FileIn n
5774       | FileOut n ->
5775           (* guestfish doesn't support string escaping, so neither do we *)
5776           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5777       | OptString n ->                  (* string option *)
5778           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5779           pr "    else printf (\" null\");\n"
5780       | StringList n
5781       | DeviceList n ->                 (* string list *)
5782           pr "    putchar (' ');\n";
5783           pr "    putchar ('\"');\n";
5784           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5785           pr "      if (i > 0) putchar (' ');\n";
5786           pr "      fputs (%s[i], stdout);\n" n;
5787           pr "    }\n";
5788           pr "    putchar ('\"');\n";
5789       | Bool n ->                       (* boolean *)
5790           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5791       | Int n ->                        (* int *)
5792           pr "    printf (\" %%d\", %s);\n" n
5793       | Int64 n ->
5794           pr "    printf (\" %%\" PRIi64, %s);\n" n
5795     ) (snd style);
5796     pr "    putchar ('\\n');\n";
5797     pr "  }\n";
5798     pr "\n";
5799   in
5800
5801   (* For non-daemon functions, generate a wrapper around each function. *)
5802   List.iter (
5803     fun (shortname, style, _, _, _, _, _) ->
5804       let name = "guestfs_" ^ shortname in
5805
5806       generate_prototype ~extern:false ~semicolon:false ~newline:true
5807         ~handle:"g" name style;
5808       pr "{\n";
5809       trace_call shortname style;
5810       pr "  return guestfs__%s " shortname;
5811       generate_c_call_args ~handle:"g" style;
5812       pr ";\n";
5813       pr "}\n";
5814       pr "\n"
5815   ) non_daemon_functions;
5816
5817   (* Client-side stubs for each function. *)
5818   List.iter (
5819     fun (shortname, style, _, _, _, _, _) ->
5820       let name = "guestfs_" ^ shortname in
5821
5822       (* Generate the action stub. *)
5823       generate_prototype ~extern:false ~semicolon:false ~newline:true
5824         ~handle:"g" name style;
5825
5826       let error_code =
5827         match fst style with
5828         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5829         | RConstString _ | RConstOptString _ ->
5830             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5831         | RString _ | RStringList _
5832         | RStruct _ | RStructList _
5833         | RHashtable _ | RBufferOut _ ->
5834             "NULL" in
5835
5836       pr "{\n";
5837
5838       (match snd style with
5839        | [] -> ()
5840        | _ -> pr "  struct %s_args args;\n" name
5841       );
5842
5843       pr "  guestfs_message_header hdr;\n";
5844       pr "  guestfs_message_error err;\n";
5845       let has_ret =
5846         match fst style with
5847         | RErr -> false
5848         | RConstString _ | RConstOptString _ ->
5849             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5850         | RInt _ | RInt64 _
5851         | RBool _ | RString _ | RStringList _
5852         | RStruct _ | RStructList _
5853         | RHashtable _ | RBufferOut _ ->
5854             pr "  struct %s_ret ret;\n" name;
5855             true in
5856
5857       pr "  int serial;\n";
5858       pr "  int r;\n";
5859       pr "\n";
5860       trace_call shortname style;
5861       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5862         shortname error_code;
5863       pr "  guestfs___set_busy (g);\n";
5864       pr "\n";
5865
5866       (* Send the main header and arguments. *)
5867       (match snd style with
5868        | [] ->
5869            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5870              (String.uppercase shortname)
5871        | args ->
5872            List.iter (
5873              function
5874              | Pathname n | Device n | Dev_or_Path n | String n ->
5875                  pr "  args.%s = (char *) %s;\n" n n
5876              | OptString n ->
5877                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5878              | StringList n | DeviceList n ->
5879                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5880                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5881              | Bool n ->
5882                  pr "  args.%s = %s;\n" n n
5883              | Int n ->
5884                  pr "  args.%s = %s;\n" n n
5885              | Int64 n ->
5886                  pr "  args.%s = %s;\n" n n
5887              | FileIn _ | FileOut _ -> ()
5888            ) args;
5889            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5890              (String.uppercase shortname);
5891            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5892              name;
5893       );
5894       pr "  if (serial == -1) {\n";
5895       pr "    guestfs___end_busy (g);\n";
5896       pr "    return %s;\n" error_code;
5897       pr "  }\n";
5898       pr "\n";
5899
5900       (* Send any additional files (FileIn) requested. *)
5901       let need_read_reply_label = ref false in
5902       List.iter (
5903         function
5904         | FileIn n ->
5905             pr "  r = guestfs___send_file (g, %s);\n" n;
5906             pr "  if (r == -1) {\n";
5907             pr "    guestfs___end_busy (g);\n";
5908             pr "    return %s;\n" error_code;
5909             pr "  }\n";
5910             pr "  if (r == -2) /* daemon cancelled */\n";
5911             pr "    goto read_reply;\n";
5912             need_read_reply_label := true;
5913             pr "\n";
5914         | _ -> ()
5915       ) (snd style);
5916
5917       (* Wait for the reply from the remote end. *)
5918       if !need_read_reply_label then pr " read_reply:\n";
5919       pr "  memset (&hdr, 0, sizeof hdr);\n";
5920       pr "  memset (&err, 0, sizeof err);\n";
5921       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5922       pr "\n";
5923       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5924       if not has_ret then
5925         pr "NULL, NULL"
5926       else
5927         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5928       pr ");\n";
5929
5930       pr "  if (r == -1) {\n";
5931       pr "    guestfs___end_busy (g);\n";
5932       pr "    return %s;\n" error_code;
5933       pr "  }\n";
5934       pr "\n";
5935
5936       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5937         (String.uppercase shortname);
5938       pr "    guestfs___end_busy (g);\n";
5939       pr "    return %s;\n" error_code;
5940       pr "  }\n";
5941       pr "\n";
5942
5943       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5944       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5945       pr "    free (err.error_message);\n";
5946       pr "    guestfs___end_busy (g);\n";
5947       pr "    return %s;\n" error_code;
5948       pr "  }\n";
5949       pr "\n";
5950
5951       (* Expecting to receive further files (FileOut)? *)
5952       List.iter (
5953         function
5954         | FileOut n ->
5955             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5956             pr "    guestfs___end_busy (g);\n";
5957             pr "    return %s;\n" error_code;
5958             pr "  }\n";
5959             pr "\n";
5960         | _ -> ()
5961       ) (snd style);
5962
5963       pr "  guestfs___end_busy (g);\n";
5964
5965       (match fst style with
5966        | RErr -> pr "  return 0;\n"
5967        | RInt n | RInt64 n | RBool n ->
5968            pr "  return ret.%s;\n" n
5969        | RConstString _ | RConstOptString _ ->
5970            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5971        | RString n ->
5972            pr "  return ret.%s; /* caller will free */\n" n
5973        | RStringList n | RHashtable n ->
5974            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5975            pr "  ret.%s.%s_val =\n" n n;
5976            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5977            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5978              n n;
5979            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5980            pr "  return ret.%s.%s_val;\n" n n
5981        | RStruct (n, _) ->
5982            pr "  /* caller will free this */\n";
5983            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5984        | RStructList (n, _) ->
5985            pr "  /* caller will free this */\n";
5986            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5987        | RBufferOut n ->
5988            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5989            pr "   * _val might be NULL here.  To make the API saner for\n";
5990            pr "   * callers, we turn this case into a unique pointer (using\n";
5991            pr "   * malloc(1)).\n";
5992            pr "   */\n";
5993            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5994            pr "    *size_r = ret.%s.%s_len;\n" n n;
5995            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5996            pr "  } else {\n";
5997            pr "    free (ret.%s.%s_val);\n" n n;
5998            pr "    char *p = safe_malloc (g, 1);\n";
5999            pr "    *size_r = ret.%s.%s_len;\n" n n;
6000            pr "    return p;\n";
6001            pr "  }\n";
6002       );
6003
6004       pr "}\n\n"
6005   ) daemon_functions;
6006
6007   (* Functions to free structures. *)
6008   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6009   pr " * structure format is identical to the XDR format.  See note in\n";
6010   pr " * generator.ml.\n";
6011   pr " */\n";
6012   pr "\n";
6013
6014   List.iter (
6015     fun (typ, _) ->
6016       pr "void\n";
6017       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6018       pr "{\n";
6019       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6020       pr "  free (x);\n";
6021       pr "}\n";
6022       pr "\n";
6023
6024       pr "void\n";
6025       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6026       pr "{\n";
6027       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6028       pr "  free (x);\n";
6029       pr "}\n";
6030       pr "\n";
6031
6032   ) structs;
6033
6034 (* Generate daemon/actions.h. *)
6035 and generate_daemon_actions_h () =
6036   generate_header CStyle GPLv2plus;
6037
6038   pr "#include \"../src/guestfs_protocol.h\"\n";
6039   pr "\n";
6040
6041   List.iter (
6042     fun (name, style, _, _, _, _, _) ->
6043       generate_prototype
6044         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6045         name style;
6046   ) daemon_functions
6047
6048 (* Generate the linker script which controls the visibility of
6049  * symbols in the public ABI and ensures no other symbols get
6050  * exported accidentally.
6051  *)
6052 and generate_linker_script () =
6053   generate_header HashStyle GPLv2plus;
6054
6055   let globals = [
6056     "guestfs_create";
6057     "guestfs_close";
6058     "guestfs_get_error_handler";
6059     "guestfs_get_out_of_memory_handler";
6060     "guestfs_last_error";
6061     "guestfs_set_error_handler";
6062     "guestfs_set_launch_done_callback";
6063     "guestfs_set_log_message_callback";
6064     "guestfs_set_out_of_memory_handler";
6065     "guestfs_set_subprocess_quit_callback";
6066
6067     (* Unofficial parts of the API: the bindings code use these
6068      * functions, so it is useful to export them.
6069      *)
6070     "guestfs_safe_calloc";
6071     "guestfs_safe_malloc";
6072   ] in
6073   let functions =
6074     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6075       all_functions in
6076   let structs =
6077     List.concat (
6078       List.map (fun (typ, _) ->
6079                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6080         structs
6081     ) in
6082   let globals = List.sort compare (globals @ functions @ structs) in
6083
6084   pr "{\n";
6085   pr "    global:\n";
6086   List.iter (pr "        %s;\n") globals;
6087   pr "\n";
6088
6089   pr "    local:\n";
6090   pr "        *;\n";
6091   pr "};\n"
6092
6093 (* Generate the server-side stubs. *)
6094 and generate_daemon_actions () =
6095   generate_header CStyle GPLv2plus;
6096
6097   pr "#include <config.h>\n";
6098   pr "\n";
6099   pr "#include <stdio.h>\n";
6100   pr "#include <stdlib.h>\n";
6101   pr "#include <string.h>\n";
6102   pr "#include <inttypes.h>\n";
6103   pr "#include <rpc/types.h>\n";
6104   pr "#include <rpc/xdr.h>\n";
6105   pr "\n";
6106   pr "#include \"daemon.h\"\n";
6107   pr "#include \"c-ctype.h\"\n";
6108   pr "#include \"../src/guestfs_protocol.h\"\n";
6109   pr "#include \"actions.h\"\n";
6110   pr "\n";
6111
6112   List.iter (
6113     fun (name, style, _, _, _, _, _) ->
6114       (* Generate server-side stubs. *)
6115       pr "static void %s_stub (XDR *xdr_in)\n" name;
6116       pr "{\n";
6117       let error_code =
6118         match fst style with
6119         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6120         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6121         | RBool _ -> pr "  int r;\n"; "-1"
6122         | RConstString _ | RConstOptString _ ->
6123             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6124         | RString _ -> pr "  char *r;\n"; "NULL"
6125         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6126         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6127         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6128         | RBufferOut _ ->
6129             pr "  size_t size = 1;\n";
6130             pr "  char *r;\n";
6131             "NULL" in
6132
6133       (match snd style with
6134        | [] -> ()
6135        | args ->
6136            pr "  struct guestfs_%s_args args;\n" name;
6137            List.iter (
6138              function
6139              | Device n | Dev_or_Path n
6140              | Pathname n
6141              | String n -> ()
6142              | OptString n -> pr "  char *%s;\n" n
6143              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6144              | Bool n -> pr "  int %s;\n" n
6145              | Int n -> pr "  int %s;\n" n
6146              | Int64 n -> pr "  int64_t %s;\n" n
6147              | FileIn _ | FileOut _ -> ()
6148            ) args
6149       );
6150       pr "\n";
6151
6152       let is_filein =
6153         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6154
6155       (match snd style with
6156        | [] -> ()
6157        | args ->
6158            pr "  memset (&args, 0, sizeof args);\n";
6159            pr "\n";
6160            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6161            if is_filein then
6162              pr "    cancel_receive ();\n";
6163            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6164            pr "    goto done;\n";
6165            pr "  }\n";
6166            let pr_args n =
6167              pr "  char *%s = args.%s;\n" n n
6168            in
6169            let pr_list_handling_code n =
6170              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6171              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6172              pr "  if (%s == NULL) {\n" n;
6173              if is_filein then
6174                pr "    cancel_receive ();\n";
6175              pr "    reply_with_perror (\"realloc\");\n";
6176              pr "    goto done;\n";
6177              pr "  }\n";
6178              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6179              pr "  args.%s.%s_val = %s;\n" n n n;
6180            in
6181            List.iter (
6182              function
6183              | Pathname n ->
6184                  pr_args n;
6185                  pr "  ABS_PATH (%s, %s, goto done);\n"
6186                    n (if is_filein then "cancel_receive ()" else "");
6187              | Device n ->
6188                  pr_args n;
6189                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6190                    n (if is_filein then "cancel_receive ()" else "");
6191              | Dev_or_Path n ->
6192                  pr_args n;
6193                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6194                    n (if is_filein then "cancel_receive ()" else "");
6195              | String n -> pr_args n
6196              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6197              | StringList n ->
6198                  pr_list_handling_code n;
6199              | DeviceList n ->
6200                  pr_list_handling_code n;
6201                  pr "  /* Ensure that each is a device,\n";
6202                  pr "   * and perform device name translation. */\n";
6203                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6204                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6205                    (if is_filein then "cancel_receive ()" else "");
6206                  pr "  }\n";
6207              | Bool n -> pr "  %s = args.%s;\n" n n
6208              | Int n -> pr "  %s = args.%s;\n" n n
6209              | Int64 n -> pr "  %s = args.%s;\n" n n
6210              | FileIn _ | FileOut _ -> ()
6211            ) args;
6212            pr "\n"
6213       );
6214
6215
6216       (* this is used at least for do_equal *)
6217       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6218         (* Emit NEED_ROOT just once, even when there are two or
6219            more Pathname args *)
6220         pr "  NEED_ROOT (%s, goto done);\n"
6221           (if is_filein then "cancel_receive ()" else "");
6222       );
6223
6224       (* Don't want to call the impl with any FileIn or FileOut
6225        * parameters, since these go "outside" the RPC protocol.
6226        *)
6227       let args' =
6228         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6229           (snd style) in
6230       pr "  r = do_%s " name;
6231       generate_c_call_args (fst style, args');
6232       pr ";\n";
6233
6234       (match fst style with
6235        | RErr | RInt _ | RInt64 _ | RBool _
6236        | RConstString _ | RConstOptString _
6237        | RString _ | RStringList _ | RHashtable _
6238        | RStruct (_, _) | RStructList (_, _) ->
6239            pr "  if (r == %s)\n" error_code;
6240            pr "    /* do_%s has already called reply_with_error */\n" name;
6241            pr "    goto done;\n";
6242            pr "\n"
6243        | RBufferOut _ ->
6244            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6245            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6246            pr "   */\n";
6247            pr "  if (size == 1 && r == %s)\n" error_code;
6248            pr "    /* do_%s has already called reply_with_error */\n" name;
6249            pr "    goto done;\n";
6250            pr "\n"
6251       );
6252
6253       (* If there are any FileOut parameters, then the impl must
6254        * send its own reply.
6255        *)
6256       let no_reply =
6257         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6258       if no_reply then
6259         pr "  /* do_%s has already sent a reply */\n" name
6260       else (
6261         match fst style with
6262         | RErr -> pr "  reply (NULL, NULL);\n"
6263         | RInt n | RInt64 n | RBool n ->
6264             pr "  struct guestfs_%s_ret ret;\n" name;
6265             pr "  ret.%s = r;\n" n;
6266             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6267               name
6268         | RConstString _ | RConstOptString _ ->
6269             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6270         | RString n ->
6271             pr "  struct guestfs_%s_ret ret;\n" name;
6272             pr "  ret.%s = r;\n" n;
6273             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6274               name;
6275             pr "  free (r);\n"
6276         | RStringList n | RHashtable n ->
6277             pr "  struct guestfs_%s_ret ret;\n" name;
6278             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6279             pr "  ret.%s.%s_val = r;\n" n n;
6280             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6281               name;
6282             pr "  free_strings (r);\n"
6283         | RStruct (n, _) ->
6284             pr "  struct guestfs_%s_ret ret;\n" name;
6285             pr "  ret.%s = *r;\n" n;
6286             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6287               name;
6288             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6289               name
6290         | RStructList (n, _) ->
6291             pr "  struct guestfs_%s_ret ret;\n" name;
6292             pr "  ret.%s = *r;\n" n;
6293             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6294               name;
6295             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6296               name
6297         | RBufferOut n ->
6298             pr "  struct guestfs_%s_ret ret;\n" name;
6299             pr "  ret.%s.%s_val = r;\n" n n;
6300             pr "  ret.%s.%s_len = size;\n" n n;
6301             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6302               name;
6303             pr "  free (r);\n"
6304       );
6305
6306       (* Free the args. *)
6307       pr "done:\n";
6308       (match snd style with
6309        | [] -> ()
6310        | _ ->
6311            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6312              name
6313       );
6314       pr "  return;\n";
6315       pr "}\n\n";
6316   ) daemon_functions;
6317
6318   (* Dispatch function. *)
6319   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6320   pr "{\n";
6321   pr "  switch (proc_nr) {\n";
6322
6323   List.iter (
6324     fun (name, style, _, _, _, _, _) ->
6325       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6326       pr "      %s_stub (xdr_in);\n" name;
6327       pr "      break;\n"
6328   ) daemon_functions;
6329
6330   pr "    default:\n";
6331   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";
6332   pr "  }\n";
6333   pr "}\n";
6334   pr "\n";
6335
6336   (* LVM columns and tokenization functions. *)
6337   (* XXX This generates crap code.  We should rethink how we
6338    * do this parsing.
6339    *)
6340   List.iter (
6341     function
6342     | typ, cols ->
6343         pr "static const char *lvm_%s_cols = \"%s\";\n"
6344           typ (String.concat "," (List.map fst cols));
6345         pr "\n";
6346
6347         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6348         pr "{\n";
6349         pr "  char *tok, *p, *next;\n";
6350         pr "  int i, j;\n";
6351         pr "\n";
6352         (*
6353           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6354           pr "\n";
6355         *)
6356         pr "  if (!str) {\n";
6357         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6358         pr "    return -1;\n";
6359         pr "  }\n";
6360         pr "  if (!*str || c_isspace (*str)) {\n";
6361         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6362         pr "    return -1;\n";
6363         pr "  }\n";
6364         pr "  tok = str;\n";
6365         List.iter (
6366           fun (name, coltype) ->
6367             pr "  if (!tok) {\n";
6368             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6369             pr "    return -1;\n";
6370             pr "  }\n";
6371             pr "  p = strchrnul (tok, ',');\n";
6372             pr "  if (*p) next = p+1; else next = NULL;\n";
6373             pr "  *p = '\\0';\n";
6374             (match coltype with
6375              | FString ->
6376                  pr "  r->%s = strdup (tok);\n" name;
6377                  pr "  if (r->%s == NULL) {\n" name;
6378                  pr "    perror (\"strdup\");\n";
6379                  pr "    return -1;\n";
6380                  pr "  }\n"
6381              | FUUID ->
6382                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6383                  pr "    if (tok[j] == '\\0') {\n";
6384                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6385                  pr "      return -1;\n";
6386                  pr "    } else if (tok[j] != '-')\n";
6387                  pr "      r->%s[i++] = tok[j];\n" name;
6388                  pr "  }\n";
6389              | FBytes ->
6390                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6391                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6392                  pr "    return -1;\n";
6393                  pr "  }\n";
6394              | FInt64 ->
6395                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6396                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6397                  pr "    return -1;\n";
6398                  pr "  }\n";
6399              | FOptPercent ->
6400                  pr "  if (tok[0] == '\\0')\n";
6401                  pr "    r->%s = -1;\n" name;
6402                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6403                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6404                  pr "    return -1;\n";
6405                  pr "  }\n";
6406              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6407                  assert false (* can never be an LVM column *)
6408             );
6409             pr "  tok = next;\n";
6410         ) cols;
6411
6412         pr "  if (tok != NULL) {\n";
6413         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6414         pr "    return -1;\n";
6415         pr "  }\n";
6416         pr "  return 0;\n";
6417         pr "}\n";
6418         pr "\n";
6419
6420         pr "guestfs_int_lvm_%s_list *\n" typ;
6421         pr "parse_command_line_%ss (void)\n" typ;
6422         pr "{\n";
6423         pr "  char *out, *err;\n";
6424         pr "  char *p, *pend;\n";
6425         pr "  int r, i;\n";
6426         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6427         pr "  void *newp;\n";
6428         pr "\n";
6429         pr "  ret = malloc (sizeof *ret);\n";
6430         pr "  if (!ret) {\n";
6431         pr "    reply_with_perror (\"malloc\");\n";
6432         pr "    return NULL;\n";
6433         pr "  }\n";
6434         pr "\n";
6435         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6436         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6437         pr "\n";
6438         pr "  r = command (&out, &err,\n";
6439         pr "           \"lvm\", \"%ss\",\n" typ;
6440         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6441         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6442         pr "  if (r == -1) {\n";
6443         pr "    reply_with_error (\"%%s\", err);\n";
6444         pr "    free (out);\n";
6445         pr "    free (err);\n";
6446         pr "    free (ret);\n";
6447         pr "    return NULL;\n";
6448         pr "  }\n";
6449         pr "\n";
6450         pr "  free (err);\n";
6451         pr "\n";
6452         pr "  /* Tokenize each line of the output. */\n";
6453         pr "  p = out;\n";
6454         pr "  i = 0;\n";
6455         pr "  while (p) {\n";
6456         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6457         pr "    if (pend) {\n";
6458         pr "      *pend = '\\0';\n";
6459         pr "      pend++;\n";
6460         pr "    }\n";
6461         pr "\n";
6462         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6463         pr "      p++;\n";
6464         pr "\n";
6465         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6466         pr "      p = pend;\n";
6467         pr "      continue;\n";
6468         pr "    }\n";
6469         pr "\n";
6470         pr "    /* Allocate some space to store this next entry. */\n";
6471         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6472         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6473         pr "    if (newp == NULL) {\n";
6474         pr "      reply_with_perror (\"realloc\");\n";
6475         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6476         pr "      free (ret);\n";
6477         pr "      free (out);\n";
6478         pr "      return NULL;\n";
6479         pr "    }\n";
6480         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6481         pr "\n";
6482         pr "    /* Tokenize the next entry. */\n";
6483         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6484         pr "    if (r == -1) {\n";
6485         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6486         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6487         pr "      free (ret);\n";
6488         pr "      free (out);\n";
6489         pr "      return NULL;\n";
6490         pr "    }\n";
6491         pr "\n";
6492         pr "    ++i;\n";
6493         pr "    p = pend;\n";
6494         pr "  }\n";
6495         pr "\n";
6496         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6497         pr "\n";
6498         pr "  free (out);\n";
6499         pr "  return ret;\n";
6500         pr "}\n"
6501
6502   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6503
6504 (* Generate a list of function names, for debugging in the daemon.. *)
6505 and generate_daemon_names () =
6506   generate_header CStyle GPLv2plus;
6507
6508   pr "#include <config.h>\n";
6509   pr "\n";
6510   pr "#include \"daemon.h\"\n";
6511   pr "\n";
6512
6513   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6514   pr "const char *function_names[] = {\n";
6515   List.iter (
6516     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6517   ) daemon_functions;
6518   pr "};\n";
6519
6520 (* Generate the optional groups for the daemon to implement
6521  * guestfs_available.
6522  *)
6523 and generate_daemon_optgroups_c () =
6524   generate_header CStyle GPLv2plus;
6525
6526   pr "#include <config.h>\n";
6527   pr "\n";
6528   pr "#include \"daemon.h\"\n";
6529   pr "#include \"optgroups.h\"\n";
6530   pr "\n";
6531
6532   pr "struct optgroup optgroups[] = {\n";
6533   List.iter (
6534     fun (group, _) ->
6535       pr "  { \"%s\", optgroup_%s_available },\n" group group
6536   ) optgroups;
6537   pr "  { NULL, NULL }\n";
6538   pr "};\n"
6539
6540 and generate_daemon_optgroups_h () =
6541   generate_header CStyle GPLv2plus;
6542
6543   List.iter (
6544     fun (group, _) ->
6545       pr "extern int optgroup_%s_available (void);\n" group
6546   ) optgroups
6547
6548 (* Generate the tests. *)
6549 and generate_tests () =
6550   generate_header CStyle GPLv2plus;
6551
6552   pr "\
6553 #include <stdio.h>
6554 #include <stdlib.h>
6555 #include <string.h>
6556 #include <unistd.h>
6557 #include <sys/types.h>
6558 #include <fcntl.h>
6559
6560 #include \"guestfs.h\"
6561 #include \"guestfs-internal.h\"
6562
6563 static guestfs_h *g;
6564 static int suppress_error = 0;
6565
6566 static void print_error (guestfs_h *g, void *data, const char *msg)
6567 {
6568   if (!suppress_error)
6569     fprintf (stderr, \"%%s\\n\", msg);
6570 }
6571
6572 /* FIXME: nearly identical code appears in fish.c */
6573 static void print_strings (char *const *argv)
6574 {
6575   int argc;
6576
6577   for (argc = 0; argv[argc] != NULL; ++argc)
6578     printf (\"\\t%%s\\n\", argv[argc]);
6579 }
6580
6581 /*
6582 static void print_table (char const *const *argv)
6583 {
6584   int i;
6585
6586   for (i = 0; argv[i] != NULL; i += 2)
6587     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6588 }
6589 */
6590
6591 ";
6592
6593   (* Generate a list of commands which are not tested anywhere. *)
6594   pr "static void no_test_warnings (void)\n";
6595   pr "{\n";
6596
6597   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6598   List.iter (
6599     fun (_, _, _, _, tests, _, _) ->
6600       let tests = filter_map (
6601         function
6602         | (_, (Always|If _|Unless _), test) -> Some test
6603         | (_, Disabled, _) -> None
6604       ) tests in
6605       let seq = List.concat (List.map seq_of_test tests) in
6606       let cmds_tested = List.map List.hd seq in
6607       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6608   ) all_functions;
6609
6610   List.iter (
6611     fun (name, _, _, _, _, _, _) ->
6612       if not (Hashtbl.mem hash name) then
6613         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6614   ) all_functions;
6615
6616   pr "}\n";
6617   pr "\n";
6618
6619   (* Generate the actual tests.  Note that we generate the tests
6620    * in reverse order, deliberately, so that (in general) the
6621    * newest tests run first.  This makes it quicker and easier to
6622    * debug them.
6623    *)
6624   let test_names =
6625     List.map (
6626       fun (name, _, _, flags, tests, _, _) ->
6627         mapi (generate_one_test name flags) tests
6628     ) (List.rev all_functions) in
6629   let test_names = List.concat test_names in
6630   let nr_tests = List.length test_names in
6631
6632   pr "\
6633 int main (int argc, char *argv[])
6634 {
6635   char c = 0;
6636   unsigned long int n_failed = 0;
6637   const char *filename;
6638   int fd;
6639   int nr_tests, test_num = 0;
6640
6641   setbuf (stdout, NULL);
6642
6643   no_test_warnings ();
6644
6645   g = guestfs_create ();
6646   if (g == NULL) {
6647     printf (\"guestfs_create FAILED\\n\");
6648     exit (EXIT_FAILURE);
6649   }
6650
6651   guestfs_set_error_handler (g, print_error, NULL);
6652
6653   guestfs_set_path (g, \"../appliance\");
6654
6655   filename = \"test1.img\";
6656   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6657   if (fd == -1) {
6658     perror (filename);
6659     exit (EXIT_FAILURE);
6660   }
6661   if (lseek (fd, %d, SEEK_SET) == -1) {
6662     perror (\"lseek\");
6663     close (fd);
6664     unlink (filename);
6665     exit (EXIT_FAILURE);
6666   }
6667   if (write (fd, &c, 1) == -1) {
6668     perror (\"write\");
6669     close (fd);
6670     unlink (filename);
6671     exit (EXIT_FAILURE);
6672   }
6673   if (close (fd) == -1) {
6674     perror (filename);
6675     unlink (filename);
6676     exit (EXIT_FAILURE);
6677   }
6678   if (guestfs_add_drive (g, filename) == -1) {
6679     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6680     exit (EXIT_FAILURE);
6681   }
6682
6683   filename = \"test2.img\";
6684   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6685   if (fd == -1) {
6686     perror (filename);
6687     exit (EXIT_FAILURE);
6688   }
6689   if (lseek (fd, %d, SEEK_SET) == -1) {
6690     perror (\"lseek\");
6691     close (fd);
6692     unlink (filename);
6693     exit (EXIT_FAILURE);
6694   }
6695   if (write (fd, &c, 1) == -1) {
6696     perror (\"write\");
6697     close (fd);
6698     unlink (filename);
6699     exit (EXIT_FAILURE);
6700   }
6701   if (close (fd) == -1) {
6702     perror (filename);
6703     unlink (filename);
6704     exit (EXIT_FAILURE);
6705   }
6706   if (guestfs_add_drive (g, filename) == -1) {
6707     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6708     exit (EXIT_FAILURE);
6709   }
6710
6711   filename = \"test3.img\";
6712   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6713   if (fd == -1) {
6714     perror (filename);
6715     exit (EXIT_FAILURE);
6716   }
6717   if (lseek (fd, %d, SEEK_SET) == -1) {
6718     perror (\"lseek\");
6719     close (fd);
6720     unlink (filename);
6721     exit (EXIT_FAILURE);
6722   }
6723   if (write (fd, &c, 1) == -1) {
6724     perror (\"write\");
6725     close (fd);
6726     unlink (filename);
6727     exit (EXIT_FAILURE);
6728   }
6729   if (close (fd) == -1) {
6730     perror (filename);
6731     unlink (filename);
6732     exit (EXIT_FAILURE);
6733   }
6734   if (guestfs_add_drive (g, filename) == -1) {
6735     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6736     exit (EXIT_FAILURE);
6737   }
6738
6739   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6740     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6741     exit (EXIT_FAILURE);
6742   }
6743
6744   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6745   alarm (600);
6746
6747   if (guestfs_launch (g) == -1) {
6748     printf (\"guestfs_launch FAILED\\n\");
6749     exit (EXIT_FAILURE);
6750   }
6751
6752   /* Cancel previous alarm. */
6753   alarm (0);
6754
6755   nr_tests = %d;
6756
6757 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6758
6759   iteri (
6760     fun i test_name ->
6761       pr "  test_num++;\n";
6762       pr "  if (guestfs_get_verbose (g))\n";
6763       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6764       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6765       pr "  if (%s () == -1) {\n" test_name;
6766       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6767       pr "    n_failed++;\n";
6768       pr "  }\n";
6769   ) test_names;
6770   pr "\n";
6771
6772   pr "  guestfs_close (g);\n";
6773   pr "  unlink (\"test1.img\");\n";
6774   pr "  unlink (\"test2.img\");\n";
6775   pr "  unlink (\"test3.img\");\n";
6776   pr "\n";
6777
6778   pr "  if (n_failed > 0) {\n";
6779   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6780   pr "    exit (EXIT_FAILURE);\n";
6781   pr "  }\n";
6782   pr "\n";
6783
6784   pr "  exit (EXIT_SUCCESS);\n";
6785   pr "}\n"
6786
6787 and generate_one_test name flags i (init, prereq, test) =
6788   let test_name = sprintf "test_%s_%d" name i in
6789
6790   pr "\
6791 static int %s_skip (void)
6792 {
6793   const char *str;
6794
6795   str = getenv (\"TEST_ONLY\");
6796   if (str)
6797     return strstr (str, \"%s\") == NULL;
6798   str = getenv (\"SKIP_%s\");
6799   if (str && STREQ (str, \"1\")) return 1;
6800   str = getenv (\"SKIP_TEST_%s\");
6801   if (str && STREQ (str, \"1\")) return 1;
6802   return 0;
6803 }
6804
6805 " test_name name (String.uppercase test_name) (String.uppercase name);
6806
6807   (match prereq with
6808    | Disabled | Always -> ()
6809    | If code | Unless code ->
6810        pr "static int %s_prereq (void)\n" test_name;
6811        pr "{\n";
6812        pr "  %s\n" code;
6813        pr "}\n";
6814        pr "\n";
6815   );
6816
6817   pr "\
6818 static int %s (void)
6819 {
6820   if (%s_skip ()) {
6821     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6822     return 0;
6823   }
6824
6825 " test_name test_name test_name;
6826
6827   (* Optional functions should only be tested if the relevant
6828    * support is available in the daemon.
6829    *)
6830   List.iter (
6831     function
6832     | Optional group ->
6833         pr "  {\n";
6834         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6835         pr "    int r;\n";
6836         pr "    suppress_error = 1;\n";
6837         pr "    r = guestfs_available (g, (char **) groups);\n";
6838         pr "    suppress_error = 0;\n";
6839         pr "    if (r == -1) {\n";
6840         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6841         pr "      return 0;\n";
6842         pr "    }\n";
6843         pr "  }\n";
6844     | _ -> ()
6845   ) flags;
6846
6847   (match prereq with
6848    | Disabled ->
6849        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6850    | If _ ->
6851        pr "  if (! %s_prereq ()) {\n" test_name;
6852        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6853        pr "    return 0;\n";
6854        pr "  }\n";
6855        pr "\n";
6856        generate_one_test_body name i test_name init test;
6857    | Unless _ ->
6858        pr "  if (%s_prereq ()) {\n" test_name;
6859        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6860        pr "    return 0;\n";
6861        pr "  }\n";
6862        pr "\n";
6863        generate_one_test_body name i test_name init test;
6864    | Always ->
6865        generate_one_test_body name i test_name init test
6866   );
6867
6868   pr "  return 0;\n";
6869   pr "}\n";
6870   pr "\n";
6871   test_name
6872
6873 and generate_one_test_body name i test_name init test =
6874   (match init with
6875    | InitNone (* XXX at some point, InitNone and InitEmpty became
6876                * folded together as the same thing.  Really we should
6877                * make InitNone do nothing at all, but the tests may
6878                * need to be checked to make sure this is OK.
6879                *)
6880    | InitEmpty ->
6881        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6882        List.iter (generate_test_command_call test_name)
6883          [["blockdev_setrw"; "/dev/sda"];
6884           ["umount_all"];
6885           ["lvm_remove_all"]]
6886    | InitPartition ->
6887        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6888        List.iter (generate_test_command_call test_name)
6889          [["blockdev_setrw"; "/dev/sda"];
6890           ["umount_all"];
6891           ["lvm_remove_all"];
6892           ["part_disk"; "/dev/sda"; "mbr"]]
6893    | InitBasicFS ->
6894        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6895        List.iter (generate_test_command_call test_name)
6896          [["blockdev_setrw"; "/dev/sda"];
6897           ["umount_all"];
6898           ["lvm_remove_all"];
6899           ["part_disk"; "/dev/sda"; "mbr"];
6900           ["mkfs"; "ext2"; "/dev/sda1"];
6901           ["mount_options"; ""; "/dev/sda1"; "/"]]
6902    | InitBasicFSonLVM ->
6903        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6904          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           ["pvcreate"; "/dev/sda1"];
6911           ["vgcreate"; "VG"; "/dev/sda1"];
6912           ["lvcreate"; "LV"; "VG"; "8"];
6913           ["mkfs"; "ext2"; "/dev/VG/LV"];
6914           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6915    | InitISOFS ->
6916        pr "  /* InitISOFS for %s */\n" test_name;
6917        List.iter (generate_test_command_call test_name)
6918          [["blockdev_setrw"; "/dev/sda"];
6919           ["umount_all"];
6920           ["lvm_remove_all"];
6921           ["mount_ro"; "/dev/sdd"; "/"]]
6922   );
6923
6924   let get_seq_last = function
6925     | [] ->
6926         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6927           test_name
6928     | seq ->
6929         let seq = List.rev seq in
6930         List.rev (List.tl seq), List.hd seq
6931   in
6932
6933   match test with
6934   | TestRun seq ->
6935       pr "  /* TestRun for %s (%d) */\n" name i;
6936       List.iter (generate_test_command_call test_name) seq
6937   | TestOutput (seq, expected) ->
6938       pr "  /* TestOutput for %s (%d) */\n" name i;
6939       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6940       let seq, last = get_seq_last seq in
6941       let test () =
6942         pr "    if (STRNEQ (r, expected)) {\n";
6943         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6944         pr "      return -1;\n";
6945         pr "    }\n"
6946       in
6947       List.iter (generate_test_command_call test_name) seq;
6948       generate_test_command_call ~test test_name last
6949   | TestOutputList (seq, expected) ->
6950       pr "  /* TestOutputList for %s (%d) */\n" name i;
6951       let seq, last = get_seq_last seq in
6952       let test () =
6953         iteri (
6954           fun i str ->
6955             pr "    if (!r[%d]) {\n" i;
6956             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6957             pr "      print_strings (r);\n";
6958             pr "      return -1;\n";
6959             pr "    }\n";
6960             pr "    {\n";
6961             pr "      const char *expected = \"%s\";\n" (c_quote str);
6962             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6963             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6964             pr "        return -1;\n";
6965             pr "      }\n";
6966             pr "    }\n"
6967         ) expected;
6968         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6969         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6970           test_name;
6971         pr "      print_strings (r);\n";
6972         pr "      return -1;\n";
6973         pr "    }\n"
6974       in
6975       List.iter (generate_test_command_call test_name) seq;
6976       generate_test_command_call ~test test_name last
6977   | TestOutputListOfDevices (seq, expected) ->
6978       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6979       let seq, last = get_seq_last seq in
6980       let test () =
6981         iteri (
6982           fun i str ->
6983             pr "    if (!r[%d]) {\n" i;
6984             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6985             pr "      print_strings (r);\n";
6986             pr "      return -1;\n";
6987             pr "    }\n";
6988             pr "    {\n";
6989             pr "      const char *expected = \"%s\";\n" (c_quote str);
6990             pr "      r[%d][5] = 's';\n" i;
6991             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6992             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6993             pr "        return -1;\n";
6994             pr "      }\n";
6995             pr "    }\n"
6996         ) expected;
6997         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6998         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6999           test_name;
7000         pr "      print_strings (r);\n";
7001         pr "      return -1;\n";
7002         pr "    }\n"
7003       in
7004       List.iter (generate_test_command_call test_name) seq;
7005       generate_test_command_call ~test test_name last
7006   | TestOutputInt (seq, expected) ->
7007       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7008       let seq, last = get_seq_last seq in
7009       let test () =
7010         pr "    if (r != %d) {\n" expected;
7011         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7012           test_name expected;
7013         pr "               (int) r);\n";
7014         pr "      return -1;\n";
7015         pr "    }\n"
7016       in
7017       List.iter (generate_test_command_call test_name) seq;
7018       generate_test_command_call ~test test_name last
7019   | TestOutputIntOp (seq, op, expected) ->
7020       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7021       let seq, last = get_seq_last seq in
7022       let test () =
7023         pr "    if (! (r %s %d)) {\n" op expected;
7024         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7025           test_name op expected;
7026         pr "               (int) r);\n";
7027         pr "      return -1;\n";
7028         pr "    }\n"
7029       in
7030       List.iter (generate_test_command_call test_name) seq;
7031       generate_test_command_call ~test test_name last
7032   | TestOutputTrue seq ->
7033       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7034       let seq, last = get_seq_last seq in
7035       let test () =
7036         pr "    if (!r) {\n";
7037         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7038           test_name;
7039         pr "      return -1;\n";
7040         pr "    }\n"
7041       in
7042       List.iter (generate_test_command_call test_name) seq;
7043       generate_test_command_call ~test test_name last
7044   | TestOutputFalse seq ->
7045       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7046       let seq, last = get_seq_last seq in
7047       let test () =
7048         pr "    if (r) {\n";
7049         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7050           test_name;
7051         pr "      return -1;\n";
7052         pr "    }\n"
7053       in
7054       List.iter (generate_test_command_call test_name) seq;
7055       generate_test_command_call ~test test_name last
7056   | TestOutputLength (seq, expected) ->
7057       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7058       let seq, last = get_seq_last seq in
7059       let test () =
7060         pr "    int j;\n";
7061         pr "    for (j = 0; j < %d; ++j)\n" expected;
7062         pr "      if (r[j] == NULL) {\n";
7063         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7064           test_name;
7065         pr "        print_strings (r);\n";
7066         pr "        return -1;\n";
7067         pr "      }\n";
7068         pr "    if (r[j] != NULL) {\n";
7069         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7070           test_name;
7071         pr "      print_strings (r);\n";
7072         pr "      return -1;\n";
7073         pr "    }\n"
7074       in
7075       List.iter (generate_test_command_call test_name) seq;
7076       generate_test_command_call ~test test_name last
7077   | TestOutputBuffer (seq, expected) ->
7078       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7079       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7080       let seq, last = get_seq_last seq in
7081       let len = String.length expected in
7082       let test () =
7083         pr "    if (size != %d) {\n" len;
7084         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7085         pr "      return -1;\n";
7086         pr "    }\n";
7087         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7088         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7089         pr "      return -1;\n";
7090         pr "    }\n"
7091       in
7092       List.iter (generate_test_command_call test_name) seq;
7093       generate_test_command_call ~test test_name last
7094   | TestOutputStruct (seq, checks) ->
7095       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7096       let seq, last = get_seq_last seq in
7097       let test () =
7098         List.iter (
7099           function
7100           | CompareWithInt (field, expected) ->
7101               pr "    if (r->%s != %d) {\n" field expected;
7102               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7103                 test_name field expected;
7104               pr "               (int) r->%s);\n" field;
7105               pr "      return -1;\n";
7106               pr "    }\n"
7107           | CompareWithIntOp (field, op, expected) ->
7108               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7109               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7110                 test_name field op expected;
7111               pr "               (int) r->%s);\n" field;
7112               pr "      return -1;\n";
7113               pr "    }\n"
7114           | CompareWithString (field, expected) ->
7115               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7116               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7117                 test_name field expected;
7118               pr "               r->%s);\n" field;
7119               pr "      return -1;\n";
7120               pr "    }\n"
7121           | CompareFieldsIntEq (field1, field2) ->
7122               pr "    if (r->%s != r->%s) {\n" field1 field2;
7123               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7124                 test_name field1 field2;
7125               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7126               pr "      return -1;\n";
7127               pr "    }\n"
7128           | CompareFieldsStrEq (field1, field2) ->
7129               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7130               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7131                 test_name field1 field2;
7132               pr "               r->%s, r->%s);\n" field1 field2;
7133               pr "      return -1;\n";
7134               pr "    }\n"
7135         ) checks
7136       in
7137       List.iter (generate_test_command_call test_name) seq;
7138       generate_test_command_call ~test test_name last
7139   | TestLastFail seq ->
7140       pr "  /* TestLastFail for %s (%d) */\n" name i;
7141       let seq, last = get_seq_last seq in
7142       List.iter (generate_test_command_call test_name) seq;
7143       generate_test_command_call test_name ~expect_error:true last
7144
7145 (* Generate the code to run a command, leaving the result in 'r'.
7146  * If you expect to get an error then you should set expect_error:true.
7147  *)
7148 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7149   match cmd with
7150   | [] -> assert false
7151   | name :: args ->
7152       (* Look up the command to find out what args/ret it has. *)
7153       let style =
7154         try
7155           let _, style, _, _, _, _, _ =
7156             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7157           style
7158         with Not_found ->
7159           failwithf "%s: in test, command %s was not found" test_name name in
7160
7161       if List.length (snd style) <> List.length args then
7162         failwithf "%s: in test, wrong number of args given to %s"
7163           test_name name;
7164
7165       pr "  {\n";
7166
7167       List.iter (
7168         function
7169         | OptString n, "NULL" -> ()
7170         | Pathname n, arg
7171         | Device n, arg
7172         | Dev_or_Path n, arg
7173         | String n, arg
7174         | OptString n, arg ->
7175             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7176         | Int _, _
7177         | Int64 _, _
7178         | Bool _, _
7179         | FileIn _, _ | FileOut _, _ -> ()
7180         | StringList n, "" | DeviceList n, "" ->
7181             pr "    const char *const %s[1] = { NULL };\n" n
7182         | StringList n, arg | DeviceList n, arg ->
7183             let strs = string_split " " arg in
7184             iteri (
7185               fun i str ->
7186                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7187             ) strs;
7188             pr "    const char *const %s[] = {\n" n;
7189             iteri (
7190               fun i _ -> pr "      %s_%d,\n" n i
7191             ) strs;
7192             pr "      NULL\n";
7193             pr "    };\n";
7194       ) (List.combine (snd style) args);
7195
7196       let error_code =
7197         match fst style with
7198         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7199         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7200         | RConstString _ | RConstOptString _ ->
7201             pr "    const char *r;\n"; "NULL"
7202         | RString _ -> pr "    char *r;\n"; "NULL"
7203         | RStringList _ | RHashtable _ ->
7204             pr "    char **r;\n";
7205             pr "    int i;\n";
7206             "NULL"
7207         | RStruct (_, typ) ->
7208             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7209         | RStructList (_, typ) ->
7210             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7211         | RBufferOut _ ->
7212             pr "    char *r;\n";
7213             pr "    size_t size;\n";
7214             "NULL" in
7215
7216       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7217       pr "    r = guestfs_%s (g" name;
7218
7219       (* Generate the parameters. *)
7220       List.iter (
7221         function
7222         | OptString _, "NULL" -> pr ", NULL"
7223         | Pathname n, _
7224         | Device n, _ | Dev_or_Path n, _
7225         | String n, _
7226         | OptString n, _ ->
7227             pr ", %s" n
7228         | FileIn _, arg | FileOut _, arg ->
7229             pr ", \"%s\"" (c_quote arg)
7230         | StringList n, _ | DeviceList n, _ ->
7231             pr ", (char **) %s" n
7232         | Int _, arg ->
7233             let i =
7234               try int_of_string arg
7235               with Failure "int_of_string" ->
7236                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7237             pr ", %d" i
7238         | Int64 _, arg ->
7239             let i =
7240               try Int64.of_string arg
7241               with Failure "int_of_string" ->
7242                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7243             pr ", %Ld" i
7244         | Bool _, arg ->
7245             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7246       ) (List.combine (snd style) args);
7247
7248       (match fst style with
7249        | RBufferOut _ -> pr ", &size"
7250        | _ -> ()
7251       );
7252
7253       pr ");\n";
7254
7255       if not expect_error then
7256         pr "    if (r == %s)\n" error_code
7257       else
7258         pr "    if (r != %s)\n" error_code;
7259       pr "      return -1;\n";
7260
7261       (* Insert the test code. *)
7262       (match test with
7263        | None -> ()
7264        | Some f -> f ()
7265       );
7266
7267       (match fst style with
7268        | RErr | RInt _ | RInt64 _ | RBool _
7269        | RConstString _ | RConstOptString _ -> ()
7270        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7271        | RStringList _ | RHashtable _ ->
7272            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7273            pr "      free (r[i]);\n";
7274            pr "    free (r);\n"
7275        | RStruct (_, typ) ->
7276            pr "    guestfs_free_%s (r);\n" typ
7277        | RStructList (_, typ) ->
7278            pr "    guestfs_free_%s_list (r);\n" typ
7279       );
7280
7281       pr "  }\n"
7282
7283 and c_quote str =
7284   let str = replace_str str "\r" "\\r" in
7285   let str = replace_str str "\n" "\\n" in
7286   let str = replace_str str "\t" "\\t" in
7287   let str = replace_str str "\000" "\\0" in
7288   str
7289
7290 (* Generate a lot of different functions for guestfish. *)
7291 and generate_fish_cmds () =
7292   generate_header CStyle GPLv2plus;
7293
7294   let all_functions =
7295     List.filter (
7296       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7297     ) all_functions in
7298   let all_functions_sorted =
7299     List.filter (
7300       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7301     ) all_functions_sorted in
7302
7303   pr "#include <config.h>\n";
7304   pr "\n";
7305   pr "#include <stdio.h>\n";
7306   pr "#include <stdlib.h>\n";
7307   pr "#include <string.h>\n";
7308   pr "#include <inttypes.h>\n";
7309   pr "\n";
7310   pr "#include <guestfs.h>\n";
7311   pr "#include \"c-ctype.h\"\n";
7312   pr "#include \"full-write.h\"\n";
7313   pr "#include \"xstrtol.h\"\n";
7314   pr "#include \"fish.h\"\n";
7315   pr "\n";
7316
7317   (* list_commands function, which implements guestfish -h *)
7318   pr "void list_commands (void)\n";
7319   pr "{\n";
7320   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7321   pr "  list_builtin_commands ();\n";
7322   List.iter (
7323     fun (name, _, _, flags, _, shortdesc, _) ->
7324       let name = replace_char name '_' '-' in
7325       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7326         name shortdesc
7327   ) all_functions_sorted;
7328   pr "  printf (\"    %%s\\n\",";
7329   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7330   pr "}\n";
7331   pr "\n";
7332
7333   (* display_command function, which implements guestfish -h cmd *)
7334   pr "void display_command (const char *cmd)\n";
7335   pr "{\n";
7336   List.iter (
7337     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7338       let name2 = replace_char name '_' '-' in
7339       let alias =
7340         try find_map (function FishAlias n -> Some n | _ -> None) flags
7341         with Not_found -> name in
7342       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7343       let synopsis =
7344         match snd style with
7345         | [] -> name2
7346         | args ->
7347             sprintf "%s %s"
7348               name2 (String.concat " " (List.map name_of_argt args)) in
7349
7350       let warnings =
7351         if List.mem ProtocolLimitWarning flags then
7352           ("\n\n" ^ protocol_limit_warning)
7353         else "" in
7354
7355       (* For DangerWillRobinson commands, we should probably have
7356        * guestfish prompt before allowing you to use them (especially
7357        * in interactive mode). XXX
7358        *)
7359       let warnings =
7360         warnings ^
7361           if List.mem DangerWillRobinson flags then
7362             ("\n\n" ^ danger_will_robinson)
7363           else "" in
7364
7365       let warnings =
7366         warnings ^
7367           match deprecation_notice flags with
7368           | None -> ""
7369           | Some txt -> "\n\n" ^ txt in
7370
7371       let describe_alias =
7372         if name <> alias then
7373           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7374         else "" in
7375
7376       pr "  if (";
7377       pr "STRCASEEQ (cmd, \"%s\")" name;
7378       if name <> name2 then
7379         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7380       if name <> alias then
7381         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7382       pr ")\n";
7383       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7384         name2 shortdesc
7385         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7386          "=head1 DESCRIPTION\n\n" ^
7387          longdesc ^ warnings ^ describe_alias);
7388       pr "  else\n"
7389   ) all_functions;
7390   pr "    display_builtin_command (cmd);\n";
7391   pr "}\n";
7392   pr "\n";
7393
7394   let emit_print_list_function typ =
7395     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7396       typ typ typ;
7397     pr "{\n";
7398     pr "  unsigned int i;\n";
7399     pr "\n";
7400     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7401     pr "    printf (\"[%%d] = {\\n\", i);\n";
7402     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7403     pr "    printf (\"}\\n\");\n";
7404     pr "  }\n";
7405     pr "}\n";
7406     pr "\n";
7407   in
7408
7409   (* print_* functions *)
7410   List.iter (
7411     fun (typ, cols) ->
7412       let needs_i =
7413         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7414
7415       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7416       pr "{\n";
7417       if needs_i then (
7418         pr "  unsigned int i;\n";
7419         pr "\n"
7420       );
7421       List.iter (
7422         function
7423         | name, FString ->
7424             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7425         | name, FUUID ->
7426             pr "  printf (\"%%s%s: \", indent);\n" name;
7427             pr "  for (i = 0; i < 32; ++i)\n";
7428             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7429             pr "  printf (\"\\n\");\n"
7430         | name, FBuffer ->
7431             pr "  printf (\"%%s%s: \", indent);\n" name;
7432             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7433             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7434             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7435             pr "    else\n";
7436             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7437             pr "  printf (\"\\n\");\n"
7438         | name, (FUInt64|FBytes) ->
7439             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7440               name typ name
7441         | name, FInt64 ->
7442             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7443               name typ name
7444         | name, FUInt32 ->
7445             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7446               name typ name
7447         | name, FInt32 ->
7448             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7449               name typ name
7450         | name, FChar ->
7451             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7452               name typ name
7453         | name, FOptPercent ->
7454             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7455               typ name name typ name;
7456             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7457       ) cols;
7458       pr "}\n";
7459       pr "\n";
7460   ) structs;
7461
7462   (* Emit a print_TYPE_list function definition only if that function is used. *)
7463   List.iter (
7464     function
7465     | typ, (RStructListOnly | RStructAndList) ->
7466         (* generate the function for typ *)
7467         emit_print_list_function typ
7468     | typ, _ -> () (* empty *)
7469   ) (rstructs_used_by all_functions);
7470
7471   (* Emit a print_TYPE function definition only if that function is used. *)
7472   List.iter (
7473     function
7474     | typ, (RStructOnly | RStructAndList) ->
7475         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7476         pr "{\n";
7477         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7478         pr "}\n";
7479         pr "\n";
7480     | typ, _ -> () (* empty *)
7481   ) (rstructs_used_by all_functions);
7482
7483   (* run_<action> actions *)
7484   List.iter (
7485     fun (name, style, _, flags, _, _, _) ->
7486       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7487       pr "{\n";
7488       (match fst style with
7489        | RErr
7490        | RInt _
7491        | RBool _ -> pr "  int r;\n"
7492        | RInt64 _ -> pr "  int64_t r;\n"
7493        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7494        | RString _ -> pr "  char *r;\n"
7495        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7496        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7497        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7498        | RBufferOut _ ->
7499            pr "  char *r;\n";
7500            pr "  size_t size;\n";
7501       );
7502       List.iter (
7503         function
7504         | Device n
7505         | String n
7506         | OptString n -> pr "  const char *%s;\n" n
7507         | Pathname n
7508         | Dev_or_Path n
7509         | FileIn n
7510         | FileOut n -> pr "  char *%s;\n" n
7511         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7512         | Bool n -> pr "  int %s;\n" n
7513         | Int n -> pr "  int %s;\n" n
7514         | Int64 n -> pr "  int64_t %s;\n" n
7515       ) (snd style);
7516
7517       (* Check and convert parameters. *)
7518       let argc_expected = List.length (snd style) in
7519       pr "  if (argc != %d) {\n" argc_expected;
7520       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7521         argc_expected;
7522       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7523       pr "    return -1;\n";
7524       pr "  }\n";
7525
7526       let parse_integer fn fntyp rtyp range name i =
7527         pr "  {\n";
7528         pr "    strtol_error xerr;\n";
7529         pr "    %s r;\n" fntyp;
7530         pr "\n";
7531         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7532         pr "    if (xerr != LONGINT_OK) {\n";
7533         pr "      fprintf (stderr,\n";
7534         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7535         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7536         pr "      return -1;\n";
7537         pr "    }\n";
7538         (match range with
7539          | None -> ()
7540          | Some (min, max, comment) ->
7541              pr "    /* %s */\n" comment;
7542              pr "    if (r < %s || r > %s) {\n" min max;
7543              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7544                name;
7545              pr "      return -1;\n";
7546              pr "    }\n";
7547              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7548         );
7549         pr "    %s = r;\n" name;
7550         pr "  }\n";
7551       in
7552
7553       iteri (
7554         fun i ->
7555           function
7556           | Device name
7557           | String name ->
7558               pr "  %s = argv[%d];\n" name i
7559           | Pathname name
7560           | Dev_or_Path name ->
7561               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7562               pr "  if (%s == NULL) return -1;\n" name
7563           | OptString name ->
7564               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7565                 name i i
7566           | FileIn name ->
7567               pr "  %s = file_in (argv[%d]);\n" name i;
7568               pr "  if (%s == NULL) return -1;\n" name
7569           | FileOut name ->
7570               pr "  %s = file_out (argv[%d]);\n" name i;
7571               pr "  if (%s == NULL) return -1;\n" name
7572           | StringList name | DeviceList name ->
7573               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7574               pr "  if (%s == NULL) return -1;\n" name;
7575           | Bool name ->
7576               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7577           | Int name ->
7578               let range =
7579                 let min = "(-(2LL<<30))"
7580                 and max = "((2LL<<30)-1)"
7581                 and comment =
7582                   "The Int type in the generator is a signed 31 bit int." in
7583                 Some (min, max, comment) in
7584               parse_integer "xstrtoll" "long long" "int" range name i
7585           | Int64 name ->
7586               parse_integer "xstrtoll" "long long" "int64_t" None name i
7587       ) (snd style);
7588
7589       (* Call C API function. *)
7590       pr "  r = guestfs_%s " name;
7591       generate_c_call_args ~handle:"g" style;
7592       pr ";\n";
7593
7594       List.iter (
7595         function
7596         | Device name | String name
7597         | OptString name | Bool name
7598         | Int name | Int64 name -> ()
7599         | Pathname name | Dev_or_Path name | FileOut name ->
7600             pr "  free (%s);\n" name
7601         | FileIn name ->
7602             pr "  free_file_in (%s);\n" name
7603         | StringList name | DeviceList name ->
7604             pr "  free_strings (%s);\n" name
7605       ) (snd style);
7606
7607       (* Any output flags? *)
7608       let fish_output =
7609         let flags = filter_map (
7610           function FishOutput flag -> Some flag | _ -> None
7611         ) flags in
7612         match flags with
7613         | [] -> None
7614         | [f] -> Some f
7615         | _ ->
7616             failwithf "%s: more than one FishOutput flag is not allowed" name in
7617
7618       (* Check return value for errors and display command results. *)
7619       (match fst style with
7620        | RErr -> pr "  return r;\n"
7621        | RInt _ ->
7622            pr "  if (r == -1) return -1;\n";
7623            (match fish_output with
7624             | None ->
7625                 pr "  printf (\"%%d\\n\", r);\n";
7626             | Some FishOutputOctal ->
7627                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7628             | Some FishOutputHexadecimal ->
7629                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7630            pr "  return 0;\n"
7631        | RInt64 _ ->
7632            pr "  if (r == -1) return -1;\n";
7633            (match fish_output with
7634             | None ->
7635                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7636             | Some FishOutputOctal ->
7637                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7638             | Some FishOutputHexadecimal ->
7639                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7640            pr "  return 0;\n"
7641        | RBool _ ->
7642            pr "  if (r == -1) return -1;\n";
7643            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7644            pr "  return 0;\n"
7645        | RConstString _ ->
7646            pr "  if (r == NULL) return -1;\n";
7647            pr "  printf (\"%%s\\n\", r);\n";
7648            pr "  return 0;\n"
7649        | RConstOptString _ ->
7650            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7651            pr "  return 0;\n"
7652        | RString _ ->
7653            pr "  if (r == NULL) return -1;\n";
7654            pr "  printf (\"%%s\\n\", r);\n";
7655            pr "  free (r);\n";
7656            pr "  return 0;\n"
7657        | RStringList _ ->
7658            pr "  if (r == NULL) return -1;\n";
7659            pr "  print_strings (r);\n";
7660            pr "  free_strings (r);\n";
7661            pr "  return 0;\n"
7662        | RStruct (_, typ) ->
7663            pr "  if (r == NULL) return -1;\n";
7664            pr "  print_%s (r);\n" typ;
7665            pr "  guestfs_free_%s (r);\n" typ;
7666            pr "  return 0;\n"
7667        | RStructList (_, typ) ->
7668            pr "  if (r == NULL) return -1;\n";
7669            pr "  print_%s_list (r);\n" typ;
7670            pr "  guestfs_free_%s_list (r);\n" typ;
7671            pr "  return 0;\n"
7672        | RHashtable _ ->
7673            pr "  if (r == NULL) return -1;\n";
7674            pr "  print_table (r);\n";
7675            pr "  free_strings (r);\n";
7676            pr "  return 0;\n"
7677        | RBufferOut _ ->
7678            pr "  if (r == NULL) return -1;\n";
7679            pr "  if (full_write (1, r, size) != size) {\n";
7680            pr "    perror (\"write\");\n";
7681            pr "    free (r);\n";
7682            pr "    return -1;\n";
7683            pr "  }\n";
7684            pr "  free (r);\n";
7685            pr "  return 0;\n"
7686       );
7687       pr "}\n";
7688       pr "\n"
7689   ) all_functions;
7690
7691   (* run_action function *)
7692   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7693   pr "{\n";
7694   List.iter (
7695     fun (name, _, _, flags, _, _, _) ->
7696       let name2 = replace_char name '_' '-' in
7697       let alias =
7698         try find_map (function FishAlias n -> Some n | _ -> None) flags
7699         with Not_found -> name in
7700       pr "  if (";
7701       pr "STRCASEEQ (cmd, \"%s\")" name;
7702       if name <> name2 then
7703         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7704       if name <> alias then
7705         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7706       pr ")\n";
7707       pr "    return run_%s (cmd, argc, argv);\n" name;
7708       pr "  else\n";
7709   ) all_functions;
7710   pr "    {\n";
7711   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7712   pr "      if (command_num == 1)\n";
7713   pr "        extended_help_message ();\n";
7714   pr "      return -1;\n";
7715   pr "    }\n";
7716   pr "  return 0;\n";
7717   pr "}\n";
7718   pr "\n"
7719
7720 (* Readline completion for guestfish. *)
7721 and generate_fish_completion () =
7722   generate_header CStyle GPLv2plus;
7723
7724   let all_functions =
7725     List.filter (
7726       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7727     ) all_functions in
7728
7729   pr "\
7730 #include <config.h>
7731
7732 #include <stdio.h>
7733 #include <stdlib.h>
7734 #include <string.h>
7735
7736 #ifdef HAVE_LIBREADLINE
7737 #include <readline/readline.h>
7738 #endif
7739
7740 #include \"fish.h\"
7741
7742 #ifdef HAVE_LIBREADLINE
7743
7744 static const char *const commands[] = {
7745   BUILTIN_COMMANDS_FOR_COMPLETION,
7746 ";
7747
7748   (* Get the commands, including the aliases.  They don't need to be
7749    * sorted - the generator() function just does a dumb linear search.
7750    *)
7751   let commands =
7752     List.map (
7753       fun (name, _, _, flags, _, _, _) ->
7754         let name2 = replace_char name '_' '-' in
7755         let alias =
7756           try find_map (function FishAlias n -> Some n | _ -> None) flags
7757           with Not_found -> name in
7758
7759         if name <> alias then [name2; alias] else [name2]
7760     ) all_functions in
7761   let commands = List.flatten commands in
7762
7763   List.iter (pr "  \"%s\",\n") commands;
7764
7765   pr "  NULL
7766 };
7767
7768 static char *
7769 generator (const char *text, int state)
7770 {
7771   static int index, len;
7772   const char *name;
7773
7774   if (!state) {
7775     index = 0;
7776     len = strlen (text);
7777   }
7778
7779   rl_attempted_completion_over = 1;
7780
7781   while ((name = commands[index]) != NULL) {
7782     index++;
7783     if (STRCASEEQLEN (name, text, len))
7784       return strdup (name);
7785   }
7786
7787   return NULL;
7788 }
7789
7790 #endif /* HAVE_LIBREADLINE */
7791
7792 #ifdef HAVE_RL_COMPLETION_MATCHES
7793 #define RL_COMPLETION_MATCHES rl_completion_matches
7794 #else
7795 #ifdef HAVE_COMPLETION_MATCHES
7796 #define RL_COMPLETION_MATCHES completion_matches
7797 #endif
7798 #endif /* else just fail if we don't have either symbol */
7799
7800 char **
7801 do_completion (const char *text, int start, int end)
7802 {
7803   char **matches = NULL;
7804
7805 #ifdef HAVE_LIBREADLINE
7806   rl_completion_append_character = ' ';
7807
7808   if (start == 0)
7809     matches = RL_COMPLETION_MATCHES (text, generator);
7810   else if (complete_dest_paths)
7811     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7812 #endif
7813
7814   return matches;
7815 }
7816 ";
7817
7818 (* Generate the POD documentation for guestfish. *)
7819 and generate_fish_actions_pod () =
7820   let all_functions_sorted =
7821     List.filter (
7822       fun (_, _, _, flags, _, _, _) ->
7823         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7824     ) all_functions_sorted in
7825
7826   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7827
7828   List.iter (
7829     fun (name, style, _, flags, _, _, longdesc) ->
7830       let longdesc =
7831         Str.global_substitute rex (
7832           fun s ->
7833             let sub =
7834               try Str.matched_group 1 s
7835               with Not_found ->
7836                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7837             "C<" ^ replace_char sub '_' '-' ^ ">"
7838         ) longdesc in
7839       let name = replace_char name '_' '-' in
7840       let alias =
7841         try find_map (function FishAlias n -> Some n | _ -> None) flags
7842         with Not_found -> name in
7843
7844       pr "=head2 %s" name;
7845       if name <> alias then
7846         pr " | %s" alias;
7847       pr "\n";
7848       pr "\n";
7849       pr " %s" name;
7850       List.iter (
7851         function
7852         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7853         | OptString n -> pr " %s" n
7854         | StringList n | DeviceList n -> pr " '%s ...'" n
7855         | Bool _ -> pr " true|false"
7856         | Int n -> pr " %s" n
7857         | Int64 n -> pr " %s" n
7858         | FileIn n | FileOut n -> pr " (%s|-)" n
7859       ) (snd style);
7860       pr "\n";
7861       pr "\n";
7862       pr "%s\n\n" longdesc;
7863
7864       if List.exists (function FileIn _ | FileOut _ -> true
7865                       | _ -> false) (snd style) then
7866         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7867
7868       if List.mem ProtocolLimitWarning flags then
7869         pr "%s\n\n" protocol_limit_warning;
7870
7871       if List.mem DangerWillRobinson flags then
7872         pr "%s\n\n" danger_will_robinson;
7873
7874       match deprecation_notice flags with
7875       | None -> ()
7876       | Some txt -> pr "%s\n\n" txt
7877   ) all_functions_sorted
7878
7879 (* Generate a C function prototype. *)
7880 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7881     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7882     ?(prefix = "")
7883     ?handle name style =
7884   if extern then pr "extern ";
7885   if static then pr "static ";
7886   (match fst style with
7887    | RErr -> pr "int "
7888    | RInt _ -> pr "int "
7889    | RInt64 _ -> pr "int64_t "
7890    | RBool _ -> pr "int "
7891    | RConstString _ | RConstOptString _ -> pr "const char *"
7892    | RString _ | RBufferOut _ -> pr "char *"
7893    | RStringList _ | RHashtable _ -> pr "char **"
7894    | RStruct (_, typ) ->
7895        if not in_daemon then pr "struct guestfs_%s *" typ
7896        else pr "guestfs_int_%s *" typ
7897    | RStructList (_, typ) ->
7898        if not in_daemon then pr "struct guestfs_%s_list *" typ
7899        else pr "guestfs_int_%s_list *" typ
7900   );
7901   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7902   pr "%s%s (" prefix name;
7903   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7904     pr "void"
7905   else (
7906     let comma = ref false in
7907     (match handle with
7908      | None -> ()
7909      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7910     );
7911     let next () =
7912       if !comma then (
7913         if single_line then pr ", " else pr ",\n\t\t"
7914       );
7915       comma := true
7916     in
7917     List.iter (
7918       function
7919       | Pathname n
7920       | Device n | Dev_or_Path n
7921       | String n
7922       | OptString n ->
7923           next ();
7924           pr "const char *%s" n
7925       | StringList n | DeviceList n ->
7926           next ();
7927           pr "char *const *%s" n
7928       | Bool n -> next (); pr "int %s" n
7929       | Int n -> next (); pr "int %s" n
7930       | Int64 n -> next (); pr "int64_t %s" n
7931       | FileIn n
7932       | FileOut n ->
7933           if not in_daemon then (next (); pr "const char *%s" n)
7934     ) (snd style);
7935     if is_RBufferOut then (next (); pr "size_t *size_r");
7936   );
7937   pr ")";
7938   if semicolon then pr ";";
7939   if newline then pr "\n"
7940
7941 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7942 and generate_c_call_args ?handle ?(decl = false) style =
7943   pr "(";
7944   let comma = ref false in
7945   let next () =
7946     if !comma then pr ", ";
7947     comma := true
7948   in
7949   (match handle with
7950    | None -> ()
7951    | Some handle -> pr "%s" handle; comma := true
7952   );
7953   List.iter (
7954     fun arg ->
7955       next ();
7956       pr "%s" (name_of_argt arg)
7957   ) (snd style);
7958   (* For RBufferOut calls, add implicit &size parameter. *)
7959   if not decl then (
7960     match fst style with
7961     | RBufferOut _ ->
7962         next ();
7963         pr "&size"
7964     | _ -> ()
7965   );
7966   pr ")"
7967
7968 (* Generate the OCaml bindings interface. *)
7969 and generate_ocaml_mli () =
7970   generate_header OCamlStyle LGPLv2plus;
7971
7972   pr "\
7973 (** For API documentation you should refer to the C API
7974     in the guestfs(3) manual page.  The OCaml API uses almost
7975     exactly the same calls. *)
7976
7977 type t
7978 (** A [guestfs_h] handle. *)
7979
7980 exception Error of string
7981 (** This exception is raised when there is an error. *)
7982
7983 exception Handle_closed of string
7984 (** This exception is raised if you use a {!Guestfs.t} handle
7985     after calling {!close} on it.  The string is the name of
7986     the function. *)
7987
7988 val create : unit -> t
7989 (** Create a {!Guestfs.t} handle. *)
7990
7991 val close : t -> unit
7992 (** Close the {!Guestfs.t} handle and free up all resources used
7993     by it immediately.
7994
7995     Handles are closed by the garbage collector when they become
7996     unreferenced, but callers can call this in order to provide
7997     predictable cleanup. *)
7998
7999 ";
8000   generate_ocaml_structure_decls ();
8001
8002   (* The actions. *)
8003   List.iter (
8004     fun (name, style, _, _, _, shortdesc, _) ->
8005       generate_ocaml_prototype name style;
8006       pr "(** %s *)\n" shortdesc;
8007       pr "\n"
8008   ) all_functions_sorted
8009
8010 (* Generate the OCaml bindings implementation. *)
8011 and generate_ocaml_ml () =
8012   generate_header OCamlStyle LGPLv2plus;
8013
8014   pr "\
8015 type t
8016
8017 exception Error of string
8018 exception Handle_closed of string
8019
8020 external create : unit -> t = \"ocaml_guestfs_create\"
8021 external close : t -> unit = \"ocaml_guestfs_close\"
8022
8023 (* Give the exceptions names, so they can be raised from the C code. *)
8024 let () =
8025   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8026   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8027
8028 ";
8029
8030   generate_ocaml_structure_decls ();
8031
8032   (* The actions. *)
8033   List.iter (
8034     fun (name, style, _, _, _, shortdesc, _) ->
8035       generate_ocaml_prototype ~is_external:true name style;
8036   ) all_functions_sorted
8037
8038 (* Generate the OCaml bindings C implementation. *)
8039 and generate_ocaml_c () =
8040   generate_header CStyle LGPLv2plus;
8041
8042   pr "\
8043 #include <stdio.h>
8044 #include <stdlib.h>
8045 #include <string.h>
8046
8047 #include <caml/config.h>
8048 #include <caml/alloc.h>
8049 #include <caml/callback.h>
8050 #include <caml/fail.h>
8051 #include <caml/memory.h>
8052 #include <caml/mlvalues.h>
8053 #include <caml/signals.h>
8054
8055 #include <guestfs.h>
8056
8057 #include \"guestfs_c.h\"
8058
8059 /* Copy a hashtable of string pairs into an assoc-list.  We return
8060  * the list in reverse order, but hashtables aren't supposed to be
8061  * ordered anyway.
8062  */
8063 static CAMLprim value
8064 copy_table (char * const * argv)
8065 {
8066   CAMLparam0 ();
8067   CAMLlocal5 (rv, pairv, kv, vv, cons);
8068   int i;
8069
8070   rv = Val_int (0);
8071   for (i = 0; argv[i] != NULL; i += 2) {
8072     kv = caml_copy_string (argv[i]);
8073     vv = caml_copy_string (argv[i+1]);
8074     pairv = caml_alloc (2, 0);
8075     Store_field (pairv, 0, kv);
8076     Store_field (pairv, 1, vv);
8077     cons = caml_alloc (2, 0);
8078     Store_field (cons, 1, rv);
8079     rv = cons;
8080     Store_field (cons, 0, pairv);
8081   }
8082
8083   CAMLreturn (rv);
8084 }
8085
8086 ";
8087
8088   (* Struct copy functions. *)
8089
8090   let emit_ocaml_copy_list_function typ =
8091     pr "static CAMLprim value\n";
8092     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8093     pr "{\n";
8094     pr "  CAMLparam0 ();\n";
8095     pr "  CAMLlocal2 (rv, v);\n";
8096     pr "  unsigned int i;\n";
8097     pr "\n";
8098     pr "  if (%ss->len == 0)\n" typ;
8099     pr "    CAMLreturn (Atom (0));\n";
8100     pr "  else {\n";
8101     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8102     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8103     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8104     pr "      caml_modify (&Field (rv, i), v);\n";
8105     pr "    }\n";
8106     pr "    CAMLreturn (rv);\n";
8107     pr "  }\n";
8108     pr "}\n";
8109     pr "\n";
8110   in
8111
8112   List.iter (
8113     fun (typ, cols) ->
8114       let has_optpercent_col =
8115         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8116
8117       pr "static CAMLprim value\n";
8118       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8119       pr "{\n";
8120       pr "  CAMLparam0 ();\n";
8121       if has_optpercent_col then
8122         pr "  CAMLlocal3 (rv, v, v2);\n"
8123       else
8124         pr "  CAMLlocal2 (rv, v);\n";
8125       pr "\n";
8126       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8127       iteri (
8128         fun i col ->
8129           (match col with
8130            | name, FString ->
8131                pr "  v = caml_copy_string (%s->%s);\n" typ name
8132            | name, FBuffer ->
8133                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8134                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8135                  typ name typ name
8136            | name, FUUID ->
8137                pr "  v = caml_alloc_string (32);\n";
8138                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8139            | name, (FBytes|FInt64|FUInt64) ->
8140                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8141            | name, (FInt32|FUInt32) ->
8142                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8143            | name, FOptPercent ->
8144                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8145                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8146                pr "    v = caml_alloc (1, 0);\n";
8147                pr "    Store_field (v, 0, v2);\n";
8148                pr "  } else /* None */\n";
8149                pr "    v = Val_int (0);\n";
8150            | name, FChar ->
8151                pr "  v = Val_int (%s->%s);\n" typ name
8152           );
8153           pr "  Store_field (rv, %d, v);\n" i
8154       ) cols;
8155       pr "  CAMLreturn (rv);\n";
8156       pr "}\n";
8157       pr "\n";
8158   ) structs;
8159
8160   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8161   List.iter (
8162     function
8163     | typ, (RStructListOnly | RStructAndList) ->
8164         (* generate the function for typ *)
8165         emit_ocaml_copy_list_function typ
8166     | typ, _ -> () (* empty *)
8167   ) (rstructs_used_by all_functions);
8168
8169   (* The wrappers. *)
8170   List.iter (
8171     fun (name, style, _, _, _, _, _) ->
8172       pr "/* Automatically generated wrapper for function\n";
8173       pr " * ";
8174       generate_ocaml_prototype name style;
8175       pr " */\n";
8176       pr "\n";
8177
8178       let params =
8179         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8180
8181       let needs_extra_vs =
8182         match fst style with RConstOptString _ -> true | _ -> false in
8183
8184       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8185       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8186       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8187       pr "\n";
8188
8189       pr "CAMLprim value\n";
8190       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8191       List.iter (pr ", value %s") (List.tl params);
8192       pr ")\n";
8193       pr "{\n";
8194
8195       (match params with
8196        | [p1; p2; p3; p4; p5] ->
8197            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8198        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8199            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8200            pr "  CAMLxparam%d (%s);\n"
8201              (List.length rest) (String.concat ", " rest)
8202        | ps ->
8203            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8204       );
8205       if not needs_extra_vs then
8206         pr "  CAMLlocal1 (rv);\n"
8207       else
8208         pr "  CAMLlocal3 (rv, v, v2);\n";
8209       pr "\n";
8210
8211       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8212       pr "  if (g == NULL)\n";
8213       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8214       pr "\n";
8215
8216       List.iter (
8217         function
8218         | Pathname n
8219         | Device n | Dev_or_Path n
8220         | String n
8221         | FileIn n
8222         | FileOut n ->
8223             pr "  const char *%s = String_val (%sv);\n" n n
8224         | OptString n ->
8225             pr "  const char *%s =\n" n;
8226             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8227               n n
8228         | StringList n | DeviceList n ->
8229             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8230         | Bool n ->
8231             pr "  int %s = Bool_val (%sv);\n" n n
8232         | Int n ->
8233             pr "  int %s = Int_val (%sv);\n" n n
8234         | Int64 n ->
8235             pr "  int64_t %s = Int64_val (%sv);\n" n n
8236       ) (snd style);
8237       let error_code =
8238         match fst style with
8239         | RErr -> pr "  int r;\n"; "-1"
8240         | RInt _ -> pr "  int r;\n"; "-1"
8241         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8242         | RBool _ -> pr "  int r;\n"; "-1"
8243         | RConstString _ | RConstOptString _ ->
8244             pr "  const char *r;\n"; "NULL"
8245         | RString _ -> pr "  char *r;\n"; "NULL"
8246         | RStringList _ ->
8247             pr "  int i;\n";
8248             pr "  char **r;\n";
8249             "NULL"
8250         | RStruct (_, typ) ->
8251             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8252         | RStructList (_, typ) ->
8253             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8254         | RHashtable _ ->
8255             pr "  int i;\n";
8256             pr "  char **r;\n";
8257             "NULL"
8258         | RBufferOut _ ->
8259             pr "  char *r;\n";
8260             pr "  size_t size;\n";
8261             "NULL" in
8262       pr "\n";
8263
8264       pr "  caml_enter_blocking_section ();\n";
8265       pr "  r = guestfs_%s " name;
8266       generate_c_call_args ~handle:"g" style;
8267       pr ";\n";
8268       pr "  caml_leave_blocking_section ();\n";
8269
8270       List.iter (
8271         function
8272         | StringList n | DeviceList n ->
8273             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8274         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8275         | Bool _ | Int _ | Int64 _
8276         | FileIn _ | FileOut _ -> ()
8277       ) (snd style);
8278
8279       pr "  if (r == %s)\n" error_code;
8280       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8281       pr "\n";
8282
8283       (match fst style with
8284        | RErr -> pr "  rv = Val_unit;\n"
8285        | RInt _ -> pr "  rv = Val_int (r);\n"
8286        | RInt64 _ ->
8287            pr "  rv = caml_copy_int64 (r);\n"
8288        | RBool _ -> pr "  rv = Val_bool (r);\n"
8289        | RConstString _ ->
8290            pr "  rv = caml_copy_string (r);\n"
8291        | RConstOptString _ ->
8292            pr "  if (r) { /* Some string */\n";
8293            pr "    v = caml_alloc (1, 0);\n";
8294            pr "    v2 = caml_copy_string (r);\n";
8295            pr "    Store_field (v, 0, v2);\n";
8296            pr "  } else /* None */\n";
8297            pr "    v = Val_int (0);\n";
8298        | RString _ ->
8299            pr "  rv = caml_copy_string (r);\n";
8300            pr "  free (r);\n"
8301        | RStringList _ ->
8302            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8303            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8304            pr "  free (r);\n"
8305        | RStruct (_, typ) ->
8306            pr "  rv = copy_%s (r);\n" typ;
8307            pr "  guestfs_free_%s (r);\n" typ;
8308        | RStructList (_, typ) ->
8309            pr "  rv = copy_%s_list (r);\n" typ;
8310            pr "  guestfs_free_%s_list (r);\n" typ;
8311        | RHashtable _ ->
8312            pr "  rv = copy_table (r);\n";
8313            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8314            pr "  free (r);\n";
8315        | RBufferOut _ ->
8316            pr "  rv = caml_alloc_string (size);\n";
8317            pr "  memcpy (String_val (rv), r, size);\n";
8318       );
8319
8320       pr "  CAMLreturn (rv);\n";
8321       pr "}\n";
8322       pr "\n";
8323
8324       if List.length params > 5 then (
8325         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8326         pr "CAMLprim value ";
8327         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8328         pr "CAMLprim value\n";
8329         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8330         pr "{\n";
8331         pr "  return ocaml_guestfs_%s (argv[0]" name;
8332         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8333         pr ");\n";
8334         pr "}\n";
8335         pr "\n"
8336       )
8337   ) all_functions_sorted
8338
8339 and generate_ocaml_structure_decls () =
8340   List.iter (
8341     fun (typ, cols) ->
8342       pr "type %s = {\n" typ;
8343       List.iter (
8344         function
8345         | name, FString -> pr "  %s : string;\n" name
8346         | name, FBuffer -> pr "  %s : string;\n" name
8347         | name, FUUID -> pr "  %s : string;\n" name
8348         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8349         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8350         | name, FChar -> pr "  %s : char;\n" name
8351         | name, FOptPercent -> pr "  %s : float option;\n" name
8352       ) cols;
8353       pr "}\n";
8354       pr "\n"
8355   ) structs
8356
8357 and generate_ocaml_prototype ?(is_external = false) name style =
8358   if is_external then pr "external " else pr "val ";
8359   pr "%s : t -> " name;
8360   List.iter (
8361     function
8362     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8363     | OptString _ -> pr "string option -> "
8364     | StringList _ | DeviceList _ -> pr "string array -> "
8365     | Bool _ -> pr "bool -> "
8366     | Int _ -> pr "int -> "
8367     | Int64 _ -> pr "int64 -> "
8368   ) (snd style);
8369   (match fst style with
8370    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8371    | RInt _ -> pr "int"
8372    | RInt64 _ -> pr "int64"
8373    | RBool _ -> pr "bool"
8374    | RConstString _ -> pr "string"
8375    | RConstOptString _ -> pr "string option"
8376    | RString _ | RBufferOut _ -> pr "string"
8377    | RStringList _ -> pr "string array"
8378    | RStruct (_, typ) -> pr "%s" typ
8379    | RStructList (_, typ) -> pr "%s array" typ
8380    | RHashtable _ -> pr "(string * string) list"
8381   );
8382   if is_external then (
8383     pr " = ";
8384     if List.length (snd style) + 1 > 5 then
8385       pr "\"ocaml_guestfs_%s_byte\" " name;
8386     pr "\"ocaml_guestfs_%s\"" name
8387   );
8388   pr "\n"
8389
8390 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8391 and generate_perl_xs () =
8392   generate_header CStyle LGPLv2plus;
8393
8394   pr "\
8395 #include \"EXTERN.h\"
8396 #include \"perl.h\"
8397 #include \"XSUB.h\"
8398
8399 #include <guestfs.h>
8400
8401 #ifndef PRId64
8402 #define PRId64 \"lld\"
8403 #endif
8404
8405 static SV *
8406 my_newSVll(long long val) {
8407 #ifdef USE_64_BIT_ALL
8408   return newSViv(val);
8409 #else
8410   char buf[100];
8411   int len;
8412   len = snprintf(buf, 100, \"%%\" PRId64, val);
8413   return newSVpv(buf, len);
8414 #endif
8415 }
8416
8417 #ifndef PRIu64
8418 #define PRIu64 \"llu\"
8419 #endif
8420
8421 static SV *
8422 my_newSVull(unsigned long long val) {
8423 #ifdef USE_64_BIT_ALL
8424   return newSVuv(val);
8425 #else
8426   char buf[100];
8427   int len;
8428   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8429   return newSVpv(buf, len);
8430 #endif
8431 }
8432
8433 /* http://www.perlmonks.org/?node_id=680842 */
8434 static char **
8435 XS_unpack_charPtrPtr (SV *arg) {
8436   char **ret;
8437   AV *av;
8438   I32 i;
8439
8440   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8441     croak (\"array reference expected\");
8442
8443   av = (AV *)SvRV (arg);
8444   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8445   if (!ret)
8446     croak (\"malloc failed\");
8447
8448   for (i = 0; i <= av_len (av); i++) {
8449     SV **elem = av_fetch (av, i, 0);
8450
8451     if (!elem || !*elem)
8452       croak (\"missing element in list\");
8453
8454     ret[i] = SvPV_nolen (*elem);
8455   }
8456
8457   ret[i] = NULL;
8458
8459   return ret;
8460 }
8461
8462 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8463
8464 PROTOTYPES: ENABLE
8465
8466 guestfs_h *
8467 _create ()
8468    CODE:
8469       RETVAL = guestfs_create ();
8470       if (!RETVAL)
8471         croak (\"could not create guestfs handle\");
8472       guestfs_set_error_handler (RETVAL, NULL, NULL);
8473  OUTPUT:
8474       RETVAL
8475
8476 void
8477 DESTROY (g)
8478       guestfs_h *g;
8479  PPCODE:
8480       guestfs_close (g);
8481
8482 ";
8483
8484   List.iter (
8485     fun (name, style, _, _, _, _, _) ->
8486       (match fst style with
8487        | RErr -> pr "void\n"
8488        | RInt _ -> pr "SV *\n"
8489        | RInt64 _ -> pr "SV *\n"
8490        | RBool _ -> pr "SV *\n"
8491        | RConstString _ -> pr "SV *\n"
8492        | RConstOptString _ -> pr "SV *\n"
8493        | RString _ -> pr "SV *\n"
8494        | RBufferOut _ -> pr "SV *\n"
8495        | RStringList _
8496        | RStruct _ | RStructList _
8497        | RHashtable _ ->
8498            pr "void\n" (* all lists returned implictly on the stack *)
8499       );
8500       (* Call and arguments. *)
8501       pr "%s " name;
8502       generate_c_call_args ~handle:"g" ~decl:true style;
8503       pr "\n";
8504       pr "      guestfs_h *g;\n";
8505       iteri (
8506         fun i ->
8507           function
8508           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8509               pr "      char *%s;\n" n
8510           | OptString n ->
8511               (* http://www.perlmonks.org/?node_id=554277
8512                * Note that the implicit handle argument means we have
8513                * to add 1 to the ST(x) operator.
8514                *)
8515               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8516           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8517           | Bool n -> pr "      int %s;\n" n
8518           | Int n -> pr "      int %s;\n" n
8519           | Int64 n -> pr "      int64_t %s;\n" n
8520       ) (snd style);
8521
8522       let do_cleanups () =
8523         List.iter (
8524           function
8525           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8526           | Bool _ | Int _ | Int64 _
8527           | FileIn _ | FileOut _ -> ()
8528           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8529         ) (snd style)
8530       in
8531
8532       (* Code. *)
8533       (match fst style with
8534        | RErr ->
8535            pr "PREINIT:\n";
8536            pr "      int r;\n";
8537            pr " PPCODE:\n";
8538            pr "      r = guestfs_%s " name;
8539            generate_c_call_args ~handle:"g" style;
8540            pr ";\n";
8541            do_cleanups ();
8542            pr "      if (r == -1)\n";
8543            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8544        | RInt n
8545        | RBool n ->
8546            pr "PREINIT:\n";
8547            pr "      int %s;\n" n;
8548            pr "   CODE:\n";
8549            pr "      %s = guestfs_%s " n name;
8550            generate_c_call_args ~handle:"g" style;
8551            pr ";\n";
8552            do_cleanups ();
8553            pr "      if (%s == -1)\n" n;
8554            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8555            pr "      RETVAL = newSViv (%s);\n" n;
8556            pr " OUTPUT:\n";
8557            pr "      RETVAL\n"
8558        | RInt64 n ->
8559            pr "PREINIT:\n";
8560            pr "      int64_t %s;\n" n;
8561            pr "   CODE:\n";
8562            pr "      %s = guestfs_%s " n name;
8563            generate_c_call_args ~handle:"g" style;
8564            pr ";\n";
8565            do_cleanups ();
8566            pr "      if (%s == -1)\n" n;
8567            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8568            pr "      RETVAL = my_newSVll (%s);\n" n;
8569            pr " OUTPUT:\n";
8570            pr "      RETVAL\n"
8571        | RConstString n ->
8572            pr "PREINIT:\n";
8573            pr "      const char *%s;\n" n;
8574            pr "   CODE:\n";
8575            pr "      %s = guestfs_%s " n name;
8576            generate_c_call_args ~handle:"g" style;
8577            pr ";\n";
8578            do_cleanups ();
8579            pr "      if (%s == NULL)\n" n;
8580            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8581            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8582            pr " OUTPUT:\n";
8583            pr "      RETVAL\n"
8584        | RConstOptString n ->
8585            pr "PREINIT:\n";
8586            pr "      const char *%s;\n" n;
8587            pr "   CODE:\n";
8588            pr "      %s = guestfs_%s " n name;
8589            generate_c_call_args ~handle:"g" style;
8590            pr ";\n";
8591            do_cleanups ();
8592            pr "      if (%s == NULL)\n" n;
8593            pr "        RETVAL = &PL_sv_undef;\n";
8594            pr "      else\n";
8595            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8596            pr " OUTPUT:\n";
8597            pr "      RETVAL\n"
8598        | RString n ->
8599            pr "PREINIT:\n";
8600            pr "      char *%s;\n" n;
8601            pr "   CODE:\n";
8602            pr "      %s = guestfs_%s " n name;
8603            generate_c_call_args ~handle:"g" style;
8604            pr ";\n";
8605            do_cleanups ();
8606            pr "      if (%s == NULL)\n" n;
8607            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8608            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8609            pr "      free (%s);\n" n;
8610            pr " OUTPUT:\n";
8611            pr "      RETVAL\n"
8612        | RStringList n | RHashtable n ->
8613            pr "PREINIT:\n";
8614            pr "      char **%s;\n" n;
8615            pr "      int i, n;\n";
8616            pr " PPCODE:\n";
8617            pr "      %s = guestfs_%s " n name;
8618            generate_c_call_args ~handle:"g" style;
8619            pr ";\n";
8620            do_cleanups ();
8621            pr "      if (%s == NULL)\n" n;
8622            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8623            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8624            pr "      EXTEND (SP, n);\n";
8625            pr "      for (i = 0; i < n; ++i) {\n";
8626            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8627            pr "        free (%s[i]);\n" n;
8628            pr "      }\n";
8629            pr "      free (%s);\n" n;
8630        | RStruct (n, typ) ->
8631            let cols = cols_of_struct typ in
8632            generate_perl_struct_code typ cols name style n do_cleanups
8633        | RStructList (n, typ) ->
8634            let cols = cols_of_struct typ in
8635            generate_perl_struct_list_code typ cols name style n do_cleanups
8636        | RBufferOut n ->
8637            pr "PREINIT:\n";
8638            pr "      char *%s;\n" n;
8639            pr "      size_t size;\n";
8640            pr "   CODE:\n";
8641            pr "      %s = guestfs_%s " n name;
8642            generate_c_call_args ~handle:"g" style;
8643            pr ";\n";
8644            do_cleanups ();
8645            pr "      if (%s == NULL)\n" n;
8646            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8647            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8648            pr "      free (%s);\n" n;
8649            pr " OUTPUT:\n";
8650            pr "      RETVAL\n"
8651       );
8652
8653       pr "\n"
8654   ) all_functions
8655
8656 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8657   pr "PREINIT:\n";
8658   pr "      struct guestfs_%s_list *%s;\n" typ n;
8659   pr "      int i;\n";
8660   pr "      HV *hv;\n";
8661   pr " PPCODE:\n";
8662   pr "      %s = guestfs_%s " n name;
8663   generate_c_call_args ~handle:"g" style;
8664   pr ";\n";
8665   do_cleanups ();
8666   pr "      if (%s == NULL)\n" n;
8667   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8668   pr "      EXTEND (SP, %s->len);\n" n;
8669   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8670   pr "        hv = newHV ();\n";
8671   List.iter (
8672     function
8673     | name, FString ->
8674         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8675           name (String.length name) n name
8676     | name, FUUID ->
8677         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8678           name (String.length name) n name
8679     | name, FBuffer ->
8680         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8681           name (String.length name) n name n name
8682     | name, (FBytes|FUInt64) ->
8683         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8684           name (String.length name) n name
8685     | name, FInt64 ->
8686         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8687           name (String.length name) n name
8688     | name, (FInt32|FUInt32) ->
8689         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8690           name (String.length name) n name
8691     | name, FChar ->
8692         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8693           name (String.length name) n name
8694     | name, FOptPercent ->
8695         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8696           name (String.length name) n name
8697   ) cols;
8698   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8699   pr "      }\n";
8700   pr "      guestfs_free_%s_list (%s);\n" typ n
8701
8702 and generate_perl_struct_code typ cols name style n do_cleanups =
8703   pr "PREINIT:\n";
8704   pr "      struct guestfs_%s *%s;\n" typ n;
8705   pr " PPCODE:\n";
8706   pr "      %s = guestfs_%s " n name;
8707   generate_c_call_args ~handle:"g" style;
8708   pr ";\n";
8709   do_cleanups ();
8710   pr "      if (%s == NULL)\n" n;
8711   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8712   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8713   List.iter (
8714     fun ((name, _) as col) ->
8715       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8716
8717       match col with
8718       | name, FString ->
8719           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8720             n name
8721       | name, FBuffer ->
8722           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8723             n name n name
8724       | name, FUUID ->
8725           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8726             n name
8727       | name, (FBytes|FUInt64) ->
8728           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8729             n name
8730       | name, FInt64 ->
8731           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8732             n name
8733       | name, (FInt32|FUInt32) ->
8734           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8735             n name
8736       | name, FChar ->
8737           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8738             n name
8739       | name, FOptPercent ->
8740           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8741             n name
8742   ) cols;
8743   pr "      free (%s);\n" n
8744
8745 (* Generate Sys/Guestfs.pm. *)
8746 and generate_perl_pm () =
8747   generate_header HashStyle LGPLv2plus;
8748
8749   pr "\
8750 =pod
8751
8752 =head1 NAME
8753
8754 Sys::Guestfs - Perl bindings for libguestfs
8755
8756 =head1 SYNOPSIS
8757
8758  use Sys::Guestfs;
8759
8760  my $h = Sys::Guestfs->new ();
8761  $h->add_drive ('guest.img');
8762  $h->launch ();
8763  $h->mount ('/dev/sda1', '/');
8764  $h->touch ('/hello');
8765  $h->sync ();
8766
8767 =head1 DESCRIPTION
8768
8769 The C<Sys::Guestfs> module provides a Perl XS binding to the
8770 libguestfs API for examining and modifying virtual machine
8771 disk images.
8772
8773 Amongst the things this is good for: making batch configuration
8774 changes to guests, getting disk used/free statistics (see also:
8775 virt-df), migrating between virtualization systems (see also:
8776 virt-p2v), performing partial backups, performing partial guest
8777 clones, cloning guests and changing registry/UUID/hostname info, and
8778 much else besides.
8779
8780 Libguestfs uses Linux kernel and qemu code, and can access any type of
8781 guest filesystem that Linux and qemu can, including but not limited
8782 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8783 schemes, qcow, qcow2, vmdk.
8784
8785 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8786 LVs, what filesystem is in each LV, etc.).  It can also run commands
8787 in the context of the guest.  Also you can access filesystems over
8788 FUSE.
8789
8790 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8791 functions for using libguestfs from Perl, including integration
8792 with libvirt.
8793
8794 =head1 ERRORS
8795
8796 All errors turn into calls to C<croak> (see L<Carp(3)>).
8797
8798 =head1 METHODS
8799
8800 =over 4
8801
8802 =cut
8803
8804 package Sys::Guestfs;
8805
8806 use strict;
8807 use warnings;
8808
8809 require XSLoader;
8810 XSLoader::load ('Sys::Guestfs');
8811
8812 =item $h = Sys::Guestfs->new ();
8813
8814 Create a new guestfs handle.
8815
8816 =cut
8817
8818 sub new {
8819   my $proto = shift;
8820   my $class = ref ($proto) || $proto;
8821
8822   my $self = Sys::Guestfs::_create ();
8823   bless $self, $class;
8824   return $self;
8825 }
8826
8827 ";
8828
8829   (* Actions.  We only need to print documentation for these as
8830    * they are pulled in from the XS code automatically.
8831    *)
8832   List.iter (
8833     fun (name, style, _, flags, _, _, longdesc) ->
8834       if not (List.mem NotInDocs flags) then (
8835         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8836         pr "=item ";
8837         generate_perl_prototype name style;
8838         pr "\n\n";
8839         pr "%s\n\n" longdesc;
8840         if List.mem ProtocolLimitWarning flags then
8841           pr "%s\n\n" protocol_limit_warning;
8842         if List.mem DangerWillRobinson flags then
8843           pr "%s\n\n" danger_will_robinson;
8844         match deprecation_notice flags with
8845         | None -> ()
8846         | Some txt -> pr "%s\n\n" txt
8847       )
8848   ) all_functions_sorted;
8849
8850   (* End of file. *)
8851   pr "\
8852 =cut
8853
8854 1;
8855
8856 =back
8857
8858 =head1 COPYRIGHT
8859
8860 Copyright (C) %s Red Hat Inc.
8861
8862 =head1 LICENSE
8863
8864 Please see the file COPYING.LIB for the full license.
8865
8866 =head1 SEE ALSO
8867
8868 L<guestfs(3)>,
8869 L<guestfish(1)>,
8870 L<http://libguestfs.org>,
8871 L<Sys::Guestfs::Lib(3)>.
8872
8873 =cut
8874 " copyright_years
8875
8876 and generate_perl_prototype name style =
8877   (match fst style with
8878    | RErr -> ()
8879    | RBool n
8880    | RInt n
8881    | RInt64 n
8882    | RConstString n
8883    | RConstOptString n
8884    | RString n
8885    | RBufferOut n -> pr "$%s = " n
8886    | RStruct (n,_)
8887    | RHashtable n -> pr "%%%s = " n
8888    | RStringList n
8889    | RStructList (n,_) -> pr "@%s = " n
8890   );
8891   pr "$h->%s (" name;
8892   let comma = ref false in
8893   List.iter (
8894     fun arg ->
8895       if !comma then pr ", ";
8896       comma := true;
8897       match arg with
8898       | Pathname n | Device n | Dev_or_Path n | String n
8899       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8900           pr "$%s" n
8901       | StringList n | DeviceList n ->
8902           pr "\\@%s" n
8903   ) (snd style);
8904   pr ");"
8905
8906 (* Generate Python C module. *)
8907 and generate_python_c () =
8908   generate_header CStyle LGPLv2plus;
8909
8910   pr "\
8911 #include <Python.h>
8912
8913 #include <stdio.h>
8914 #include <stdlib.h>
8915 #include <assert.h>
8916
8917 #include \"guestfs.h\"
8918
8919 typedef struct {
8920   PyObject_HEAD
8921   guestfs_h *g;
8922 } Pyguestfs_Object;
8923
8924 static guestfs_h *
8925 get_handle (PyObject *obj)
8926 {
8927   assert (obj);
8928   assert (obj != Py_None);
8929   return ((Pyguestfs_Object *) obj)->g;
8930 }
8931
8932 static PyObject *
8933 put_handle (guestfs_h *g)
8934 {
8935   assert (g);
8936   return
8937     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8938 }
8939
8940 /* This list should be freed (but not the strings) after use. */
8941 static char **
8942 get_string_list (PyObject *obj)
8943 {
8944   int i, len;
8945   char **r;
8946
8947   assert (obj);
8948
8949   if (!PyList_Check (obj)) {
8950     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8951     return NULL;
8952   }
8953
8954   len = PyList_Size (obj);
8955   r = malloc (sizeof (char *) * (len+1));
8956   if (r == NULL) {
8957     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8958     return NULL;
8959   }
8960
8961   for (i = 0; i < len; ++i)
8962     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8963   r[len] = NULL;
8964
8965   return r;
8966 }
8967
8968 static PyObject *
8969 put_string_list (char * const * const argv)
8970 {
8971   PyObject *list;
8972   int argc, i;
8973
8974   for (argc = 0; argv[argc] != NULL; ++argc)
8975     ;
8976
8977   list = PyList_New (argc);
8978   for (i = 0; i < argc; ++i)
8979     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8980
8981   return list;
8982 }
8983
8984 static PyObject *
8985 put_table (char * const * const argv)
8986 {
8987   PyObject *list, *item;
8988   int argc, i;
8989
8990   for (argc = 0; argv[argc] != NULL; ++argc)
8991     ;
8992
8993   list = PyList_New (argc >> 1);
8994   for (i = 0; i < argc; i += 2) {
8995     item = PyTuple_New (2);
8996     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8997     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8998     PyList_SetItem (list, i >> 1, item);
8999   }
9000
9001   return list;
9002 }
9003
9004 static void
9005 free_strings (char **argv)
9006 {
9007   int argc;
9008
9009   for (argc = 0; argv[argc] != NULL; ++argc)
9010     free (argv[argc]);
9011   free (argv);
9012 }
9013
9014 static PyObject *
9015 py_guestfs_create (PyObject *self, PyObject *args)
9016 {
9017   guestfs_h *g;
9018
9019   g = guestfs_create ();
9020   if (g == NULL) {
9021     PyErr_SetString (PyExc_RuntimeError,
9022                      \"guestfs.create: failed to allocate handle\");
9023     return NULL;
9024   }
9025   guestfs_set_error_handler (g, NULL, NULL);
9026   return put_handle (g);
9027 }
9028
9029 static PyObject *
9030 py_guestfs_close (PyObject *self, PyObject *args)
9031 {
9032   PyObject *py_g;
9033   guestfs_h *g;
9034
9035   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9036     return NULL;
9037   g = get_handle (py_g);
9038
9039   guestfs_close (g);
9040
9041   Py_INCREF (Py_None);
9042   return Py_None;
9043 }
9044
9045 ";
9046
9047   let emit_put_list_function typ =
9048     pr "static PyObject *\n";
9049     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9050     pr "{\n";
9051     pr "  PyObject *list;\n";
9052     pr "  int i;\n";
9053     pr "\n";
9054     pr "  list = PyList_New (%ss->len);\n" typ;
9055     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9056     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9057     pr "  return list;\n";
9058     pr "};\n";
9059     pr "\n"
9060   in
9061
9062   (* Structures, turned into Python dictionaries. *)
9063   List.iter (
9064     fun (typ, cols) ->
9065       pr "static PyObject *\n";
9066       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9067       pr "{\n";
9068       pr "  PyObject *dict;\n";
9069       pr "\n";
9070       pr "  dict = PyDict_New ();\n";
9071       List.iter (
9072         function
9073         | name, FString ->
9074             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9075             pr "                        PyString_FromString (%s->%s));\n"
9076               typ name
9077         | name, FBuffer ->
9078             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9079             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9080               typ name typ name
9081         | name, FUUID ->
9082             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9083             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9084               typ name
9085         | name, (FBytes|FUInt64) ->
9086             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9087             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9088               typ name
9089         | name, FInt64 ->
9090             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9091             pr "                        PyLong_FromLongLong (%s->%s));\n"
9092               typ name
9093         | name, FUInt32 ->
9094             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9095             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9096               typ name
9097         | name, FInt32 ->
9098             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9099             pr "                        PyLong_FromLong (%s->%s));\n"
9100               typ name
9101         | name, FOptPercent ->
9102             pr "  if (%s->%s >= 0)\n" typ name;
9103             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9104             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9105               typ name;
9106             pr "  else {\n";
9107             pr "    Py_INCREF (Py_None);\n";
9108             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9109             pr "  }\n"
9110         | name, FChar ->
9111             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9112             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9113       ) cols;
9114       pr "  return dict;\n";
9115       pr "};\n";
9116       pr "\n";
9117
9118   ) structs;
9119
9120   (* Emit a put_TYPE_list function definition only if that function is used. *)
9121   List.iter (
9122     function
9123     | typ, (RStructListOnly | RStructAndList) ->
9124         (* generate the function for typ *)
9125         emit_put_list_function typ
9126     | typ, _ -> () (* empty *)
9127   ) (rstructs_used_by all_functions);
9128
9129   (* Python wrapper functions. *)
9130   List.iter (
9131     fun (name, style, _, _, _, _, _) ->
9132       pr "static PyObject *\n";
9133       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9134       pr "{\n";
9135
9136       pr "  PyObject *py_g;\n";
9137       pr "  guestfs_h *g;\n";
9138       pr "  PyObject *py_r;\n";
9139
9140       let error_code =
9141         match fst style with
9142         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9143         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9144         | RConstString _ | RConstOptString _ ->
9145             pr "  const char *r;\n"; "NULL"
9146         | RString _ -> pr "  char *r;\n"; "NULL"
9147         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9148         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9149         | RStructList (_, typ) ->
9150             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9151         | RBufferOut _ ->
9152             pr "  char *r;\n";
9153             pr "  size_t size;\n";
9154             "NULL" in
9155
9156       List.iter (
9157         function
9158         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9159             pr "  const char *%s;\n" n
9160         | OptString n -> pr "  const char *%s;\n" n
9161         | StringList n | DeviceList n ->
9162             pr "  PyObject *py_%s;\n" n;
9163             pr "  char **%s;\n" n
9164         | Bool n -> pr "  int %s;\n" n
9165         | Int n -> pr "  int %s;\n" n
9166         | Int64 n -> pr "  long long %s;\n" n
9167       ) (snd style);
9168
9169       pr "\n";
9170
9171       (* Convert the parameters. *)
9172       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9173       List.iter (
9174         function
9175         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9176         | OptString _ -> pr "z"
9177         | StringList _ | DeviceList _ -> pr "O"
9178         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9179         | Int _ -> pr "i"
9180         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9181                              * emulate C's int/long/long long in Python?
9182                              *)
9183       ) (snd style);
9184       pr ":guestfs_%s\",\n" name;
9185       pr "                         &py_g";
9186       List.iter (
9187         function
9188         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9189         | OptString n -> pr ", &%s" n
9190         | StringList n | DeviceList n -> pr ", &py_%s" n
9191         | Bool n -> pr ", &%s" n
9192         | Int n -> pr ", &%s" n
9193         | Int64 n -> pr ", &%s" n
9194       ) (snd style);
9195
9196       pr "))\n";
9197       pr "    return NULL;\n";
9198
9199       pr "  g = get_handle (py_g);\n";
9200       List.iter (
9201         function
9202         | Pathname _ | Device _ | Dev_or_Path _ | String _
9203         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9204         | StringList n | DeviceList n ->
9205             pr "  %s = get_string_list (py_%s);\n" n n;
9206             pr "  if (!%s) return NULL;\n" n
9207       ) (snd style);
9208
9209       pr "\n";
9210
9211       pr "  r = guestfs_%s " name;
9212       generate_c_call_args ~handle:"g" style;
9213       pr ";\n";
9214
9215       List.iter (
9216         function
9217         | Pathname _ | Device _ | Dev_or_Path _ | String _
9218         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9219         | StringList n | DeviceList n ->
9220             pr "  free (%s);\n" n
9221       ) (snd style);
9222
9223       pr "  if (r == %s) {\n" error_code;
9224       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9225       pr "    return NULL;\n";
9226       pr "  }\n";
9227       pr "\n";
9228
9229       (match fst style with
9230        | RErr ->
9231            pr "  Py_INCREF (Py_None);\n";
9232            pr "  py_r = Py_None;\n"
9233        | RInt _
9234        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9235        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9236        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9237        | RConstOptString _ ->
9238            pr "  if (r)\n";
9239            pr "    py_r = PyString_FromString (r);\n";
9240            pr "  else {\n";
9241            pr "    Py_INCREF (Py_None);\n";
9242            pr "    py_r = Py_None;\n";
9243            pr "  }\n"
9244        | RString _ ->
9245            pr "  py_r = PyString_FromString (r);\n";
9246            pr "  free (r);\n"
9247        | RStringList _ ->
9248            pr "  py_r = put_string_list (r);\n";
9249            pr "  free_strings (r);\n"
9250        | RStruct (_, typ) ->
9251            pr "  py_r = put_%s (r);\n" typ;
9252            pr "  guestfs_free_%s (r);\n" typ
9253        | RStructList (_, typ) ->
9254            pr "  py_r = put_%s_list (r);\n" typ;
9255            pr "  guestfs_free_%s_list (r);\n" typ
9256        | RHashtable n ->
9257            pr "  py_r = put_table (r);\n";
9258            pr "  free_strings (r);\n"
9259        | RBufferOut _ ->
9260            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9261            pr "  free (r);\n"
9262       );
9263
9264       pr "  return py_r;\n";
9265       pr "}\n";
9266       pr "\n"
9267   ) all_functions;
9268
9269   (* Table of functions. *)
9270   pr "static PyMethodDef methods[] = {\n";
9271   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9272   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9273   List.iter (
9274     fun (name, _, _, _, _, _, _) ->
9275       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9276         name name
9277   ) all_functions;
9278   pr "  { NULL, NULL, 0, NULL }\n";
9279   pr "};\n";
9280   pr "\n";
9281
9282   (* Init function. *)
9283   pr "\
9284 void
9285 initlibguestfsmod (void)
9286 {
9287   static int initialized = 0;
9288
9289   if (initialized) return;
9290   Py_InitModule ((char *) \"libguestfsmod\", methods);
9291   initialized = 1;
9292 }
9293 "
9294
9295 (* Generate Python module. *)
9296 and generate_python_py () =
9297   generate_header HashStyle LGPLv2plus;
9298
9299   pr "\
9300 u\"\"\"Python bindings for libguestfs
9301
9302 import guestfs
9303 g = guestfs.GuestFS ()
9304 g.add_drive (\"guest.img\")
9305 g.launch ()
9306 parts = g.list_partitions ()
9307
9308 The guestfs module provides a Python binding to the libguestfs API
9309 for examining and modifying virtual machine disk images.
9310
9311 Amongst the things this is good for: making batch configuration
9312 changes to guests, getting disk used/free statistics (see also:
9313 virt-df), migrating between virtualization systems (see also:
9314 virt-p2v), performing partial backups, performing partial guest
9315 clones, cloning guests and changing registry/UUID/hostname info, and
9316 much else besides.
9317
9318 Libguestfs uses Linux kernel and qemu code, and can access any type of
9319 guest filesystem that Linux and qemu can, including but not limited
9320 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9321 schemes, qcow, qcow2, vmdk.
9322
9323 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9324 LVs, what filesystem is in each LV, etc.).  It can also run commands
9325 in the context of the guest.  Also you can access filesystems over
9326 FUSE.
9327
9328 Errors which happen while using the API are turned into Python
9329 RuntimeError exceptions.
9330
9331 To create a guestfs handle you usually have to perform the following
9332 sequence of calls:
9333
9334 # Create the handle, call add_drive at least once, and possibly
9335 # several times if the guest has multiple block devices:
9336 g = guestfs.GuestFS ()
9337 g.add_drive (\"guest.img\")
9338
9339 # Launch the qemu subprocess and wait for it to become ready:
9340 g.launch ()
9341
9342 # Now you can issue commands, for example:
9343 logvols = g.lvs ()
9344
9345 \"\"\"
9346
9347 import libguestfsmod
9348
9349 class GuestFS:
9350     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9351
9352     def __init__ (self):
9353         \"\"\"Create a new libguestfs handle.\"\"\"
9354         self._o = libguestfsmod.create ()
9355
9356     def __del__ (self):
9357         libguestfsmod.close (self._o)
9358
9359 ";
9360
9361   List.iter (
9362     fun (name, style, _, flags, _, _, longdesc) ->
9363       pr "    def %s " name;
9364       generate_py_call_args ~handle:"self" (snd style);
9365       pr ":\n";
9366
9367       if not (List.mem NotInDocs flags) then (
9368         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9369         let doc =
9370           match fst style with
9371           | RErr | RInt _ | RInt64 _ | RBool _
9372           | RConstOptString _ | RConstString _
9373           | RString _ | RBufferOut _ -> doc
9374           | RStringList _ ->
9375               doc ^ "\n\nThis function returns a list of strings."
9376           | RStruct (_, typ) ->
9377               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9378           | RStructList (_, typ) ->
9379               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9380           | RHashtable _ ->
9381               doc ^ "\n\nThis function returns a dictionary." in
9382         let doc =
9383           if List.mem ProtocolLimitWarning flags then
9384             doc ^ "\n\n" ^ protocol_limit_warning
9385           else doc in
9386         let doc =
9387           if List.mem DangerWillRobinson flags then
9388             doc ^ "\n\n" ^ danger_will_robinson
9389           else doc in
9390         let doc =
9391           match deprecation_notice flags with
9392           | None -> doc
9393           | Some txt -> doc ^ "\n\n" ^ txt in
9394         let doc = pod2text ~width:60 name doc in
9395         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9396         let doc = String.concat "\n        " doc in
9397         pr "        u\"\"\"%s\"\"\"\n" doc;
9398       );
9399       pr "        return libguestfsmod.%s " name;
9400       generate_py_call_args ~handle:"self._o" (snd style);
9401       pr "\n";
9402       pr "\n";
9403   ) all_functions
9404
9405 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9406 and generate_py_call_args ~handle args =
9407   pr "(%s" handle;
9408   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9409   pr ")"
9410
9411 (* Useful if you need the longdesc POD text as plain text.  Returns a
9412  * list of lines.
9413  *
9414  * Because this is very slow (the slowest part of autogeneration),
9415  * we memoize the results.
9416  *)
9417 and pod2text ~width name longdesc =
9418   let key = width, name, longdesc in
9419   try Hashtbl.find pod2text_memo key
9420   with Not_found ->
9421     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9422     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9423     close_out chan;
9424     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9425     let chan = open_process_in cmd in
9426     let lines = ref [] in
9427     let rec loop i =
9428       let line = input_line chan in
9429       if i = 1 then             (* discard the first line of output *)
9430         loop (i+1)
9431       else (
9432         let line = triml line in
9433         lines := line :: !lines;
9434         loop (i+1)
9435       ) in
9436     let lines = try loop 1 with End_of_file -> List.rev !lines in
9437     unlink filename;
9438     (match close_process_in chan with
9439      | WEXITED 0 -> ()
9440      | WEXITED i ->
9441          failwithf "pod2text: process exited with non-zero status (%d)" i
9442      | WSIGNALED i | WSTOPPED i ->
9443          failwithf "pod2text: process signalled or stopped by signal %d" i
9444     );
9445     Hashtbl.add pod2text_memo key lines;
9446     pod2text_memo_updated ();
9447     lines
9448
9449 (* Generate ruby bindings. *)
9450 and generate_ruby_c () =
9451   generate_header CStyle LGPLv2plus;
9452
9453   pr "\
9454 #include <stdio.h>
9455 #include <stdlib.h>
9456
9457 #include <ruby.h>
9458
9459 #include \"guestfs.h\"
9460
9461 #include \"extconf.h\"
9462
9463 /* For Ruby < 1.9 */
9464 #ifndef RARRAY_LEN
9465 #define RARRAY_LEN(r) (RARRAY((r))->len)
9466 #endif
9467
9468 static VALUE m_guestfs;                 /* guestfs module */
9469 static VALUE c_guestfs;                 /* guestfs_h handle */
9470 static VALUE e_Error;                   /* used for all errors */
9471
9472 static void ruby_guestfs_free (void *p)
9473 {
9474   if (!p) return;
9475   guestfs_close ((guestfs_h *) p);
9476 }
9477
9478 static VALUE ruby_guestfs_create (VALUE m)
9479 {
9480   guestfs_h *g;
9481
9482   g = guestfs_create ();
9483   if (!g)
9484     rb_raise (e_Error, \"failed to create guestfs handle\");
9485
9486   /* Don't print error messages to stderr by default. */
9487   guestfs_set_error_handler (g, NULL, NULL);
9488
9489   /* Wrap it, and make sure the close function is called when the
9490    * handle goes away.
9491    */
9492   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9493 }
9494
9495 static VALUE ruby_guestfs_close (VALUE gv)
9496 {
9497   guestfs_h *g;
9498   Data_Get_Struct (gv, guestfs_h, g);
9499
9500   ruby_guestfs_free (g);
9501   DATA_PTR (gv) = NULL;
9502
9503   return Qnil;
9504 }
9505
9506 ";
9507
9508   List.iter (
9509     fun (name, style, _, _, _, _, _) ->
9510       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9511       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9512       pr ")\n";
9513       pr "{\n";
9514       pr "  guestfs_h *g;\n";
9515       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9516       pr "  if (!g)\n";
9517       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9518         name;
9519       pr "\n";
9520
9521       List.iter (
9522         function
9523         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9524             pr "  Check_Type (%sv, T_STRING);\n" n;
9525             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9526             pr "  if (!%s)\n" n;
9527             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9528             pr "              \"%s\", \"%s\");\n" n name
9529         | OptString n ->
9530             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9531         | StringList n | DeviceList n ->
9532             pr "  char **%s;\n" n;
9533             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9534             pr "  {\n";
9535             pr "    int i, len;\n";
9536             pr "    len = RARRAY_LEN (%sv);\n" n;
9537             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9538               n;
9539             pr "    for (i = 0; i < len; ++i) {\n";
9540             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9541             pr "      %s[i] = StringValueCStr (v);\n" n;
9542             pr "    }\n";
9543             pr "    %s[len] = NULL;\n" n;
9544             pr "  }\n";
9545         | Bool n ->
9546             pr "  int %s = RTEST (%sv);\n" n n
9547         | Int n ->
9548             pr "  int %s = NUM2INT (%sv);\n" n n
9549         | Int64 n ->
9550             pr "  long long %s = NUM2LL (%sv);\n" n n
9551       ) (snd style);
9552       pr "\n";
9553
9554       let error_code =
9555         match fst style with
9556         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9557         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9558         | RConstString _ | RConstOptString _ ->
9559             pr "  const char *r;\n"; "NULL"
9560         | RString _ -> pr "  char *r;\n"; "NULL"
9561         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9562         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9563         | RStructList (_, typ) ->
9564             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9565         | RBufferOut _ ->
9566             pr "  char *r;\n";
9567             pr "  size_t size;\n";
9568             "NULL" in
9569       pr "\n";
9570
9571       pr "  r = guestfs_%s " name;
9572       generate_c_call_args ~handle:"g" style;
9573       pr ";\n";
9574
9575       List.iter (
9576         function
9577         | Pathname _ | Device _ | Dev_or_Path _ | String _
9578         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9579         | StringList n | DeviceList n ->
9580             pr "  free (%s);\n" n
9581       ) (snd style);
9582
9583       pr "  if (r == %s)\n" error_code;
9584       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9585       pr "\n";
9586
9587       (match fst style with
9588        | RErr ->
9589            pr "  return Qnil;\n"
9590        | RInt _ | RBool _ ->
9591            pr "  return INT2NUM (r);\n"
9592        | RInt64 _ ->
9593            pr "  return ULL2NUM (r);\n"
9594        | RConstString _ ->
9595            pr "  return rb_str_new2 (r);\n";
9596        | RConstOptString _ ->
9597            pr "  if (r)\n";
9598            pr "    return rb_str_new2 (r);\n";
9599            pr "  else\n";
9600            pr "    return Qnil;\n";
9601        | RString _ ->
9602            pr "  VALUE rv = rb_str_new2 (r);\n";
9603            pr "  free (r);\n";
9604            pr "  return rv;\n";
9605        | RStringList _ ->
9606            pr "  int i, len = 0;\n";
9607            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9608            pr "  VALUE rv = rb_ary_new2 (len);\n";
9609            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9610            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9611            pr "    free (r[i]);\n";
9612            pr "  }\n";
9613            pr "  free (r);\n";
9614            pr "  return rv;\n"
9615        | RStruct (_, typ) ->
9616            let cols = cols_of_struct typ in
9617            generate_ruby_struct_code typ cols
9618        | RStructList (_, typ) ->
9619            let cols = cols_of_struct typ in
9620            generate_ruby_struct_list_code typ cols
9621        | RHashtable _ ->
9622            pr "  VALUE rv = rb_hash_new ();\n";
9623            pr "  int i;\n";
9624            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9625            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9626            pr "    free (r[i]);\n";
9627            pr "    free (r[i+1]);\n";
9628            pr "  }\n";
9629            pr "  free (r);\n";
9630            pr "  return rv;\n"
9631        | RBufferOut _ ->
9632            pr "  VALUE rv = rb_str_new (r, size);\n";
9633            pr "  free (r);\n";
9634            pr "  return rv;\n";
9635       );
9636
9637       pr "}\n";
9638       pr "\n"
9639   ) all_functions;
9640
9641   pr "\
9642 /* Initialize the module. */
9643 void Init__guestfs ()
9644 {
9645   m_guestfs = rb_define_module (\"Guestfs\");
9646   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9647   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9648
9649   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9650   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9651
9652 ";
9653   (* Define the rest of the methods. *)
9654   List.iter (
9655     fun (name, style, _, _, _, _, _) ->
9656       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9657       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9658   ) all_functions;
9659
9660   pr "}\n"
9661
9662 (* Ruby code to return a struct. *)
9663 and generate_ruby_struct_code typ cols =
9664   pr "  VALUE rv = rb_hash_new ();\n";
9665   List.iter (
9666     function
9667     | name, FString ->
9668         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9669     | name, FBuffer ->
9670         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9671     | name, FUUID ->
9672         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9673     | name, (FBytes|FUInt64) ->
9674         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9675     | name, FInt64 ->
9676         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9677     | name, FUInt32 ->
9678         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9679     | name, FInt32 ->
9680         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9681     | name, FOptPercent ->
9682         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9683     | name, FChar -> (* XXX wrong? *)
9684         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9685   ) cols;
9686   pr "  guestfs_free_%s (r);\n" typ;
9687   pr "  return rv;\n"
9688
9689 (* Ruby code to return a struct list. *)
9690 and generate_ruby_struct_list_code typ cols =
9691   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9692   pr "  int i;\n";
9693   pr "  for (i = 0; i < r->len; ++i) {\n";
9694   pr "    VALUE hv = rb_hash_new ();\n";
9695   List.iter (
9696     function
9697     | name, FString ->
9698         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9699     | name, FBuffer ->
9700         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
9701     | name, FUUID ->
9702         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9703     | name, (FBytes|FUInt64) ->
9704         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9705     | name, FInt64 ->
9706         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9707     | name, FUInt32 ->
9708         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9709     | name, FInt32 ->
9710         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9711     | name, FOptPercent ->
9712         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9713     | name, FChar -> (* XXX wrong? *)
9714         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9715   ) cols;
9716   pr "    rb_ary_push (rv, hv);\n";
9717   pr "  }\n";
9718   pr "  guestfs_free_%s_list (r);\n" typ;
9719   pr "  return rv;\n"
9720
9721 (* Generate Java bindings GuestFS.java file. *)
9722 and generate_java_java () =
9723   generate_header CStyle LGPLv2plus;
9724
9725   pr "\
9726 package com.redhat.et.libguestfs;
9727
9728 import java.util.HashMap;
9729 import com.redhat.et.libguestfs.LibGuestFSException;
9730 import com.redhat.et.libguestfs.PV;
9731 import com.redhat.et.libguestfs.VG;
9732 import com.redhat.et.libguestfs.LV;
9733 import com.redhat.et.libguestfs.Stat;
9734 import com.redhat.et.libguestfs.StatVFS;
9735 import com.redhat.et.libguestfs.IntBool;
9736 import com.redhat.et.libguestfs.Dirent;
9737
9738 /**
9739  * The GuestFS object is a libguestfs handle.
9740  *
9741  * @author rjones
9742  */
9743 public class GuestFS {
9744   // Load the native code.
9745   static {
9746     System.loadLibrary (\"guestfs_jni\");
9747   }
9748
9749   /**
9750    * The native guestfs_h pointer.
9751    */
9752   long g;
9753
9754   /**
9755    * Create a libguestfs handle.
9756    *
9757    * @throws LibGuestFSException
9758    */
9759   public GuestFS () throws LibGuestFSException
9760   {
9761     g = _create ();
9762   }
9763   private native long _create () throws LibGuestFSException;
9764
9765   /**
9766    * Close a libguestfs handle.
9767    *
9768    * You can also leave handles to be collected by the garbage
9769    * collector, but this method ensures that the resources used
9770    * by the handle are freed up immediately.  If you call any
9771    * other methods after closing the handle, you will get an
9772    * exception.
9773    *
9774    * @throws LibGuestFSException
9775    */
9776   public void close () throws LibGuestFSException
9777   {
9778     if (g != 0)
9779       _close (g);
9780     g = 0;
9781   }
9782   private native void _close (long g) throws LibGuestFSException;
9783
9784   public void finalize () throws LibGuestFSException
9785   {
9786     close ();
9787   }
9788
9789 ";
9790
9791   List.iter (
9792     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9793       if not (List.mem NotInDocs flags); then (
9794         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9795         let doc =
9796           if List.mem ProtocolLimitWarning flags then
9797             doc ^ "\n\n" ^ protocol_limit_warning
9798           else doc in
9799         let doc =
9800           if List.mem DangerWillRobinson flags then
9801             doc ^ "\n\n" ^ danger_will_robinson
9802           else doc in
9803         let doc =
9804           match deprecation_notice flags with
9805           | None -> doc
9806           | Some txt -> doc ^ "\n\n" ^ txt in
9807         let doc = pod2text ~width:60 name doc in
9808         let doc = List.map (            (* RHBZ#501883 *)
9809           function
9810           | "" -> "<p>"
9811           | nonempty -> nonempty
9812         ) doc in
9813         let doc = String.concat "\n   * " doc in
9814
9815         pr "  /**\n";
9816         pr "   * %s\n" shortdesc;
9817         pr "   * <p>\n";
9818         pr "   * %s\n" doc;
9819         pr "   * @throws LibGuestFSException\n";
9820         pr "   */\n";
9821         pr "  ";
9822       );
9823       generate_java_prototype ~public:true ~semicolon:false name style;
9824       pr "\n";
9825       pr "  {\n";
9826       pr "    if (g == 0)\n";
9827       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9828         name;
9829       pr "    ";
9830       if fst style <> RErr then pr "return ";
9831       pr "_%s " name;
9832       generate_java_call_args ~handle:"g" (snd style);
9833       pr ";\n";
9834       pr "  }\n";
9835       pr "  ";
9836       generate_java_prototype ~privat:true ~native:true name style;
9837       pr "\n";
9838       pr "\n";
9839   ) all_functions;
9840
9841   pr "}\n"
9842
9843 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9844 and generate_java_call_args ~handle args =
9845   pr "(%s" handle;
9846   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9847   pr ")"
9848
9849 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9850     ?(semicolon=true) name style =
9851   if privat then pr "private ";
9852   if public then pr "public ";
9853   if native then pr "native ";
9854
9855   (* return type *)
9856   (match fst style with
9857    | RErr -> pr "void ";
9858    | RInt _ -> pr "int ";
9859    | RInt64 _ -> pr "long ";
9860    | RBool _ -> pr "boolean ";
9861    | RConstString _ | RConstOptString _ | RString _
9862    | RBufferOut _ -> pr "String ";
9863    | RStringList _ -> pr "String[] ";
9864    | RStruct (_, typ) ->
9865        let name = java_name_of_struct typ in
9866        pr "%s " name;
9867    | RStructList (_, typ) ->
9868        let name = java_name_of_struct typ in
9869        pr "%s[] " name;
9870    | RHashtable _ -> pr "HashMap<String,String> ";
9871   );
9872
9873   if native then pr "_%s " name else pr "%s " name;
9874   pr "(";
9875   let needs_comma = ref false in
9876   if native then (
9877     pr "long g";
9878     needs_comma := true
9879   );
9880
9881   (* args *)
9882   List.iter (
9883     fun arg ->
9884       if !needs_comma then pr ", ";
9885       needs_comma := true;
9886
9887       match arg with
9888       | Pathname n
9889       | Device n | Dev_or_Path n
9890       | String n
9891       | OptString n
9892       | FileIn n
9893       | FileOut n ->
9894           pr "String %s" n
9895       | StringList n | DeviceList n ->
9896           pr "String[] %s" n
9897       | Bool n ->
9898           pr "boolean %s" n
9899       | Int n ->
9900           pr "int %s" n
9901       | Int64 n ->
9902           pr "long %s" n
9903   ) (snd style);
9904
9905   pr ")\n";
9906   pr "    throws LibGuestFSException";
9907   if semicolon then pr ";"
9908
9909 and generate_java_struct jtyp cols () =
9910   generate_header CStyle LGPLv2plus;
9911
9912   pr "\
9913 package com.redhat.et.libguestfs;
9914
9915 /**
9916  * Libguestfs %s structure.
9917  *
9918  * @author rjones
9919  * @see GuestFS
9920  */
9921 public class %s {
9922 " jtyp jtyp;
9923
9924   List.iter (
9925     function
9926     | name, FString
9927     | name, FUUID
9928     | name, FBuffer -> pr "  public String %s;\n" name
9929     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9930     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9931     | name, FChar -> pr "  public char %s;\n" name
9932     | name, FOptPercent ->
9933         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9934         pr "  public float %s;\n" name
9935   ) cols;
9936
9937   pr "}\n"
9938
9939 and generate_java_c () =
9940   generate_header CStyle LGPLv2plus;
9941
9942   pr "\
9943 #include <stdio.h>
9944 #include <stdlib.h>
9945 #include <string.h>
9946
9947 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9948 #include \"guestfs.h\"
9949
9950 /* Note that this function returns.  The exception is not thrown
9951  * until after the wrapper function returns.
9952  */
9953 static void
9954 throw_exception (JNIEnv *env, const char *msg)
9955 {
9956   jclass cl;
9957   cl = (*env)->FindClass (env,
9958                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9959   (*env)->ThrowNew (env, cl, msg);
9960 }
9961
9962 JNIEXPORT jlong JNICALL
9963 Java_com_redhat_et_libguestfs_GuestFS__1create
9964   (JNIEnv *env, jobject obj)
9965 {
9966   guestfs_h *g;
9967
9968   g = guestfs_create ();
9969   if (g == NULL) {
9970     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9971     return 0;
9972   }
9973   guestfs_set_error_handler (g, NULL, NULL);
9974   return (jlong) (long) g;
9975 }
9976
9977 JNIEXPORT void JNICALL
9978 Java_com_redhat_et_libguestfs_GuestFS__1close
9979   (JNIEnv *env, jobject obj, jlong jg)
9980 {
9981   guestfs_h *g = (guestfs_h *) (long) jg;
9982   guestfs_close (g);
9983 }
9984
9985 ";
9986
9987   List.iter (
9988     fun (name, style, _, _, _, _, _) ->
9989       pr "JNIEXPORT ";
9990       (match fst style with
9991        | RErr -> pr "void ";
9992        | RInt _ -> pr "jint ";
9993        | RInt64 _ -> pr "jlong ";
9994        | RBool _ -> pr "jboolean ";
9995        | RConstString _ | RConstOptString _ | RString _
9996        | RBufferOut _ -> pr "jstring ";
9997        | RStruct _ | RHashtable _ ->
9998            pr "jobject ";
9999        | RStringList _ | RStructList _ ->
10000            pr "jobjectArray ";
10001       );
10002       pr "JNICALL\n";
10003       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10004       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10005       pr "\n";
10006       pr "  (JNIEnv *env, jobject obj, jlong jg";
10007       List.iter (
10008         function
10009         | Pathname n
10010         | Device n | Dev_or_Path n
10011         | String n
10012         | OptString n
10013         | FileIn n
10014         | FileOut n ->
10015             pr ", jstring j%s" n
10016         | StringList n | DeviceList n ->
10017             pr ", jobjectArray j%s" n
10018         | Bool n ->
10019             pr ", jboolean j%s" n
10020         | Int n ->
10021             pr ", jint j%s" n
10022         | Int64 n ->
10023             pr ", jlong j%s" n
10024       ) (snd style);
10025       pr ")\n";
10026       pr "{\n";
10027       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10028       let error_code, no_ret =
10029         match fst style with
10030         | RErr -> pr "  int r;\n"; "-1", ""
10031         | RBool _
10032         | RInt _ -> pr "  int r;\n"; "-1", "0"
10033         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10034         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10035         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10036         | RString _ ->
10037             pr "  jstring jr;\n";
10038             pr "  char *r;\n"; "NULL", "NULL"
10039         | RStringList _ ->
10040             pr "  jobjectArray jr;\n";
10041             pr "  int r_len;\n";
10042             pr "  jclass cl;\n";
10043             pr "  jstring jstr;\n";
10044             pr "  char **r;\n"; "NULL", "NULL"
10045         | RStruct (_, typ) ->
10046             pr "  jobject jr;\n";
10047             pr "  jclass cl;\n";
10048             pr "  jfieldID fl;\n";
10049             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10050         | RStructList (_, typ) ->
10051             pr "  jobjectArray jr;\n";
10052             pr "  jclass cl;\n";
10053             pr "  jfieldID fl;\n";
10054             pr "  jobject jfl;\n";
10055             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10056         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10057         | RBufferOut _ ->
10058             pr "  jstring jr;\n";
10059             pr "  char *r;\n";
10060             pr "  size_t size;\n";
10061             "NULL", "NULL" in
10062       List.iter (
10063         function
10064         | Pathname n
10065         | Device n | Dev_or_Path n
10066         | String n
10067         | OptString n
10068         | FileIn n
10069         | FileOut n ->
10070             pr "  const char *%s;\n" n
10071         | StringList n | DeviceList n ->
10072             pr "  int %s_len;\n" n;
10073             pr "  const char **%s;\n" n
10074         | Bool n
10075         | Int n ->
10076             pr "  int %s;\n" n
10077         | Int64 n ->
10078             pr "  int64_t %s;\n" n
10079       ) (snd style);
10080
10081       let needs_i =
10082         (match fst style with
10083          | RStringList _ | RStructList _ -> true
10084          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10085          | RConstOptString _
10086          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10087           List.exists (function
10088                        | StringList _ -> true
10089                        | DeviceList _ -> true
10090                        | _ -> false) (snd style) in
10091       if needs_i then
10092         pr "  int i;\n";
10093
10094       pr "\n";
10095
10096       (* Get the parameters. *)
10097       List.iter (
10098         function
10099         | Pathname n
10100         | Device n | Dev_or_Path n
10101         | String n
10102         | FileIn n
10103         | FileOut n ->
10104             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10105         | OptString n ->
10106             (* This is completely undocumented, but Java null becomes
10107              * a NULL parameter.
10108              *)
10109             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10110         | StringList n | DeviceList n ->
10111             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10112             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10113             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10114             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10115               n;
10116             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10117             pr "  }\n";
10118             pr "  %s[%s_len] = NULL;\n" n n;
10119         | Bool n
10120         | Int n
10121         | Int64 n ->
10122             pr "  %s = j%s;\n" n n
10123       ) (snd style);
10124
10125       (* Make the call. *)
10126       pr "  r = guestfs_%s " name;
10127       generate_c_call_args ~handle:"g" style;
10128       pr ";\n";
10129
10130       (* Release the parameters. *)
10131       List.iter (
10132         function
10133         | Pathname n
10134         | Device n | Dev_or_Path n
10135         | String n
10136         | FileIn n
10137         | FileOut n ->
10138             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10139         | OptString n ->
10140             pr "  if (j%s)\n" n;
10141             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10142         | StringList n | DeviceList n ->
10143             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10144             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10145               n;
10146             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10147             pr "  }\n";
10148             pr "  free (%s);\n" n
10149         | Bool n
10150         | Int n
10151         | Int64 n -> ()
10152       ) (snd style);
10153
10154       (* Check for errors. *)
10155       pr "  if (r == %s) {\n" error_code;
10156       pr "    throw_exception (env, guestfs_last_error (g));\n";
10157       pr "    return %s;\n" no_ret;
10158       pr "  }\n";
10159
10160       (* Return value. *)
10161       (match fst style with
10162        | RErr -> ()
10163        | RInt _ -> pr "  return (jint) r;\n"
10164        | RBool _ -> pr "  return (jboolean) r;\n"
10165        | RInt64 _ -> pr "  return (jlong) r;\n"
10166        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10167        | RConstOptString _ ->
10168            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10169        | RString _ ->
10170            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10171            pr "  free (r);\n";
10172            pr "  return jr;\n"
10173        | RStringList _ ->
10174            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10175            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10176            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10177            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10178            pr "  for (i = 0; i < r_len; ++i) {\n";
10179            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10180            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10181            pr "    free (r[i]);\n";
10182            pr "  }\n";
10183            pr "  free (r);\n";
10184            pr "  return jr;\n"
10185        | RStruct (_, typ) ->
10186            let jtyp = java_name_of_struct typ in
10187            let cols = cols_of_struct typ in
10188            generate_java_struct_return typ jtyp cols
10189        | RStructList (_, typ) ->
10190            let jtyp = java_name_of_struct typ in
10191            let cols = cols_of_struct typ in
10192            generate_java_struct_list_return typ jtyp cols
10193        | RHashtable _ ->
10194            (* XXX *)
10195            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10196            pr "  return NULL;\n"
10197        | RBufferOut _ ->
10198            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10199            pr "  free (r);\n";
10200            pr "  return jr;\n"
10201       );
10202
10203       pr "}\n";
10204       pr "\n"
10205   ) all_functions
10206
10207 and generate_java_struct_return typ jtyp cols =
10208   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10209   pr "  jr = (*env)->AllocObject (env, cl);\n";
10210   List.iter (
10211     function
10212     | name, FString ->
10213         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10214         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10215     | name, FUUID ->
10216         pr "  {\n";
10217         pr "    char s[33];\n";
10218         pr "    memcpy (s, r->%s, 32);\n" name;
10219         pr "    s[32] = 0;\n";
10220         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10221         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10222         pr "  }\n";
10223     | name, FBuffer ->
10224         pr "  {\n";
10225         pr "    int len = r->%s_len;\n" name;
10226         pr "    char s[len+1];\n";
10227         pr "    memcpy (s, r->%s, len);\n" name;
10228         pr "    s[len] = 0;\n";
10229         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10230         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10231         pr "  }\n";
10232     | name, (FBytes|FUInt64|FInt64) ->
10233         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10234         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10235     | name, (FUInt32|FInt32) ->
10236         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10237         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10238     | name, FOptPercent ->
10239         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10240         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10241     | name, FChar ->
10242         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10243         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10244   ) cols;
10245   pr "  free (r);\n";
10246   pr "  return jr;\n"
10247
10248 and generate_java_struct_list_return typ jtyp cols =
10249   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10250   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10251   pr "  for (i = 0; i < r->len; ++i) {\n";
10252   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10253   List.iter (
10254     function
10255     | name, FString ->
10256         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10257         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10258     | name, FUUID ->
10259         pr "    {\n";
10260         pr "      char s[33];\n";
10261         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10262         pr "      s[32] = 0;\n";
10263         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10264         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10265         pr "    }\n";
10266     | name, FBuffer ->
10267         pr "    {\n";
10268         pr "      int len = r->val[i].%s_len;\n" name;
10269         pr "      char s[len+1];\n";
10270         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10271         pr "      s[len] = 0;\n";
10272         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10273         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10274         pr "    }\n";
10275     | name, (FBytes|FUInt64|FInt64) ->
10276         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10277         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10278     | name, (FUInt32|FInt32) ->
10279         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10280         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10281     | name, FOptPercent ->
10282         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10283         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10284     | name, FChar ->
10285         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10286         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10287   ) cols;
10288   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10289   pr "  }\n";
10290   pr "  guestfs_free_%s_list (r);\n" typ;
10291   pr "  return jr;\n"
10292
10293 and generate_java_makefile_inc () =
10294   generate_header HashStyle GPLv2plus;
10295
10296   pr "java_built_sources = \\\n";
10297   List.iter (
10298     fun (typ, jtyp) ->
10299         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10300   ) java_structs;
10301   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10302
10303 and generate_haskell_hs () =
10304   generate_header HaskellStyle LGPLv2plus;
10305
10306   (* XXX We only know how to generate partial FFI for Haskell
10307    * at the moment.  Please help out!
10308    *)
10309   let can_generate style =
10310     match style with
10311     | RErr, _
10312     | RInt _, _
10313     | RInt64 _, _ -> true
10314     | RBool _, _
10315     | RConstString _, _
10316     | RConstOptString _, _
10317     | RString _, _
10318     | RStringList _, _
10319     | RStruct _, _
10320     | RStructList _, _
10321     | RHashtable _, _
10322     | RBufferOut _, _ -> false in
10323
10324   pr "\
10325 {-# INCLUDE <guestfs.h> #-}
10326 {-# LANGUAGE ForeignFunctionInterface #-}
10327
10328 module Guestfs (
10329   create";
10330
10331   (* List out the names of the actions we want to export. *)
10332   List.iter (
10333     fun (name, style, _, _, _, _, _) ->
10334       if can_generate style then pr ",\n  %s" name
10335   ) all_functions;
10336
10337   pr "
10338   ) where
10339
10340 -- Unfortunately some symbols duplicate ones already present
10341 -- in Prelude.  We don't know which, so we hard-code a list
10342 -- here.
10343 import Prelude hiding (truncate)
10344
10345 import Foreign
10346 import Foreign.C
10347 import Foreign.C.Types
10348 import IO
10349 import Control.Exception
10350 import Data.Typeable
10351
10352 data GuestfsS = GuestfsS            -- represents the opaque C struct
10353 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10354 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10355
10356 -- XXX define properly later XXX
10357 data PV = PV
10358 data VG = VG
10359 data LV = LV
10360 data IntBool = IntBool
10361 data Stat = Stat
10362 data StatVFS = StatVFS
10363 data Hashtable = Hashtable
10364
10365 foreign import ccall unsafe \"guestfs_create\" c_create
10366   :: IO GuestfsP
10367 foreign import ccall unsafe \"&guestfs_close\" c_close
10368   :: FunPtr (GuestfsP -> IO ())
10369 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10370   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10371
10372 create :: IO GuestfsH
10373 create = do
10374   p <- c_create
10375   c_set_error_handler p nullPtr nullPtr
10376   h <- newForeignPtr c_close p
10377   return h
10378
10379 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10380   :: GuestfsP -> IO CString
10381
10382 -- last_error :: GuestfsH -> IO (Maybe String)
10383 -- last_error h = do
10384 --   str <- withForeignPtr h (\\p -> c_last_error p)
10385 --   maybePeek peekCString str
10386
10387 last_error :: GuestfsH -> IO (String)
10388 last_error h = do
10389   str <- withForeignPtr h (\\p -> c_last_error p)
10390   if (str == nullPtr)
10391     then return \"no error\"
10392     else peekCString str
10393
10394 ";
10395
10396   (* Generate wrappers for each foreign function. *)
10397   List.iter (
10398     fun (name, style, _, _, _, _, _) ->
10399       if can_generate style then (
10400         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10401         pr "  :: ";
10402         generate_haskell_prototype ~handle:"GuestfsP" style;
10403         pr "\n";
10404         pr "\n";
10405         pr "%s :: " name;
10406         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10407         pr "\n";
10408         pr "%s %s = do\n" name
10409           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10410         pr "  r <- ";
10411         (* Convert pointer arguments using with* functions. *)
10412         List.iter (
10413           function
10414           | FileIn n
10415           | FileOut n
10416           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10417           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10418           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10419           | Bool _ | Int _ | Int64 _ -> ()
10420         ) (snd style);
10421         (* Convert integer arguments. *)
10422         let args =
10423           List.map (
10424             function
10425             | Bool n -> sprintf "(fromBool %s)" n
10426             | Int n -> sprintf "(fromIntegral %s)" n
10427             | Int64 n -> sprintf "(fromIntegral %s)" n
10428             | FileIn n | FileOut n
10429             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10430           ) (snd style) in
10431         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10432           (String.concat " " ("p" :: args));
10433         (match fst style with
10434          | RErr | RInt _ | RInt64 _ | RBool _ ->
10435              pr "  if (r == -1)\n";
10436              pr "    then do\n";
10437              pr "      err <- last_error h\n";
10438              pr "      fail err\n";
10439          | RConstString _ | RConstOptString _ | RString _
10440          | RStringList _ | RStruct _
10441          | RStructList _ | RHashtable _ | RBufferOut _ ->
10442              pr "  if (r == nullPtr)\n";
10443              pr "    then do\n";
10444              pr "      err <- last_error h\n";
10445              pr "      fail err\n";
10446         );
10447         (match fst style with
10448          | RErr ->
10449              pr "    else return ()\n"
10450          | RInt _ ->
10451              pr "    else return (fromIntegral r)\n"
10452          | RInt64 _ ->
10453              pr "    else return (fromIntegral r)\n"
10454          | RBool _ ->
10455              pr "    else return (toBool r)\n"
10456          | RConstString _
10457          | RConstOptString _
10458          | RString _
10459          | RStringList _
10460          | RStruct _
10461          | RStructList _
10462          | RHashtable _
10463          | RBufferOut _ ->
10464              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10465         );
10466         pr "\n";
10467       )
10468   ) all_functions
10469
10470 and generate_haskell_prototype ~handle ?(hs = false) style =
10471   pr "%s -> " handle;
10472   let string = if hs then "String" else "CString" in
10473   let int = if hs then "Int" else "CInt" in
10474   let bool = if hs then "Bool" else "CInt" in
10475   let int64 = if hs then "Integer" else "Int64" in
10476   List.iter (
10477     fun arg ->
10478       (match arg with
10479        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10480        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10481        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10482        | Bool _ -> pr "%s" bool
10483        | Int _ -> pr "%s" int
10484        | Int64 _ -> pr "%s" int
10485        | FileIn _ -> pr "%s" string
10486        | FileOut _ -> pr "%s" string
10487       );
10488       pr " -> ";
10489   ) (snd style);
10490   pr "IO (";
10491   (match fst style with
10492    | RErr -> if not hs then pr "CInt"
10493    | RInt _ -> pr "%s" int
10494    | RInt64 _ -> pr "%s" int64
10495    | RBool _ -> pr "%s" bool
10496    | RConstString _ -> pr "%s" string
10497    | RConstOptString _ -> pr "Maybe %s" string
10498    | RString _ -> pr "%s" string
10499    | RStringList _ -> pr "[%s]" string
10500    | RStruct (_, typ) ->
10501        let name = java_name_of_struct typ in
10502        pr "%s" name
10503    | RStructList (_, typ) ->
10504        let name = java_name_of_struct typ in
10505        pr "[%s]" name
10506    | RHashtable _ -> pr "Hashtable"
10507    | RBufferOut _ -> pr "%s" string
10508   );
10509   pr ")"
10510
10511 and generate_csharp () =
10512   generate_header CPlusPlusStyle LGPLv2plus;
10513
10514   (* XXX Make this configurable by the C# assembly users. *)
10515   let library = "libguestfs.so.0" in
10516
10517   pr "\
10518 // These C# bindings are highly experimental at present.
10519 //
10520 // Firstly they only work on Linux (ie. Mono).  In order to get them
10521 // to work on Windows (ie. .Net) you would need to port the library
10522 // itself to Windows first.
10523 //
10524 // The second issue is that some calls are known to be incorrect and
10525 // can cause Mono to segfault.  Particularly: calls which pass or
10526 // return string[], or return any structure value.  This is because
10527 // we haven't worked out the correct way to do this from C#.
10528 //
10529 // The third issue is that when compiling you get a lot of warnings.
10530 // We are not sure whether the warnings are important or not.
10531 //
10532 // Fourthly we do not routinely build or test these bindings as part
10533 // of the make && make check cycle, which means that regressions might
10534 // go unnoticed.
10535 //
10536 // Suggestions and patches are welcome.
10537
10538 // To compile:
10539 //
10540 // gmcs Libguestfs.cs
10541 // mono Libguestfs.exe
10542 //
10543 // (You'll probably want to add a Test class / static main function
10544 // otherwise this won't do anything useful).
10545
10546 using System;
10547 using System.IO;
10548 using System.Runtime.InteropServices;
10549 using System.Runtime.Serialization;
10550 using System.Collections;
10551
10552 namespace Guestfs
10553 {
10554   class Error : System.ApplicationException
10555   {
10556     public Error (string message) : base (message) {}
10557     protected Error (SerializationInfo info, StreamingContext context) {}
10558   }
10559
10560   class Guestfs
10561   {
10562     IntPtr _handle;
10563
10564     [DllImport (\"%s\")]
10565     static extern IntPtr guestfs_create ();
10566
10567     public Guestfs ()
10568     {
10569       _handle = guestfs_create ();
10570       if (_handle == IntPtr.Zero)
10571         throw new Error (\"could not create guestfs handle\");
10572     }
10573
10574     [DllImport (\"%s\")]
10575     static extern void guestfs_close (IntPtr h);
10576
10577     ~Guestfs ()
10578     {
10579       guestfs_close (_handle);
10580     }
10581
10582     [DllImport (\"%s\")]
10583     static extern string guestfs_last_error (IntPtr h);
10584
10585 " library library library;
10586
10587   (* Generate C# structure bindings.  We prefix struct names with
10588    * underscore because C# cannot have conflicting struct names and
10589    * method names (eg. "class stat" and "stat").
10590    *)
10591   List.iter (
10592     fun (typ, cols) ->
10593       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10594       pr "    public class _%s {\n" typ;
10595       List.iter (
10596         function
10597         | name, FChar -> pr "      char %s;\n" name
10598         | name, FString -> pr "      string %s;\n" name
10599         | name, FBuffer ->
10600             pr "      uint %s_len;\n" name;
10601             pr "      string %s;\n" name
10602         | name, FUUID ->
10603             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10604             pr "      string %s;\n" name
10605         | name, FUInt32 -> pr "      uint %s;\n" name
10606         | name, FInt32 -> pr "      int %s;\n" name
10607         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10608         | name, FInt64 -> pr "      long %s;\n" name
10609         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10610       ) cols;
10611       pr "    }\n";
10612       pr "\n"
10613   ) structs;
10614
10615   (* Generate C# function bindings. *)
10616   List.iter (
10617     fun (name, style, _, _, _, shortdesc, _) ->
10618       let rec csharp_return_type () =
10619         match fst style with
10620         | RErr -> "void"
10621         | RBool n -> "bool"
10622         | RInt n -> "int"
10623         | RInt64 n -> "long"
10624         | RConstString n
10625         | RConstOptString n
10626         | RString n
10627         | RBufferOut n -> "string"
10628         | RStruct (_,n) -> "_" ^ n
10629         | RHashtable n -> "Hashtable"
10630         | RStringList n -> "string[]"
10631         | RStructList (_,n) -> sprintf "_%s[]" n
10632
10633       and c_return_type () =
10634         match fst style with
10635         | RErr
10636         | RBool _
10637         | RInt _ -> "int"
10638         | RInt64 _ -> "long"
10639         | RConstString _
10640         | RConstOptString _
10641         | RString _
10642         | RBufferOut _ -> "string"
10643         | RStruct (_,n) -> "_" ^ n
10644         | RHashtable _
10645         | RStringList _ -> "string[]"
10646         | RStructList (_,n) -> sprintf "_%s[]" n
10647
10648       and c_error_comparison () =
10649         match fst style with
10650         | RErr
10651         | RBool _
10652         | RInt _
10653         | RInt64 _ -> "== -1"
10654         | RConstString _
10655         | RConstOptString _
10656         | RString _
10657         | RBufferOut _
10658         | RStruct (_,_)
10659         | RHashtable _
10660         | RStringList _
10661         | RStructList (_,_) -> "== null"
10662
10663       and generate_extern_prototype () =
10664         pr "    static extern %s guestfs_%s (IntPtr h"
10665           (c_return_type ()) name;
10666         List.iter (
10667           function
10668           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10669           | FileIn n | FileOut n ->
10670               pr ", [In] string %s" n
10671           | StringList n | DeviceList n ->
10672               pr ", [In] string[] %s" n
10673           | Bool n ->
10674               pr ", bool %s" n
10675           | Int n ->
10676               pr ", int %s" n
10677           | Int64 n ->
10678               pr ", long %s" n
10679         ) (snd style);
10680         pr ");\n"
10681
10682       and generate_public_prototype () =
10683         pr "    public %s %s (" (csharp_return_type ()) name;
10684         let comma = ref false in
10685         let next () =
10686           if !comma then pr ", ";
10687           comma := true
10688         in
10689         List.iter (
10690           function
10691           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10692           | FileIn n | FileOut n ->
10693               next (); pr "string %s" n
10694           | StringList n | DeviceList n ->
10695               next (); pr "string[] %s" n
10696           | Bool n ->
10697               next (); pr "bool %s" n
10698           | Int n ->
10699               next (); pr "int %s" n
10700           | Int64 n ->
10701               next (); pr "long %s" n
10702         ) (snd style);
10703         pr ")\n"
10704
10705       and generate_call () =
10706         pr "guestfs_%s (_handle" name;
10707         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10708         pr ");\n";
10709       in
10710
10711       pr "    [DllImport (\"%s\")]\n" library;
10712       generate_extern_prototype ();
10713       pr "\n";
10714       pr "    /// <summary>\n";
10715       pr "    /// %s\n" shortdesc;
10716       pr "    /// </summary>\n";
10717       generate_public_prototype ();
10718       pr "    {\n";
10719       pr "      %s r;\n" (c_return_type ());
10720       pr "      r = ";
10721       generate_call ();
10722       pr "      if (r %s)\n" (c_error_comparison ());
10723       pr "        throw new Error (guestfs_last_error (_handle));\n";
10724       (match fst style with
10725        | RErr -> ()
10726        | RBool _ ->
10727            pr "      return r != 0 ? true : false;\n"
10728        | RHashtable _ ->
10729            pr "      Hashtable rr = new Hashtable ();\n";
10730            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10731            pr "        rr.Add (r[i], r[i+1]);\n";
10732            pr "      return rr;\n"
10733        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10734        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10735        | RStructList _ ->
10736            pr "      return r;\n"
10737       );
10738       pr "    }\n";
10739       pr "\n";
10740   ) all_functions_sorted;
10741
10742   pr "  }
10743 }
10744 "
10745
10746 and generate_bindtests () =
10747   generate_header CStyle LGPLv2plus;
10748
10749   pr "\
10750 #include <stdio.h>
10751 #include <stdlib.h>
10752 #include <inttypes.h>
10753 #include <string.h>
10754
10755 #include \"guestfs.h\"
10756 #include \"guestfs-internal.h\"
10757 #include \"guestfs-internal-actions.h\"
10758 #include \"guestfs_protocol.h\"
10759
10760 #define error guestfs_error
10761 #define safe_calloc guestfs_safe_calloc
10762 #define safe_malloc guestfs_safe_malloc
10763
10764 static void
10765 print_strings (char *const *argv)
10766 {
10767   int argc;
10768
10769   printf (\"[\");
10770   for (argc = 0; argv[argc] != NULL; ++argc) {
10771     if (argc > 0) printf (\", \");
10772     printf (\"\\\"%%s\\\"\", argv[argc]);
10773   }
10774   printf (\"]\\n\");
10775 }
10776
10777 /* The test0 function prints its parameters to stdout. */
10778 ";
10779
10780   let test0, tests =
10781     match test_functions with
10782     | [] -> assert false
10783     | test0 :: tests -> test0, tests in
10784
10785   let () =
10786     let (name, style, _, _, _, _, _) = test0 in
10787     generate_prototype ~extern:false ~semicolon:false ~newline:true
10788       ~handle:"g" ~prefix:"guestfs__" name style;
10789     pr "{\n";
10790     List.iter (
10791       function
10792       | Pathname n
10793       | Device n | Dev_or_Path n
10794       | String n
10795       | FileIn n
10796       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10797       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10798       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10799       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10800       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10801       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10802     ) (snd style);
10803     pr "  /* Java changes stdout line buffering so we need this: */\n";
10804     pr "  fflush (stdout);\n";
10805     pr "  return 0;\n";
10806     pr "}\n";
10807     pr "\n" in
10808
10809   List.iter (
10810     fun (name, style, _, _, _, _, _) ->
10811       if String.sub name (String.length name - 3) 3 <> "err" then (
10812         pr "/* Test normal return. */\n";
10813         generate_prototype ~extern:false ~semicolon:false ~newline:true
10814           ~handle:"g" ~prefix:"guestfs__" name style;
10815         pr "{\n";
10816         (match fst style with
10817          | RErr ->
10818              pr "  return 0;\n"
10819          | RInt _ ->
10820              pr "  int r;\n";
10821              pr "  sscanf (val, \"%%d\", &r);\n";
10822              pr "  return r;\n"
10823          | RInt64 _ ->
10824              pr "  int64_t r;\n";
10825              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10826              pr "  return r;\n"
10827          | RBool _ ->
10828              pr "  return STREQ (val, \"true\");\n"
10829          | RConstString _
10830          | RConstOptString _ ->
10831              (* Can't return the input string here.  Return a static
10832               * string so we ensure we get a segfault if the caller
10833               * tries to free it.
10834               *)
10835              pr "  return \"static string\";\n"
10836          | RString _ ->
10837              pr "  return strdup (val);\n"
10838          | RStringList _ ->
10839              pr "  char **strs;\n";
10840              pr "  int n, i;\n";
10841              pr "  sscanf (val, \"%%d\", &n);\n";
10842              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10843              pr "  for (i = 0; i < n; ++i) {\n";
10844              pr "    strs[i] = safe_malloc (g, 16);\n";
10845              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10846              pr "  }\n";
10847              pr "  strs[n] = NULL;\n";
10848              pr "  return strs;\n"
10849          | RStruct (_, typ) ->
10850              pr "  struct guestfs_%s *r;\n" typ;
10851              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10852              pr "  return r;\n"
10853          | RStructList (_, typ) ->
10854              pr "  struct guestfs_%s_list *r;\n" typ;
10855              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10856              pr "  sscanf (val, \"%%d\", &r->len);\n";
10857              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10858              pr "  return r;\n"
10859          | RHashtable _ ->
10860              pr "  char **strs;\n";
10861              pr "  int n, i;\n";
10862              pr "  sscanf (val, \"%%d\", &n);\n";
10863              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10864              pr "  for (i = 0; i < n; ++i) {\n";
10865              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10866              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10867              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10868              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10869              pr "  }\n";
10870              pr "  strs[n*2] = NULL;\n";
10871              pr "  return strs;\n"
10872          | RBufferOut _ ->
10873              pr "  return strdup (val);\n"
10874         );
10875         pr "}\n";
10876         pr "\n"
10877       ) else (
10878         pr "/* Test error return. */\n";
10879         generate_prototype ~extern:false ~semicolon:false ~newline:true
10880           ~handle:"g" ~prefix:"guestfs__" name style;
10881         pr "{\n";
10882         pr "  error (g, \"error\");\n";
10883         (match fst style with
10884          | RErr | RInt _ | RInt64 _ | RBool _ ->
10885              pr "  return -1;\n"
10886          | RConstString _ | RConstOptString _
10887          | RString _ | RStringList _ | RStruct _
10888          | RStructList _
10889          | RHashtable _
10890          | RBufferOut _ ->
10891              pr "  return NULL;\n"
10892         );
10893         pr "}\n";
10894         pr "\n"
10895       )
10896   ) tests
10897
10898 and generate_ocaml_bindtests () =
10899   generate_header OCamlStyle GPLv2plus;
10900
10901   pr "\
10902 let () =
10903   let g = Guestfs.create () in
10904 ";
10905
10906   let mkargs args =
10907     String.concat " " (
10908       List.map (
10909         function
10910         | CallString s -> "\"" ^ s ^ "\""
10911         | CallOptString None -> "None"
10912         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10913         | CallStringList xs ->
10914             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10915         | CallInt i when i >= 0 -> string_of_int i
10916         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10917         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10918         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10919         | CallBool b -> string_of_bool b
10920       ) args
10921     )
10922   in
10923
10924   generate_lang_bindtests (
10925     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10926   );
10927
10928   pr "print_endline \"EOF\"\n"
10929
10930 and generate_perl_bindtests () =
10931   pr "#!/usr/bin/perl -w\n";
10932   generate_header HashStyle GPLv2plus;
10933
10934   pr "\
10935 use strict;
10936
10937 use Sys::Guestfs;
10938
10939 my $g = Sys::Guestfs->new ();
10940 ";
10941
10942   let mkargs args =
10943     String.concat ", " (
10944       List.map (
10945         function
10946         | CallString s -> "\"" ^ s ^ "\""
10947         | CallOptString None -> "undef"
10948         | CallOptString (Some s) -> sprintf "\"%s\"" s
10949         | CallStringList xs ->
10950             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10951         | CallInt i -> string_of_int i
10952         | CallInt64 i -> Int64.to_string i
10953         | CallBool b -> if b then "1" else "0"
10954       ) args
10955     )
10956   in
10957
10958   generate_lang_bindtests (
10959     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10960   );
10961
10962   pr "print \"EOF\\n\"\n"
10963
10964 and generate_python_bindtests () =
10965   generate_header HashStyle GPLv2plus;
10966
10967   pr "\
10968 import guestfs
10969
10970 g = guestfs.GuestFS ()
10971 ";
10972
10973   let mkargs args =
10974     String.concat ", " (
10975       List.map (
10976         function
10977         | CallString s -> "\"" ^ s ^ "\""
10978         | CallOptString None -> "None"
10979         | CallOptString (Some s) -> sprintf "\"%s\"" s
10980         | CallStringList xs ->
10981             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10982         | CallInt i -> string_of_int i
10983         | CallInt64 i -> Int64.to_string i
10984         | CallBool b -> if b then "1" else "0"
10985       ) args
10986     )
10987   in
10988
10989   generate_lang_bindtests (
10990     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10991   );
10992
10993   pr "print \"EOF\"\n"
10994
10995 and generate_ruby_bindtests () =
10996   generate_header HashStyle GPLv2plus;
10997
10998   pr "\
10999 require 'guestfs'
11000
11001 g = Guestfs::create()
11002 ";
11003
11004   let mkargs args =
11005     String.concat ", " (
11006       List.map (
11007         function
11008         | CallString s -> "\"" ^ s ^ "\""
11009         | CallOptString None -> "nil"
11010         | CallOptString (Some s) -> sprintf "\"%s\"" s
11011         | CallStringList xs ->
11012             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11013         | CallInt i -> string_of_int i
11014         | CallInt64 i -> Int64.to_string i
11015         | CallBool b -> string_of_bool b
11016       ) args
11017     )
11018   in
11019
11020   generate_lang_bindtests (
11021     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11022   );
11023
11024   pr "print \"EOF\\n\"\n"
11025
11026 and generate_java_bindtests () =
11027   generate_header CStyle GPLv2plus;
11028
11029   pr "\
11030 import com.redhat.et.libguestfs.*;
11031
11032 public class Bindtests {
11033     public static void main (String[] argv)
11034     {
11035         try {
11036             GuestFS g = new GuestFS ();
11037 ";
11038
11039   let mkargs args =
11040     String.concat ", " (
11041       List.map (
11042         function
11043         | CallString s -> "\"" ^ s ^ "\""
11044         | CallOptString None -> "null"
11045         | CallOptString (Some s) -> sprintf "\"%s\"" s
11046         | CallStringList xs ->
11047             "new String[]{" ^
11048               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11049         | CallInt i -> string_of_int i
11050         | CallInt64 i -> Int64.to_string i
11051         | CallBool b -> string_of_bool b
11052       ) args
11053     )
11054   in
11055
11056   generate_lang_bindtests (
11057     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11058   );
11059
11060   pr "
11061             System.out.println (\"EOF\");
11062         }
11063         catch (Exception exn) {
11064             System.err.println (exn);
11065             System.exit (1);
11066         }
11067     }
11068 }
11069 "
11070
11071 and generate_haskell_bindtests () =
11072   generate_header HaskellStyle GPLv2plus;
11073
11074   pr "\
11075 module Bindtests where
11076 import qualified Guestfs
11077
11078 main = do
11079   g <- Guestfs.create
11080 ";
11081
11082   let mkargs args =
11083     String.concat " " (
11084       List.map (
11085         function
11086         | CallString s -> "\"" ^ s ^ "\""
11087         | CallOptString None -> "Nothing"
11088         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11089         | CallStringList xs ->
11090             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11091         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11092         | CallInt i -> string_of_int i
11093         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11094         | CallInt64 i -> Int64.to_string i
11095         | CallBool true -> "True"
11096         | CallBool false -> "False"
11097       ) args
11098     )
11099   in
11100
11101   generate_lang_bindtests (
11102     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11103   );
11104
11105   pr "  putStrLn \"EOF\"\n"
11106
11107 (* Language-independent bindings tests - we do it this way to
11108  * ensure there is parity in testing bindings across all languages.
11109  *)
11110 and generate_lang_bindtests call =
11111   call "test0" [CallString "abc"; CallOptString (Some "def");
11112                 CallStringList []; CallBool false;
11113                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11114   call "test0" [CallString "abc"; CallOptString None;
11115                 CallStringList []; CallBool false;
11116                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11117   call "test0" [CallString ""; CallOptString (Some "def");
11118                 CallStringList []; CallBool false;
11119                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11120   call "test0" [CallString ""; CallOptString (Some "");
11121                 CallStringList []; CallBool false;
11122                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11123   call "test0" [CallString "abc"; CallOptString (Some "def");
11124                 CallStringList ["1"]; CallBool false;
11125                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11126   call "test0" [CallString "abc"; CallOptString (Some "def");
11127                 CallStringList ["1"; "2"]; CallBool false;
11128                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11129   call "test0" [CallString "abc"; CallOptString (Some "def");
11130                 CallStringList ["1"]; CallBool true;
11131                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11132   call "test0" [CallString "abc"; CallOptString (Some "def");
11133                 CallStringList ["1"]; CallBool false;
11134                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11135   call "test0" [CallString "abc"; CallOptString (Some "def");
11136                 CallStringList ["1"]; CallBool false;
11137                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11138   call "test0" [CallString "abc"; CallOptString (Some "def");
11139                 CallStringList ["1"]; CallBool false;
11140                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11141   call "test0" [CallString "abc"; CallOptString (Some "def");
11142                 CallStringList ["1"]; CallBool false;
11143                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11144   call "test0" [CallString "abc"; CallOptString (Some "def");
11145                 CallStringList ["1"]; CallBool false;
11146                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11147   call "test0" [CallString "abc"; CallOptString (Some "def");
11148                 CallStringList ["1"]; CallBool false;
11149                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11150
11151 (* XXX Add here tests of the return and error functions. *)
11152
11153 (* Code to generator bindings for virt-inspector.  Currently only
11154  * implemented for OCaml code (for virt-p2v 2.0).
11155  *)
11156 let rng_input = "inspector/virt-inspector.rng"
11157
11158 (* Read the input file and parse it into internal structures.  This is
11159  * by no means a complete RELAX NG parser, but is just enough to be
11160  * able to parse the specific input file.
11161  *)
11162 type rng =
11163   | Element of string * rng list        (* <element name=name/> *)
11164   | Attribute of string * rng list        (* <attribute name=name/> *)
11165   | Interleave of rng list                (* <interleave/> *)
11166   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11167   | OneOrMore of rng                        (* <oneOrMore/> *)
11168   | Optional of rng                        (* <optional/> *)
11169   | Choice of string list                (* <choice><value/>*</choice> *)
11170   | Value of string                        (* <value>str</value> *)
11171   | Text                                (* <text/> *)
11172
11173 let rec string_of_rng = function
11174   | Element (name, xs) ->
11175       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11176   | Attribute (name, xs) ->
11177       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11178   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11179   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11180   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11181   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11182   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11183   | Value value -> "Value \"" ^ value ^ "\""
11184   | Text -> "Text"
11185
11186 and string_of_rng_list xs =
11187   String.concat ", " (List.map string_of_rng xs)
11188
11189 let rec parse_rng ?defines context = function
11190   | [] -> []
11191   | Xml.Element ("element", ["name", name], children) :: rest ->
11192       Element (name, parse_rng ?defines context children)
11193       :: parse_rng ?defines context rest
11194   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11195       Attribute (name, parse_rng ?defines context children)
11196       :: parse_rng ?defines context rest
11197   | Xml.Element ("interleave", [], children) :: rest ->
11198       Interleave (parse_rng ?defines context children)
11199       :: parse_rng ?defines context rest
11200   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11201       let rng = parse_rng ?defines context [child] in
11202       (match rng with
11203        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11204        | _ ->
11205            failwithf "%s: <zeroOrMore> contains more than one child element"
11206              context
11207       )
11208   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11209       let rng = parse_rng ?defines context [child] in
11210       (match rng with
11211        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11212        | _ ->
11213            failwithf "%s: <oneOrMore> contains more than one child element"
11214              context
11215       )
11216   | Xml.Element ("optional", [], [child]) :: rest ->
11217       let rng = parse_rng ?defines context [child] in
11218       (match rng with
11219        | [child] -> Optional child :: parse_rng ?defines context rest
11220        | _ ->
11221            failwithf "%s: <optional> contains more than one child element"
11222              context
11223       )
11224   | Xml.Element ("choice", [], children) :: rest ->
11225       let values = List.map (
11226         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11227         | _ ->
11228             failwithf "%s: can't handle anything except <value> in <choice>"
11229               context
11230       ) children in
11231       Choice values
11232       :: parse_rng ?defines context rest
11233   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11234       Value value :: parse_rng ?defines context rest
11235   | Xml.Element ("text", [], []) :: rest ->
11236       Text :: parse_rng ?defines context rest
11237   | Xml.Element ("ref", ["name", name], []) :: rest ->
11238       (* Look up the reference.  Because of limitations in this parser,
11239        * we can't handle arbitrarily nested <ref> yet.  You can only
11240        * use <ref> from inside <start>.
11241        *)
11242       (match defines with
11243        | None ->
11244            failwithf "%s: contains <ref>, but no refs are defined yet" context
11245        | Some map ->
11246            let rng = StringMap.find name map in
11247            rng @ parse_rng ?defines context rest
11248       )
11249   | x :: _ ->
11250       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11251
11252 let grammar =
11253   let xml = Xml.parse_file rng_input in
11254   match xml with
11255   | Xml.Element ("grammar", _,
11256                  Xml.Element ("start", _, gram) :: defines) ->
11257       (* The <define/> elements are referenced in the <start> section,
11258        * so build a map of those first.
11259        *)
11260       let defines = List.fold_left (
11261         fun map ->
11262           function Xml.Element ("define", ["name", name], defn) ->
11263             StringMap.add name defn map
11264           | _ ->
11265               failwithf "%s: expected <define name=name/>" rng_input
11266       ) StringMap.empty defines in
11267       let defines = StringMap.mapi parse_rng defines in
11268
11269       (* Parse the <start> clause, passing the defines. *)
11270       parse_rng ~defines "<start>" gram
11271   | _ ->
11272       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11273         rng_input
11274
11275 let name_of_field = function
11276   | Element (name, _) | Attribute (name, _)
11277   | ZeroOrMore (Element (name, _))
11278   | OneOrMore (Element (name, _))
11279   | Optional (Element (name, _)) -> name
11280   | Optional (Attribute (name, _)) -> name
11281   | Text -> (* an unnamed field in an element *)
11282       "data"
11283   | rng ->
11284       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11285
11286 (* At the moment this function only generates OCaml types.  However we
11287  * should parameterize it later so it can generate types/structs in a
11288  * variety of languages.
11289  *)
11290 let generate_types xs =
11291   (* A simple type is one that can be printed out directly, eg.
11292    * "string option".  A complex type is one which has a name and has
11293    * to be defined via another toplevel definition, eg. a struct.
11294    *
11295    * generate_type generates code for either simple or complex types.
11296    * In the simple case, it returns the string ("string option").  In
11297    * the complex case, it returns the name ("mountpoint").  In the
11298    * complex case it has to print out the definition before returning,
11299    * so it should only be called when we are at the beginning of a
11300    * new line (BOL context).
11301    *)
11302   let rec generate_type = function
11303     | Text ->                                (* string *)
11304         "string", true
11305     | Choice values ->                        (* [`val1|`val2|...] *)
11306         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11307     | ZeroOrMore rng ->                        (* <rng> list *)
11308         let t, is_simple = generate_type rng in
11309         t ^ " list (* 0 or more *)", is_simple
11310     | OneOrMore rng ->                        (* <rng> list *)
11311         let t, is_simple = generate_type rng in
11312         t ^ " list (* 1 or more *)", is_simple
11313                                         (* virt-inspector hack: bool *)
11314     | Optional (Attribute (name, [Value "1"])) ->
11315         "bool", true
11316     | Optional rng ->                        (* <rng> list *)
11317         let t, is_simple = generate_type rng in
11318         t ^ " option", is_simple
11319                                         (* type name = { fields ... } *)
11320     | Element (name, fields) when is_attrs_interleave fields ->
11321         generate_type_struct name (get_attrs_interleave fields)
11322     | Element (name, [field])                (* type name = field *)
11323     | Attribute (name, [field]) ->
11324         let t, is_simple = generate_type field in
11325         if is_simple then (t, true)
11326         else (
11327           pr "type %s = %s\n" name t;
11328           name, false
11329         )
11330     | Element (name, fields) ->              (* type name = { fields ... } *)
11331         generate_type_struct name fields
11332     | rng ->
11333         failwithf "generate_type failed at: %s" (string_of_rng rng)
11334
11335   and is_attrs_interleave = function
11336     | [Interleave _] -> true
11337     | Attribute _ :: fields -> is_attrs_interleave fields
11338     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11339     | _ -> false
11340
11341   and get_attrs_interleave = function
11342     | [Interleave fields] -> fields
11343     | ((Attribute _) as field) :: fields
11344     | ((Optional (Attribute _)) as field) :: fields ->
11345         field :: get_attrs_interleave fields
11346     | _ -> assert false
11347
11348   and generate_types xs =
11349     List.iter (fun x -> ignore (generate_type x)) xs
11350
11351   and generate_type_struct name fields =
11352     (* Calculate the types of the fields first.  We have to do this
11353      * before printing anything so we are still in BOL context.
11354      *)
11355     let types = List.map fst (List.map generate_type fields) in
11356
11357     (* Special case of a struct containing just a string and another
11358      * field.  Turn it into an assoc list.
11359      *)
11360     match types with
11361     | ["string"; other] ->
11362         let fname1, fname2 =
11363           match fields with
11364           | [f1; f2] -> name_of_field f1, name_of_field f2
11365           | _ -> assert false in
11366         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11367         name, false
11368
11369     | types ->
11370         pr "type %s = {\n" name;
11371         List.iter (
11372           fun (field, ftype) ->
11373             let fname = name_of_field field in
11374             pr "  %s_%s : %s;\n" name fname ftype
11375         ) (List.combine fields types);
11376         pr "}\n";
11377         (* Return the name of this type, and
11378          * false because it's not a simple type.
11379          *)
11380         name, false
11381   in
11382
11383   generate_types xs
11384
11385 let generate_parsers xs =
11386   (* As for generate_type above, generate_parser makes a parser for
11387    * some type, and returns the name of the parser it has generated.
11388    * Because it (may) need to print something, it should always be
11389    * called in BOL context.
11390    *)
11391   let rec generate_parser = function
11392     | Text ->                                (* string *)
11393         "string_child_or_empty"
11394     | Choice values ->                        (* [`val1|`val2|...] *)
11395         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11396           (String.concat "|"
11397              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11398     | ZeroOrMore rng ->                        (* <rng> list *)
11399         let pa = generate_parser rng in
11400         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11401     | OneOrMore rng ->                        (* <rng> list *)
11402         let pa = generate_parser rng in
11403         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11404                                         (* virt-inspector hack: bool *)
11405     | Optional (Attribute (name, [Value "1"])) ->
11406         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11407     | Optional rng ->                        (* <rng> list *)
11408         let pa = generate_parser rng in
11409         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11410                                         (* type name = { fields ... } *)
11411     | Element (name, fields) when is_attrs_interleave fields ->
11412         generate_parser_struct name (get_attrs_interleave fields)
11413     | Element (name, [field]) ->        (* type name = field *)
11414         let pa = generate_parser field in
11415         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11416         pr "let %s =\n" parser_name;
11417         pr "  %s\n" pa;
11418         pr "let parse_%s = %s\n" name parser_name;
11419         parser_name
11420     | Attribute (name, [field]) ->
11421         let pa = generate_parser field in
11422         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11423         pr "let %s =\n" parser_name;
11424         pr "  %s\n" pa;
11425         pr "let parse_%s = %s\n" name parser_name;
11426         parser_name
11427     | Element (name, fields) ->              (* type name = { fields ... } *)
11428         generate_parser_struct name ([], fields)
11429     | rng ->
11430         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11431
11432   and is_attrs_interleave = function
11433     | [Interleave _] -> true
11434     | Attribute _ :: fields -> is_attrs_interleave fields
11435     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11436     | _ -> false
11437
11438   and get_attrs_interleave = function
11439     | [Interleave fields] -> [], fields
11440     | ((Attribute _) as field) :: fields
11441     | ((Optional (Attribute _)) as field) :: fields ->
11442         let attrs, interleaves = get_attrs_interleave fields in
11443         (field :: attrs), interleaves
11444     | _ -> assert false
11445
11446   and generate_parsers xs =
11447     List.iter (fun x -> ignore (generate_parser x)) xs
11448
11449   and generate_parser_struct name (attrs, interleaves) =
11450     (* Generate parsers for the fields first.  We have to do this
11451      * before printing anything so we are still in BOL context.
11452      *)
11453     let fields = attrs @ interleaves in
11454     let pas = List.map generate_parser fields in
11455
11456     (* Generate an intermediate tuple from all the fields first.
11457      * If the type is just a string + another field, then we will
11458      * return this directly, otherwise it is turned into a record.
11459      *
11460      * RELAX NG note: This code treats <interleave> and plain lists of
11461      * fields the same.  In other words, it doesn't bother enforcing
11462      * any ordering of fields in the XML.
11463      *)
11464     pr "let parse_%s x =\n" name;
11465     pr "  let t = (\n    ";
11466     let comma = ref false in
11467     List.iter (
11468       fun x ->
11469         if !comma then pr ",\n    ";
11470         comma := true;
11471         match x with
11472         | Optional (Attribute (fname, [field])), pa ->
11473             pr "%s x" pa
11474         | Optional (Element (fname, [field])), pa ->
11475             pr "%s (optional_child %S x)" pa fname
11476         | Attribute (fname, [Text]), _ ->
11477             pr "attribute %S x" fname
11478         | (ZeroOrMore _ | OneOrMore _), pa ->
11479             pr "%s x" pa
11480         | Text, pa ->
11481             pr "%s x" pa
11482         | (field, pa) ->
11483             let fname = name_of_field field in
11484             pr "%s (child %S x)" pa fname
11485     ) (List.combine fields pas);
11486     pr "\n  ) in\n";
11487
11488     (match fields with
11489      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11490          pr "  t\n"
11491
11492      | _ ->
11493          pr "  (Obj.magic t : %s)\n" name
11494 (*
11495          List.iter (
11496            function
11497            | (Optional (Attribute (fname, [field])), pa) ->
11498                pr "  %s_%s =\n" name fname;
11499                pr "    %s x;\n" pa
11500            | (Optional (Element (fname, [field])), pa) ->
11501                pr "  %s_%s =\n" name fname;
11502                pr "    (let x = optional_child %S x in\n" fname;
11503                pr "     %s x);\n" pa
11504            | (field, pa) ->
11505                let fname = name_of_field field in
11506                pr "  %s_%s =\n" name fname;
11507                pr "    (let x = child %S x in\n" fname;
11508                pr "     %s x);\n" pa
11509          ) (List.combine fields pas);
11510          pr "}\n"
11511 *)
11512     );
11513     sprintf "parse_%s" name
11514   in
11515
11516   generate_parsers xs
11517
11518 (* Generate ocaml/guestfs_inspector.mli. *)
11519 let generate_ocaml_inspector_mli () =
11520   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11521
11522   pr "\
11523 (** This is an OCaml language binding to the external [virt-inspector]
11524     program.
11525
11526     For more information, please read the man page [virt-inspector(1)].
11527 *)
11528
11529 ";
11530
11531   generate_types grammar;
11532   pr "(** The nested information returned from the {!inspect} function. *)\n";
11533   pr "\n";
11534
11535   pr "\
11536 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11537 (** To inspect a libvirt domain called [name], pass a singleton
11538     list: [inspect [name]].  When using libvirt only, you may
11539     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11540
11541     To inspect a disk image or images, pass a list of the filenames
11542     of the disk images: [inspect filenames]
11543
11544     This function inspects the given guest or disk images and
11545     returns a list of operating system(s) found and a large amount
11546     of information about them.  In the vast majority of cases,
11547     a virtual machine only contains a single operating system.
11548
11549     If the optional [~xml] parameter is given, then this function
11550     skips running the external virt-inspector program and just
11551     parses the given XML directly (which is expected to be XML
11552     produced from a previous run of virt-inspector).  The list of
11553     names and connect URI are ignored in this case.
11554
11555     This function can throw a wide variety of exceptions, for example
11556     if the external virt-inspector program cannot be found, or if
11557     it doesn't generate valid XML.
11558 *)
11559 "
11560
11561 (* Generate ocaml/guestfs_inspector.ml. *)
11562 let generate_ocaml_inspector_ml () =
11563   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11564
11565   pr "open Unix\n";
11566   pr "\n";
11567
11568   generate_types grammar;
11569   pr "\n";
11570
11571   pr "\
11572 (* Misc functions which are used by the parser code below. *)
11573 let first_child = function
11574   | Xml.Element (_, _, c::_) -> c
11575   | Xml.Element (name, _, []) ->
11576       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11577   | Xml.PCData str ->
11578       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11579
11580 let string_child_or_empty = function
11581   | Xml.Element (_, _, [Xml.PCData s]) -> s
11582   | Xml.Element (_, _, []) -> \"\"
11583   | Xml.Element (x, _, _) ->
11584       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11585                 x ^ \" instead\")
11586   | Xml.PCData str ->
11587       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11588
11589 let optional_child name xml =
11590   let children = Xml.children xml in
11591   try
11592     Some (List.find (function
11593                      | Xml.Element (n, _, _) when n = name -> true
11594                      | _ -> false) children)
11595   with
11596     Not_found -> None
11597
11598 let child name xml =
11599   match optional_child name xml with
11600   | Some c -> c
11601   | None ->
11602       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11603
11604 let attribute name xml =
11605   try Xml.attrib xml name
11606   with Xml.No_attribute _ ->
11607     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11608
11609 ";
11610
11611   generate_parsers grammar;
11612   pr "\n";
11613
11614   pr "\
11615 (* Run external virt-inspector, then use parser to parse the XML. *)
11616 let inspect ?connect ?xml names =
11617   let xml =
11618     match xml with
11619     | None ->
11620         if names = [] then invalid_arg \"inspect: no names given\";
11621         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11622           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11623           names in
11624         let cmd = List.map Filename.quote cmd in
11625         let cmd = String.concat \" \" cmd in
11626         let chan = open_process_in cmd in
11627         let xml = Xml.parse_in chan in
11628         (match close_process_in chan with
11629          | WEXITED 0 -> ()
11630          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11631          | WSIGNALED i | WSTOPPED i ->
11632              failwith (\"external virt-inspector command died or stopped on sig \" ^
11633                        string_of_int i)
11634         );
11635         xml
11636     | Some doc ->
11637         Xml.parse_string doc in
11638   parse_operatingsystems xml
11639 "
11640
11641 (* This is used to generate the src/MAX_PROC_NR file which
11642  * contains the maximum procedure number, a surrogate for the
11643  * ABI version number.  See src/Makefile.am for the details.
11644  *)
11645 and generate_max_proc_nr () =
11646   let proc_nrs = List.map (
11647     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11648   ) daemon_functions in
11649
11650   let max_proc_nr = List.fold_left max 0 proc_nrs in
11651
11652   pr "%d\n" max_proc_nr
11653
11654 let output_to filename k =
11655   let filename_new = filename ^ ".new" in
11656   chan := open_out filename_new;
11657   k ();
11658   close_out !chan;
11659   chan := Pervasives.stdout;
11660
11661   (* Is the new file different from the current file? *)
11662   if Sys.file_exists filename && files_equal filename filename_new then
11663     unlink filename_new                 (* same, so skip it *)
11664   else (
11665     (* different, overwrite old one *)
11666     (try chmod filename 0o644 with Unix_error _ -> ());
11667     rename filename_new filename;
11668     chmod filename 0o444;
11669     printf "written %s\n%!" filename;
11670   )
11671
11672 let perror msg = function
11673   | Unix_error (err, _, _) ->
11674       eprintf "%s: %s\n" msg (error_message err)
11675   | exn ->
11676       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11677
11678 (* Main program. *)
11679 let () =
11680   let lock_fd =
11681     try openfile "HACKING" [O_RDWR] 0
11682     with
11683     | Unix_error (ENOENT, _, _) ->
11684         eprintf "\
11685 You are probably running this from the wrong directory.
11686 Run it from the top source directory using the command
11687   src/generator.ml
11688 ";
11689         exit 1
11690     | exn ->
11691         perror "open: HACKING" exn;
11692         exit 1 in
11693
11694   (* Acquire a lock so parallel builds won't try to run the generator
11695    * twice at the same time.  Subsequent builds will wait for the first
11696    * one to finish.  Note the lock is released implicitly when the
11697    * program exits.
11698    *)
11699   (try lockf lock_fd F_LOCK 1
11700    with exn ->
11701      perror "lock: HACKING" exn;
11702      exit 1);
11703
11704   check_functions ();
11705
11706   output_to "src/guestfs_protocol.x" generate_xdr;
11707   output_to "src/guestfs-structs.h" generate_structs_h;
11708   output_to "src/guestfs-actions.h" generate_actions_h;
11709   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11710   output_to "src/guestfs-actions.c" generate_client_actions;
11711   output_to "src/guestfs-bindtests.c" generate_bindtests;
11712   output_to "src/guestfs-structs.pod" generate_structs_pod;
11713   output_to "src/guestfs-actions.pod" generate_actions_pod;
11714   output_to "src/guestfs-availability.pod" generate_availability_pod;
11715   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11716   output_to "src/libguestfs.syms" generate_linker_script;
11717   output_to "daemon/actions.h" generate_daemon_actions_h;
11718   output_to "daemon/stubs.c" generate_daemon_actions;
11719   output_to "daemon/names.c" generate_daemon_names;
11720   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11721   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11722   output_to "capitests/tests.c" generate_tests;
11723   output_to "fish/cmds.c" generate_fish_cmds;
11724   output_to "fish/completion.c" generate_fish_completion;
11725   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11726   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11727   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11728   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11729   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11730   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11731   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11732   output_to "perl/Guestfs.xs" generate_perl_xs;
11733   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11734   output_to "perl/bindtests.pl" generate_perl_bindtests;
11735   output_to "python/guestfs-py.c" generate_python_c;
11736   output_to "python/guestfs.py" generate_python_py;
11737   output_to "python/bindtests.py" generate_python_bindtests;
11738   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11739   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11740   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11741
11742   List.iter (
11743     fun (typ, jtyp) ->
11744       let cols = cols_of_struct typ in
11745       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11746       output_to filename (generate_java_struct jtyp cols);
11747   ) java_structs;
11748
11749   output_to "java/Makefile.inc" generate_java_makefile_inc;
11750   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11751   output_to "java/Bindtests.java" generate_java_bindtests;
11752   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11753   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11754   output_to "csharp/Libguestfs.cs" generate_csharp;
11755
11756   (* Always generate this file last, and unconditionally.  It's used
11757    * by the Makefile to know when we must re-run the generator.
11758    *)
11759   let chan = open_out "src/stamp-generator" in
11760   fprintf chan "1\n";
11761   close_out chan;
11762
11763   printf "generated %d lines of code\n" !lines