generator: Implement BufferIn parameter type (RHBZ#501889).
[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     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <const char *, size_t> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177
178 type flags =
179   | ProtocolLimitWarning  (* display warning about protocol size limits *)
180   | DangerWillRobinson    (* flags particularly dangerous commands *)
181   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
182   | FishOutput of fish_output_t (* how to display output in guestfish *)
183   | NotInFish             (* do not export via guestfish *)
184   | NotInDocs             (* do not add this function to documentation *)
185   | DeprecatedBy of string (* function is deprecated, use .. instead *)
186   | Optional of string    (* function is part of an optional group *)
187
188 and fish_output_t =
189   | FishOutputOctal       (* for int return, print in octal *)
190   | FishOutputHexadecimal (* for int return, print in hex *)
191
192 (* You can supply zero or as many tests as you want per API call.
193  *
194  * Note that the test environment has 3 block devices, of size 500MB,
195  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196  * a fourth ISO block device with some known files on it (/dev/sdd).
197  *
198  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199  * Number of cylinders was 63 for IDE emulated disks with precisely
200  * the same size.  How exactly this is calculated is a mystery.
201  *
202  * The ISO block device (/dev/sdd) comes from images/test.iso.
203  *
204  * To be able to run the tests in a reasonable amount of time,
205  * the virtual machine and block devices are reused between tests.
206  * So don't try testing kill_subprocess :-x
207  *
208  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
209  *
210  * Don't assume anything about the previous contents of the block
211  * devices.  Use 'Init*' to create some initial scenarios.
212  *
213  * You can add a prerequisite clause to any individual test.  This
214  * is a run-time check, which, if it fails, causes the test to be
215  * skipped.  Useful if testing a command which might not work on
216  * all variations of libguestfs builds.  A test that has prerequisite
217  * of 'Always' is run unconditionally.
218  *
219  * In addition, packagers can skip individual tests by setting the
220  * environment variables:     eg:
221  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
222  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
223  *)
224 type tests = (test_init * test_prereq * test) list
225 and test =
226     (* Run the command sequence and just expect nothing to fail. *)
227   | TestRun of seq
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the string.
231      *)
232   | TestOutput of seq * string
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of strings.
236      *)
237   | TestOutputList of seq * string list
238
239     (* Run the command sequence and expect the output of the final
240      * command to be the list of block devices (could be either
241      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242      * character of each string).
243      *)
244   | TestOutputListOfDevices of seq * string list
245
246     (* Run the command sequence and expect the output of the final
247      * command to be the integer.
248      *)
249   | TestOutputInt of seq * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be <op> <int>, eg. ">=", "1".
253      *)
254   | TestOutputIntOp of seq * string * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a true value (!= 0 or != NULL).
258      *)
259   | TestOutputTrue of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a false value (== 0 or == NULL, but not an error).
263      *)
264   | TestOutputFalse of seq
265
266     (* Run the command sequence and expect the output of the final
267      * command to be a list of the given length (but don't care about
268      * content).
269      *)
270   | TestOutputLength of seq * int
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a buffer (RBufferOut), ie. string + size.
274      *)
275   | TestOutputBuffer of seq * string
276
277     (* Run the command sequence and expect the output of the final
278      * command to be a structure.
279      *)
280   | TestOutputStruct of seq * test_field_compare list
281
282     (* Run the command sequence and expect the final command (only)
283      * to fail.
284      *)
285   | TestLastFail of seq
286
287 and test_field_compare =
288   | CompareWithInt of string * int
289   | CompareWithIntOp of string * string * int
290   | CompareWithString of string * string
291   | CompareFieldsIntEq of string * string
292   | CompareFieldsStrEq of string * string
293
294 (* Test prerequisites. *)
295 and test_prereq =
296     (* Test always runs. *)
297   | Always
298
299     (* Test is currently disabled - eg. it fails, or it tests some
300      * unimplemented feature.
301      *)
302   | Disabled
303
304     (* 'string' is some C code (a function body) that should return
305      * true or false.  The test will run if the code returns true.
306      *)
307   | If of string
308
309     (* As for 'If' but the test runs _unless_ the code returns true. *)
310   | Unless of string
311
312 (* Some initial scenarios for testing. *)
313 and test_init =
314     (* Do nothing, block devices could contain random stuff including
315      * LVM PVs, and some filesystems might be mounted.  This is usually
316      * a bad idea.
317      *)
318   | InitNone
319
320     (* Block devices are empty and no filesystems are mounted. *)
321   | InitEmpty
322
323     (* /dev/sda contains a single partition /dev/sda1, with random
324      * content.  /dev/sdb and /dev/sdc may have random content.
325      * No LVM.
326      *)
327   | InitPartition
328
329     (* /dev/sda contains a single partition /dev/sda1, which is formatted
330      * as ext2, empty [except for lost+found] and mounted on /.
331      * /dev/sdb and /dev/sdc may have random content.
332      * No LVM.
333      *)
334   | InitBasicFS
335
336     (* /dev/sda:
337      *   /dev/sda1 (is a PV):
338      *     /dev/VG/LV (size 8MB):
339      *       formatted as ext2, empty [except for lost+found], mounted on /
340      * /dev/sdb and /dev/sdc may have random content.
341      *)
342   | InitBasicFSonLVM
343
344     (* /dev/sdd (the ISO, see images/ directory in source)
345      * is mounted on /
346      *)
347   | InitISOFS
348
349 (* Sequence of commands for testing. *)
350 and seq = cmd list
351 and cmd = string list
352
353 (* Note about long descriptions: When referring to another
354  * action, use the format C<guestfs_other> (ie. the full name of
355  * the C function).  This will be replaced as appropriate in other
356  * language bindings.
357  *
358  * Apart from that, long descriptions are just perldoc paragraphs.
359  *)
360
361 (* Generate a random UUID (used in tests). *)
362 let uuidgen () =
363   let chan = open_process_in "uuidgen" in
364   let uuid = input_line chan in
365   (match close_process_in chan with
366    | WEXITED 0 -> ()
367    | WEXITED _ ->
368        failwith "uuidgen: process exited with non-zero status"
369    | WSIGNALED _ | WSTOPPED _ ->
370        failwith "uuidgen: process signalled or stopped by signal"
371   );
372   uuid
373
374 (* These test functions are used in the language binding tests. *)
375
376 let test_all_args = [
377   String "str";
378   OptString "optstr";
379   StringList "strlist";
380   Bool "b";
381   Int "integer";
382   Int64 "integer64";
383   FileIn "filein";
384   FileOut "fileout";
385   BufferIn "bufferin";
386 ]
387
388 let test_all_rets = [
389   (* except for RErr, which is tested thoroughly elsewhere *)
390   "test0rint",         RInt "valout";
391   "test0rint64",       RInt64 "valout";
392   "test0rbool",        RBool "valout";
393   "test0rconststring", RConstString "valout";
394   "test0rconstoptstring", RConstOptString "valout";
395   "test0rstring",      RString "valout";
396   "test0rstringlist",  RStringList "valout";
397   "test0rstruct",      RStruct ("valout", "lvm_pv");
398   "test0rstructlist",  RStructList ("valout", "lvm_pv");
399   "test0rhashtable",   RHashtable "valout";
400 ]
401
402 let test_functions = [
403   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
404    [],
405    "internal test function - do not use",
406    "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
410
411 It echos the contents of each parameter to stdout.
412
413 You probably don't want to call this function.");
414 ] @ List.flatten (
415   List.map (
416     fun (name, ret) ->
417       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
418         [],
419         "internal test function - do not use",
420         "\
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
424
425 It converts string C<val> to the return type.
426
427 You probably don't want to call this function.");
428        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
429         [],
430         "internal test function - do not use",
431         "\
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
435
436 This function always returns an error.
437
438 You probably don't want to call this function.")]
439   ) test_all_rets
440 )
441
442 (* non_daemon_functions are any functions which don't get processed
443  * in the daemon, eg. functions for setting and getting local
444  * configuration values.
445  *)
446
447 let non_daemon_functions = test_functions @ [
448   ("launch", (RErr, []), -1, [FishAlias "run"],
449    [],
450    "launch the qemu subprocess",
451    "\
452 Internally libguestfs is implemented by running a virtual machine
453 using L<qemu(1)>.
454
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
457
458   ("wait_ready", (RErr, []), -1, [NotInFish],
459    [],
460    "wait until the qemu subprocess launches (no op)",
461    "\
462 This function is a no op.
463
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete.  However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
468
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
472
473   ("kill_subprocess", (RErr, []), -1, [],
474    [],
475    "kill the qemu subprocess",
476    "\
477 This kills the qemu subprocess.  You should never need to call this.");
478
479   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
480    [],
481    "add an image to examine or modify",
482    "\
483 This function adds a virtual machine disk image C<filename> to the
484 guest.  The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
486 so on.
487
488 You don't necessarily need to be root when using libguestfs.  However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
492 image).
493
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
496
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
499
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>.  In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
504
505 Note that this call checks for the existence of C<filename>.  This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
508 the general C<guestfs_config> call instead.");
509
510   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
511    [],
512    "add a CD-ROM disk image to examine",
513    "\
514 This function adds a virtual CD-ROM disk image to the guest.
515
516 This is equivalent to the qemu parameter C<-cdrom filename>.
517
518 Notes:
519
520 =over 4
521
522 =item *
523
524 This call checks for the existence of C<filename>.  This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
527 the general C<guestfs_config> call instead.
528
529 =item *
530
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
534
535 =back");
536
537   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
538    [],
539    "add a drive in snapshot mode (read-only)",
540    "\
541 This adds a drive in snapshot mode, making it effectively
542 read-only.
543
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed.  We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
549
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
552
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>.  In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
557
558 C<readonly=on> is only added where qemu supports this option.
559
560 Note that this call checks for the existence of C<filename>.  This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
563 the general C<guestfs_config> call instead.");
564
565   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
566    [],
567    "add qemu parameters",
568    "\
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>.  Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
573
574 The first character of C<param> string must be a C<-> (dash).
575
576 C<value> can be NULL.");
577
578   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
579    [],
580    "set the qemu binary",
581    "\
582 Set the qemu binary that we will use.
583
584 The default is chosen when the library was compiled by the
585 configure script.
586
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
589
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
591
592 Note that you should call this function as early as possible
593 after creating the handle.  This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results.  Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
599
600   ("get_qemu", (RConstString "qemu", []), -1, [],
601    [InitNone, Always, TestRun (
602       [["get_qemu"]])],
603    "get the qemu binary",
604    "\
605 Return the current qemu binary.
606
607 This is always non-NULL.  If it wasn't set already, then this will
608 return the default qemu binary name.");
609
610   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
611    [],
612    "set the search path",
613    "\
614 Set the path that libguestfs searches for kernel and initrd.img.
615
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
618
619 Setting C<path> to C<NULL> restores the default path.");
620
621   ("get_path", (RConstString "path", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_path"]])],
624    "get the search path",
625    "\
626 Return the current search path.
627
628 This is always non-NULL.  If it wasn't set already, then this will
629 return the default path.");
630
631   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
632    [],
633    "add options to kernel command line",
634    "\
635 This function is used to add additional options to the
636 guest kernel command line.
637
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
640
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
643
644   ("get_append", (RConstOptString "append", []), -1, [],
645    (* This cannot be tested with the current framework.  The
646     * function can return NULL in normal operations, which the
647     * test framework interprets as an error.
648     *)
649    [],
650    "get the additional kernel options",
651    "\
652 Return the additional kernel options which are added to the
653 guest kernel command line.
654
655 If C<NULL> then no options are added.");
656
657   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658    [],
659    "set autosync mode",
660    "\
661 If C<autosync> is true, this enables autosync.  Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
665
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
668
669   ("get_autosync", (RBool "autosync", []), -1, [],
670    [InitNone, Always, TestRun (
671       [["get_autosync"]])],
672    "get autosync mode",
673    "\
674 Get the autosync flag.");
675
676   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677    [],
678    "set verbose mode",
679    "\
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
681
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
684
685   ("get_verbose", (RBool "verbose", []), -1, [],
686    [],
687    "get verbose mode",
688    "\
689 This returns the verbose messages flag.");
690
691   ("is_ready", (RBool "ready", []), -1, [],
692    [InitNone, Always, TestOutputTrue (
693       [["is_ready"]])],
694    "is ready to accept commands",
695    "\
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("is_config", (RBool "config", []), -1, [],
702    [InitNone, Always, TestOutputFalse (
703       [["is_config"]])],
704    "is in configuration state",
705    "\
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("is_launching", (RBool "launching", []), -1, [],
712    [InitNone, Always, TestOutputFalse (
713       [["is_launching"]])],
714    "is launching subprocess",
715    "\
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
718
719 For more information on states, see L<guestfs(3)>.");
720
721   ("is_busy", (RBool "busy", []), -1, [],
722    [InitNone, Always, TestOutputFalse (
723       [["is_busy"]])],
724    "is busy processing a command",
725    "\
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
728
729 For more information on states, see L<guestfs(3)>.");
730
731   ("get_state", (RInt "state", []), -1, [],
732    [],
733    "get the current state",
734    "\
735 This returns the current state as an opaque integer.  This is
736 only useful for printing debug and internal error messages.
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741    [InitNone, Always, TestOutputInt (
742       [["set_memsize"; "500"];
743        ["get_memsize"]], 500)],
744    "set memory allocated to the qemu subprocess",
745    "\
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess.  This only has any effect if called before
748 C<guestfs_launch>.
749
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
752 created.
753
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
756
757   ("get_memsize", (RInt "memsize", []), -1, [],
758    [InitNone, Always, TestOutputIntOp (
759       [["get_memsize"]], ">=", 256)],
760    "get memory allocated to the qemu subprocess",
761    "\
762 This gets the memory size in megabytes allocated to the
763 qemu subprocess.
764
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
768
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
771
772   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773    [InitNone, Always, TestOutputIntOp (
774       [["get_pid"]], ">=", 1)],
775    "get PID of qemu subprocess",
776    "\
777 Return the process ID of the qemu subprocess.  If there is no
778 qemu subprocess, then this will return an error.
779
780 This is an internal call used for debugging and testing.");
781
782   ("version", (RStruct ("version", "version"), []), -1, [],
783    [InitNone, Always, TestOutputStruct (
784       [["version"]], [CompareWithInt ("major", 1)])],
785    "get the library version number",
786    "\
787 Return the libguestfs version number that the program is linked
788 against.
789
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against.  You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
794
795 This call was added in version C<1.0.58>.  In previous
796 versions of libguestfs there was no way to get the version
797 number.  From C code you can use ELF weak linking tricks to find out if
798 this symbol exists (if it doesn't, then it's an earlier version).
799
800 The call returns a structure with four elements.  The first
801 three (C<major>, C<minor> and C<release>) are numbers and
802 correspond to the usual version triplet.  The fourth element
803 (C<extra>) is a string and is normally empty, but may be
804 used for distro-specific information.
805
806 To construct the original version string:
807 C<$major.$minor.$release$extra>
808
809 I<Note:> Don't use this call to test for availability
810 of features.  Distro backports makes this unreliable.  Use
811 C<guestfs_available> instead.");
812
813   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
814    [InitNone, Always, TestOutputTrue (
815       [["set_selinux"; "true"];
816        ["get_selinux"]])],
817    "set SELinux enabled or disabled at appliance boot",
818    "\
819 This sets the selinux flag that is passed to the appliance
820 at boot time.  The default is C<selinux=0> (disabled).
821
822 Note that if SELinux is enabled, it is always in
823 Permissive mode (C<enforcing=0>).
824
825 For more information on the architecture of libguestfs,
826 see L<guestfs(3)>.");
827
828   ("get_selinux", (RBool "selinux", []), -1, [],
829    [],
830    "get SELinux enabled flag",
831    "\
832 This returns the current setting of the selinux flag which
833 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
834
835 For more information on the architecture of libguestfs,
836 see L<guestfs(3)>.");
837
838   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
839    [InitNone, Always, TestOutputFalse (
840       [["set_trace"; "false"];
841        ["get_trace"]])],
842    "enable or disable command traces",
843    "\
844 If the command trace flag is set to 1, then commands are
845 printed on stdout before they are executed in a format
846 which is very similar to the one used by guestfish.  In
847 other words, you can run a program with this enabled, and
848 you will get out a script which you can feed to guestfish
849 to perform the same set of actions.
850
851 If you want to trace C API calls into libguestfs (and
852 other libraries) then possibly a better way is to use
853 the external ltrace(1) command.
854
855 Command traces are disabled unless the environment variable
856 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
857
858   ("get_trace", (RBool "trace", []), -1, [],
859    [],
860    "get command trace enabled flag",
861    "\
862 Return the command trace flag.");
863
864   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
865    [InitNone, Always, TestOutputFalse (
866       [["set_direct"; "false"];
867        ["get_direct"]])],
868    "enable or disable direct appliance mode",
869    "\
870 If the direct appliance mode flag is enabled, then stdin and
871 stdout are passed directly through to the appliance once it
872 is launched.
873
874 One consequence of this is that log messages aren't caught
875 by the library and handled by C<guestfs_set_log_message_callback>,
876 but go straight to stdout.
877
878 You probably don't want to use this unless you know what you
879 are doing.
880
881 The default is disabled.");
882
883   ("get_direct", (RBool "direct", []), -1, [],
884    [],
885    "get direct appliance mode flag",
886    "\
887 Return the direct appliance mode flag.");
888
889   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
890    [InitNone, Always, TestOutputTrue (
891       [["set_recovery_proc"; "true"];
892        ["get_recovery_proc"]])],
893    "enable or disable the recovery process",
894    "\
895 If this is called with the parameter C<false> then
896 C<guestfs_launch> does not create a recovery process.  The
897 purpose of the recovery process is to stop runaway qemu
898 processes in the case where the main program aborts abruptly.
899
900 This only has any effect if called before C<guestfs_launch>,
901 and the default is true.
902
903 About the only time when you would want to disable this is
904 if the main process will fork itself into the background
905 (\"daemonize\" itself).  In this case the recovery process
906 thinks that the main program has disappeared and so kills
907 qemu, which is not very helpful.");
908
909   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
910    [],
911    "get recovery process enabled flag",
912    "\
913 Return the recovery process enabled flag.");
914
915   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
916    [],
917    "add a drive specifying the QEMU block emulation to use",
918    "\
919 This is the same as C<guestfs_add_drive> but it allows you
920 to specify the QEMU interface emulation to use at run time.");
921
922   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
923    [],
924    "add a drive read-only specifying the QEMU block emulation to use",
925    "\
926 This is the same as C<guestfs_add_drive_ro> but it allows you
927 to specify the QEMU interface emulation to use at run time.");
928
929 ]
930
931 (* daemon_functions are any functions which cause some action
932  * to take place in the daemon.
933  *)
934
935 let daemon_functions = [
936   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
937    [InitEmpty, Always, TestOutput (
938       [["part_disk"; "/dev/sda"; "mbr"];
939        ["mkfs"; "ext2"; "/dev/sda1"];
940        ["mount"; "/dev/sda1"; "/"];
941        ["write_file"; "/new"; "new file contents"; "0"];
942        ["cat"; "/new"]], "new file contents")],
943    "mount a guest disk at a position in the filesystem",
944    "\
945 Mount a guest disk at a position in the filesystem.  Block devices
946 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
947 the guest.  If those block devices contain partitions, they will have
948 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
949 names can be used.
950
951 The rules are the same as for L<mount(2)>:  A filesystem must
952 first be mounted on C</> before others can be mounted.  Other
953 filesystems can only be mounted on directories which already
954 exist.
955
956 The mounted filesystem is writable, if we have sufficient permissions
957 on the underlying device.
958
959 B<Important note:>
960 When you use this call, the filesystem options C<sync> and C<noatime>
961 are set implicitly.  This was originally done because we thought it
962 would improve reliability, but it turns out that I<-o sync> has a
963 very large negative performance impact and negligible effect on
964 reliability.  Therefore we recommend that you avoid using
965 C<guestfs_mount> in any code that needs performance, and instead
966 use C<guestfs_mount_options> (use an empty string for the first
967 parameter if you don't want any options).");
968
969   ("sync", (RErr, []), 2, [],
970    [ InitEmpty, Always, TestRun [["sync"]]],
971    "sync disks, writes are flushed through to the disk image",
972    "\
973 This syncs the disk, so that any writes are flushed through to the
974 underlying disk image.
975
976 You should always call this if you have modified a disk image, before
977 closing the handle.");
978
979   ("touch", (RErr, [Pathname "path"]), 3, [],
980    [InitBasicFS, Always, TestOutputTrue (
981       [["touch"; "/new"];
982        ["exists"; "/new"]])],
983    "update file timestamps or create a new file",
984    "\
985 Touch acts like the L<touch(1)> command.  It can be used to
986 update the timestamps on a file, or, if the file does not exist,
987 to create a new zero-length file.");
988
989   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
990    [InitISOFS, Always, TestOutput (
991       [["cat"; "/known-2"]], "abcdef\n")],
992    "list the contents of a file",
993    "\
994 Return the contents of the file named C<path>.
995
996 Note that this function cannot correctly handle binary files
997 (specifically, files containing C<\\0> character which is treated
998 as end of string).  For those you need to use the C<guestfs_read_file>
999 or C<guestfs_download> functions which have a more complex interface.");
1000
1001   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1002    [], (* XXX Tricky to test because it depends on the exact format
1003         * of the 'ls -l' command, which changes between F10 and F11.
1004         *)
1005    "list the files in a directory (long format)",
1006    "\
1007 List the files in C<directory> (relative to the root directory,
1008 there is no cwd) in the format of 'ls -la'.
1009
1010 This command is mostly useful for interactive sessions.  It
1011 is I<not> intended that you try to parse the output string.");
1012
1013   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1014    [InitBasicFS, Always, TestOutputList (
1015       [["touch"; "/new"];
1016        ["touch"; "/newer"];
1017        ["touch"; "/newest"];
1018        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1019    "list the files in a directory",
1020    "\
1021 List the files in C<directory> (relative to the root directory,
1022 there is no cwd).  The '.' and '..' entries are not returned, but
1023 hidden files are shown.
1024
1025 This command is mostly useful for interactive sessions.  Programs
1026 should probably use C<guestfs_readdir> instead.");
1027
1028   ("list_devices", (RStringList "devices", []), 7, [],
1029    [InitEmpty, Always, TestOutputListOfDevices (
1030       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1031    "list the block devices",
1032    "\
1033 List all the block devices.
1034
1035 The full block device names are returned, eg. C</dev/sda>");
1036
1037   ("list_partitions", (RStringList "partitions", []), 8, [],
1038    [InitBasicFS, Always, TestOutputListOfDevices (
1039       [["list_partitions"]], ["/dev/sda1"]);
1040     InitEmpty, Always, TestOutputListOfDevices (
1041       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1042        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1043    "list the partitions",
1044    "\
1045 List all the partitions detected on all block devices.
1046
1047 The full partition device names are returned, eg. C</dev/sda1>
1048
1049 This does not return logical volumes.  For that you will need to
1050 call C<guestfs_lvs>.");
1051
1052   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1053    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1054       [["pvs"]], ["/dev/sda1"]);
1055     InitEmpty, Always, TestOutputListOfDevices (
1056       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1057        ["pvcreate"; "/dev/sda1"];
1058        ["pvcreate"; "/dev/sda2"];
1059        ["pvcreate"; "/dev/sda3"];
1060        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1061    "list the LVM physical volumes (PVs)",
1062    "\
1063 List all the physical volumes detected.  This is the equivalent
1064 of the L<pvs(8)> command.
1065
1066 This returns a list of just the device names that contain
1067 PVs (eg. C</dev/sda2>).
1068
1069 See also C<guestfs_pvs_full>.");
1070
1071   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1072    [InitBasicFSonLVM, Always, TestOutputList (
1073       [["vgs"]], ["VG"]);
1074     InitEmpty, Always, TestOutputList (
1075       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1076        ["pvcreate"; "/dev/sda1"];
1077        ["pvcreate"; "/dev/sda2"];
1078        ["pvcreate"; "/dev/sda3"];
1079        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1080        ["vgcreate"; "VG2"; "/dev/sda3"];
1081        ["vgs"]], ["VG1"; "VG2"])],
1082    "list the LVM volume groups (VGs)",
1083    "\
1084 List all the volumes groups detected.  This is the equivalent
1085 of the L<vgs(8)> command.
1086
1087 This returns a list of just the volume group names that were
1088 detected (eg. C<VolGroup00>).
1089
1090 See also C<guestfs_vgs_full>.");
1091
1092   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1093    [InitBasicFSonLVM, Always, TestOutputList (
1094       [["lvs"]], ["/dev/VG/LV"]);
1095     InitEmpty, Always, TestOutputList (
1096       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1097        ["pvcreate"; "/dev/sda1"];
1098        ["pvcreate"; "/dev/sda2"];
1099        ["pvcreate"; "/dev/sda3"];
1100        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1101        ["vgcreate"; "VG2"; "/dev/sda3"];
1102        ["lvcreate"; "LV1"; "VG1"; "50"];
1103        ["lvcreate"; "LV2"; "VG1"; "50"];
1104        ["lvcreate"; "LV3"; "VG2"; "50"];
1105        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1106    "list the LVM logical volumes (LVs)",
1107    "\
1108 List all the logical volumes detected.  This is the equivalent
1109 of the L<lvs(8)> command.
1110
1111 This returns a list of the logical volume device names
1112 (eg. C</dev/VolGroup00/LogVol00>).
1113
1114 See also C<guestfs_lvs_full>.");
1115
1116   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1117    [], (* XXX how to test? *)
1118    "list the LVM physical volumes (PVs)",
1119    "\
1120 List all the physical volumes detected.  This is the equivalent
1121 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1122
1123   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1124    [], (* XXX how to test? *)
1125    "list the LVM volume groups (VGs)",
1126    "\
1127 List all the volumes groups detected.  This is the equivalent
1128 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1129
1130   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1131    [], (* XXX how to test? *)
1132    "list the LVM logical volumes (LVs)",
1133    "\
1134 List all the logical volumes detected.  This is the equivalent
1135 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1136
1137   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1138    [InitISOFS, Always, TestOutputList (
1139       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1140     InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/empty"]], [])],
1142    "read file as lines",
1143    "\
1144 Return the contents of the file named C<path>.
1145
1146 The file contents are returned as a list of lines.  Trailing
1147 C<LF> and C<CRLF> character sequences are I<not> returned.
1148
1149 Note that this function cannot correctly handle binary files
1150 (specifically, files containing C<\\0> character which is treated
1151 as end of line).  For those you need to use the C<guestfs_read_file>
1152 function which has a more complex interface.");
1153
1154   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1155    [], (* XXX Augeas code needs tests. *)
1156    "create a new Augeas handle",
1157    "\
1158 Create a new Augeas handle for editing configuration files.
1159 If there was any previous Augeas handle associated with this
1160 guestfs session, then it is closed.
1161
1162 You must call this before using any other C<guestfs_aug_*>
1163 commands.
1164
1165 C<root> is the filesystem root.  C<root> must not be NULL,
1166 use C</> instead.
1167
1168 The flags are the same as the flags defined in
1169 E<lt>augeas.hE<gt>, the logical I<or> of the following
1170 integers:
1171
1172 =over 4
1173
1174 =item C<AUG_SAVE_BACKUP> = 1
1175
1176 Keep the original file with a C<.augsave> extension.
1177
1178 =item C<AUG_SAVE_NEWFILE> = 2
1179
1180 Save changes into a file with extension C<.augnew>, and
1181 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1182
1183 =item C<AUG_TYPE_CHECK> = 4
1184
1185 Typecheck lenses (can be expensive).
1186
1187 =item C<AUG_NO_STDINC> = 8
1188
1189 Do not use standard load path for modules.
1190
1191 =item C<AUG_SAVE_NOOP> = 16
1192
1193 Make save a no-op, just record what would have been changed.
1194
1195 =item C<AUG_NO_LOAD> = 32
1196
1197 Do not load the tree in C<guestfs_aug_init>.
1198
1199 =back
1200
1201 To close the handle, you can call C<guestfs_aug_close>.
1202
1203 To find out more about Augeas, see L<http://augeas.net/>.");
1204
1205   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1206    [], (* XXX Augeas code needs tests. *)
1207    "close the current Augeas handle",
1208    "\
1209 Close the current Augeas handle and free up any resources
1210 used by it.  After calling this, you have to call
1211 C<guestfs_aug_init> again before you can use any other
1212 Augeas functions.");
1213
1214   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "define an Augeas variable",
1217    "\
1218 Defines an Augeas variable C<name> whose value is the result
1219 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1220 undefined.
1221
1222 On success this returns the number of nodes in C<expr>, or
1223 C<0> if C<expr> evaluates to something which is not a nodeset.");
1224
1225   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1226    [], (* XXX Augeas code needs tests. *)
1227    "define an Augeas node",
1228    "\
1229 Defines a variable C<name> whose value is the result of
1230 evaluating C<expr>.
1231
1232 If C<expr> evaluates to an empty nodeset, a node is created,
1233 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1234 C<name> will be the nodeset containing that single node.
1235
1236 On success this returns a pair containing the
1237 number of nodes in the nodeset, and a boolean flag
1238 if a node was created.");
1239
1240   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1241    [], (* XXX Augeas code needs tests. *)
1242    "look up the value of an Augeas path",
1243    "\
1244 Look up the value associated with C<path>.  If C<path>
1245 matches exactly one node, the C<value> is returned.");
1246
1247   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1248    [], (* XXX Augeas code needs tests. *)
1249    "set Augeas path to value",
1250    "\
1251 Set the value associated with C<path> to C<val>.
1252
1253 In the Augeas API, it is possible to clear a node by setting
1254 the value to NULL.  Due to an oversight in the libguestfs API
1255 you cannot do that with this call.  Instead you must use the
1256 C<guestfs_aug_clear> call.");
1257
1258   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1259    [], (* XXX Augeas code needs tests. *)
1260    "insert a sibling Augeas node",
1261    "\
1262 Create a new sibling C<label> for C<path>, inserting it into
1263 the tree before or after C<path> (depending on the boolean
1264 flag C<before>).
1265
1266 C<path> must match exactly one existing node in the tree, and
1267 C<label> must be a label, ie. not contain C</>, C<*> or end
1268 with a bracketed index C<[N]>.");
1269
1270   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "remove an Augeas path",
1273    "\
1274 Remove C<path> and all of its children.
1275
1276 On success this returns the number of entries which were removed.");
1277
1278   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "move Augeas node",
1281    "\
1282 Move the node C<src> to C<dest>.  C<src> must match exactly
1283 one node.  C<dest> is overwritten if it exists.");
1284
1285   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1286    [], (* XXX Augeas code needs tests. *)
1287    "return Augeas nodes which match augpath",
1288    "\
1289 Returns a list of paths which match the path expression C<path>.
1290 The returned paths are sufficiently qualified so that they match
1291 exactly one node in the current tree.");
1292
1293   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1294    [], (* XXX Augeas code needs tests. *)
1295    "write all pending Augeas changes to disk",
1296    "\
1297 This writes all pending changes to disk.
1298
1299 The flags which were passed to C<guestfs_aug_init> affect exactly
1300 how files are saved.");
1301
1302   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1303    [], (* XXX Augeas code needs tests. *)
1304    "load files into the tree",
1305    "\
1306 Load files into the tree.
1307
1308 See C<aug_load> in the Augeas documentation for the full gory
1309 details.");
1310
1311   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1312    [], (* XXX Augeas code needs tests. *)
1313    "list Augeas nodes under augpath",
1314    "\
1315 This is just a shortcut for listing C<guestfs_aug_match>
1316 C<path/*> and sorting the resulting nodes into alphabetical order.");
1317
1318   ("rm", (RErr, [Pathname "path"]), 29, [],
1319    [InitBasicFS, Always, TestRun
1320       [["touch"; "/new"];
1321        ["rm"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["mkdir"; "/new"];
1326        ["rm"; "/new"]]],
1327    "remove a file",
1328    "\
1329 Remove the single file C<path>.");
1330
1331   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1332    [InitBasicFS, Always, TestRun
1333       [["mkdir"; "/new"];
1334        ["rmdir"; "/new"]];
1335     InitBasicFS, Always, TestLastFail
1336       [["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["touch"; "/new"];
1339        ["rmdir"; "/new"]]],
1340    "remove a directory",
1341    "\
1342 Remove the single directory C<path>.");
1343
1344   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1345    [InitBasicFS, Always, TestOutputFalse
1346       [["mkdir"; "/new"];
1347        ["mkdir"; "/new/foo"];
1348        ["touch"; "/new/foo/bar"];
1349        ["rm_rf"; "/new"];
1350        ["exists"; "/new"]]],
1351    "remove a file or directory recursively",
1352    "\
1353 Remove the file or directory C<path>, recursively removing the
1354 contents if its a directory.  This is like the C<rm -rf> shell
1355 command.");
1356
1357   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1358    [InitBasicFS, Always, TestOutputTrue
1359       [["mkdir"; "/new"];
1360        ["is_dir"; "/new"]];
1361     InitBasicFS, Always, TestLastFail
1362       [["mkdir"; "/new/foo/bar"]]],
1363    "create a directory",
1364    "\
1365 Create a directory named C<path>.");
1366
1367   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1368    [InitBasicFS, Always, TestOutputTrue
1369       [["mkdir_p"; "/new/foo/bar"];
1370        ["is_dir"; "/new/foo/bar"]];
1371     InitBasicFS, Always, TestOutputTrue
1372       [["mkdir_p"; "/new/foo/bar"];
1373        ["is_dir"; "/new/foo"]];
1374     InitBasicFS, Always, TestOutputTrue
1375       [["mkdir_p"; "/new/foo/bar"];
1376        ["is_dir"; "/new"]];
1377     (* Regression tests for RHBZ#503133: *)
1378     InitBasicFS, Always, TestRun
1379       [["mkdir"; "/new"];
1380        ["mkdir_p"; "/new"]];
1381     InitBasicFS, Always, TestLastFail
1382       [["touch"; "/new"];
1383        ["mkdir_p"; "/new"]]],
1384    "create a directory and parents",
1385    "\
1386 Create a directory named C<path>, creating any parent directories
1387 as necessary.  This is like the C<mkdir -p> shell command.");
1388
1389   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1390    [], (* XXX Need stat command to test *)
1391    "change file mode",
1392    "\
1393 Change the mode (permissions) of C<path> to C<mode>.  Only
1394 numeric modes are supported.
1395
1396 I<Note>: When using this command from guestfish, C<mode>
1397 by default would be decimal, unless you prefix it with
1398 C<0> to get octal, ie. use C<0700> not C<700>.
1399
1400 The mode actually set is affected by the umask.");
1401
1402   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1403    [], (* XXX Need stat command to test *)
1404    "change file owner and group",
1405    "\
1406 Change the file owner to C<owner> and group to C<group>.
1407
1408 Only numeric uid and gid are supported.  If you want to use
1409 names, you will need to locate and parse the password file
1410 yourself (Augeas support makes this relatively easy).");
1411
1412   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1413    [InitISOFS, Always, TestOutputTrue (
1414       [["exists"; "/empty"]]);
1415     InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/directory"]])],
1417    "test if file or directory exists",
1418    "\
1419 This returns C<true> if and only if there is a file, directory
1420 (or anything) with the given C<path> name.
1421
1422 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1423
1424   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1425    [InitISOFS, Always, TestOutputTrue (
1426       [["is_file"; "/known-1"]]);
1427     InitISOFS, Always, TestOutputFalse (
1428       [["is_file"; "/directory"]])],
1429    "test if file exists",
1430    "\
1431 This returns C<true> if and only if there is a file
1432 with the given C<path> name.  Note that it returns false for
1433 other objects like directories.
1434
1435 See also C<guestfs_stat>.");
1436
1437   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1438    [InitISOFS, Always, TestOutputFalse (
1439       [["is_dir"; "/known-3"]]);
1440     InitISOFS, Always, TestOutputTrue (
1441       [["is_dir"; "/directory"]])],
1442    "test if file exists",
1443    "\
1444 This returns C<true> if and only if there is a directory
1445 with the given C<path> name.  Note that it returns false for
1446 other objects like files.
1447
1448 See also C<guestfs_stat>.");
1449
1450   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1451    [InitEmpty, Always, TestOutputListOfDevices (
1452       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1453        ["pvcreate"; "/dev/sda1"];
1454        ["pvcreate"; "/dev/sda2"];
1455        ["pvcreate"; "/dev/sda3"];
1456        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1457    "create an LVM physical volume",
1458    "\
1459 This creates an LVM physical volume on the named C<device>,
1460 where C<device> should usually be a partition name such
1461 as C</dev/sda1>.");
1462
1463   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1464    [InitEmpty, Always, TestOutputList (
1465       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1466        ["pvcreate"; "/dev/sda1"];
1467        ["pvcreate"; "/dev/sda2"];
1468        ["pvcreate"; "/dev/sda3"];
1469        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1470        ["vgcreate"; "VG2"; "/dev/sda3"];
1471        ["vgs"]], ["VG1"; "VG2"])],
1472    "create an LVM volume group",
1473    "\
1474 This creates an LVM volume group called C<volgroup>
1475 from the non-empty list of physical volumes C<physvols>.");
1476
1477   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1478    [InitEmpty, Always, TestOutputList (
1479       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1480        ["pvcreate"; "/dev/sda1"];
1481        ["pvcreate"; "/dev/sda2"];
1482        ["pvcreate"; "/dev/sda3"];
1483        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1484        ["vgcreate"; "VG2"; "/dev/sda3"];
1485        ["lvcreate"; "LV1"; "VG1"; "50"];
1486        ["lvcreate"; "LV2"; "VG1"; "50"];
1487        ["lvcreate"; "LV3"; "VG2"; "50"];
1488        ["lvcreate"; "LV4"; "VG2"; "50"];
1489        ["lvcreate"; "LV5"; "VG2"; "50"];
1490        ["lvs"]],
1491       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1492        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1493    "create an LVM logical volume",
1494    "\
1495 This creates an LVM logical volume called C<logvol>
1496 on the volume group C<volgroup>, with C<size> megabytes.");
1497
1498   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1499    [InitEmpty, Always, TestOutput (
1500       [["part_disk"; "/dev/sda"; "mbr"];
1501        ["mkfs"; "ext2"; "/dev/sda1"];
1502        ["mount_options"; ""; "/dev/sda1"; "/"];
1503        ["write_file"; "/new"; "new file contents"; "0"];
1504        ["cat"; "/new"]], "new file contents")],
1505    "make a filesystem",
1506    "\
1507 This creates a filesystem on C<device> (usually a partition
1508 or LVM logical volume).  The filesystem type is C<fstype>, for
1509 example C<ext3>.");
1510
1511   ("sfdisk", (RErr, [Device "device";
1512                      Int "cyls"; Int "heads"; Int "sectors";
1513                      StringList "lines"]), 43, [DangerWillRobinson],
1514    [],
1515    "create partitions on a block device",
1516    "\
1517 This is a direct interface to the L<sfdisk(8)> program for creating
1518 partitions on block devices.
1519
1520 C<device> should be a block device, for example C</dev/sda>.
1521
1522 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1523 and sectors on the device, which are passed directly to sfdisk as
1524 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1525 of these, then the corresponding parameter is omitted.  Usually for
1526 'large' disks, you can just pass C<0> for these, but for small
1527 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1528 out the right geometry and you will need to tell it.
1529
1530 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1531 information refer to the L<sfdisk(8)> manpage.
1532
1533 To create a single partition occupying the whole disk, you would
1534 pass C<lines> as a single element list, when the single element being
1535 the string C<,> (comma).
1536
1537 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1538 C<guestfs_part_init>");
1539
1540   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1541    [InitBasicFS, Always, TestOutput (
1542       [["write_file"; "/new"; "new file contents"; "0"];
1543        ["cat"; "/new"]], "new file contents");
1544     InitBasicFS, Always, TestOutput (
1545       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1546        ["cat"; "/new"]], "\nnew file contents\n");
1547     InitBasicFS, Always, TestOutput (
1548       [["write_file"; "/new"; "\n\n"; "0"];
1549        ["cat"; "/new"]], "\n\n");
1550     InitBasicFS, Always, TestOutput (
1551       [["write_file"; "/new"; ""; "0"];
1552        ["cat"; "/new"]], "");
1553     InitBasicFS, Always, TestOutput (
1554       [["write_file"; "/new"; "\n\n\n"; "0"];
1555        ["cat"; "/new"]], "\n\n\n");
1556     InitBasicFS, Always, TestOutput (
1557       [["write_file"; "/new"; "\n"; "0"];
1558        ["cat"; "/new"]], "\n")],
1559    "create a file",
1560    "\
1561 This call creates a file called C<path>.  The contents of the
1562 file is the string C<content> (which can contain any 8 bit data),
1563 with length C<size>.
1564
1565 As a special case, if C<size> is C<0>
1566 then the length is calculated using C<strlen> (so in this case
1567 the content cannot contain embedded ASCII NULs).
1568
1569 I<NB.> Owing to a bug, writing content containing ASCII NUL
1570 characters does I<not> work, even if the length is specified.
1571 We hope to resolve this bug in a future version.  In the meantime
1572 use C<guestfs_upload>.");
1573
1574   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1575    [InitEmpty, Always, TestOutputListOfDevices (
1576       [["part_disk"; "/dev/sda"; "mbr"];
1577        ["mkfs"; "ext2"; "/dev/sda1"];
1578        ["mount_options"; ""; "/dev/sda1"; "/"];
1579        ["mounts"]], ["/dev/sda1"]);
1580     InitEmpty, Always, TestOutputList (
1581       [["part_disk"; "/dev/sda"; "mbr"];
1582        ["mkfs"; "ext2"; "/dev/sda1"];
1583        ["mount_options"; ""; "/dev/sda1"; "/"];
1584        ["umount"; "/"];
1585        ["mounts"]], [])],
1586    "unmount a filesystem",
1587    "\
1588 This unmounts the given filesystem.  The filesystem may be
1589 specified either by its mountpoint (path) or the device which
1590 contains the filesystem.");
1591
1592   ("mounts", (RStringList "devices", []), 46, [],
1593    [InitBasicFS, Always, TestOutputListOfDevices (
1594       [["mounts"]], ["/dev/sda1"])],
1595    "show mounted filesystems",
1596    "\
1597 This returns the list of currently mounted filesystems.  It returns
1598 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1599
1600 Some internal mounts are not shown.
1601
1602 See also: C<guestfs_mountpoints>");
1603
1604   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1605    [InitBasicFS, Always, TestOutputList (
1606       [["umount_all"];
1607        ["mounts"]], []);
1608     (* check that umount_all can unmount nested mounts correctly: *)
1609     InitEmpty, Always, TestOutputList (
1610       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1611        ["mkfs"; "ext2"; "/dev/sda1"];
1612        ["mkfs"; "ext2"; "/dev/sda2"];
1613        ["mkfs"; "ext2"; "/dev/sda3"];
1614        ["mount_options"; ""; "/dev/sda1"; "/"];
1615        ["mkdir"; "/mp1"];
1616        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1617        ["mkdir"; "/mp1/mp2"];
1618        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1619        ["mkdir"; "/mp1/mp2/mp3"];
1620        ["umount_all"];
1621        ["mounts"]], [])],
1622    "unmount all filesystems",
1623    "\
1624 This unmounts all mounted filesystems.
1625
1626 Some internal mounts are not unmounted by this call.");
1627
1628   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1629    [],
1630    "remove all LVM LVs, VGs and PVs",
1631    "\
1632 This command removes all LVM logical volumes, volume groups
1633 and physical volumes.");
1634
1635   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1636    [InitISOFS, Always, TestOutput (
1637       [["file"; "/empty"]], "empty");
1638     InitISOFS, Always, TestOutput (
1639       [["file"; "/known-1"]], "ASCII text");
1640     InitISOFS, Always, TestLastFail (
1641       [["file"; "/notexists"]])],
1642    "determine file type",
1643    "\
1644 This call uses the standard L<file(1)> command to determine
1645 the type or contents of the file.  This also works on devices,
1646 for example to find out whether a partition contains a filesystem.
1647
1648 This call will also transparently look inside various types
1649 of compressed file.
1650
1651 The exact command which runs is C<file -zbsL path>.  Note in
1652 particular that the filename is not prepended to the output
1653 (the C<-b> option).");
1654
1655   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1656    [InitBasicFS, Always, TestOutput (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command"; "/test-command 1"]], "Result1");
1660     InitBasicFS, Always, TestOutput (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command"; "/test-command 2"]], "Result2\n");
1664     InitBasicFS, Always, TestOutput (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command"; "/test-command 3"]], "\nResult3");
1668     InitBasicFS, Always, TestOutput (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command"; "/test-command 4"]], "\nResult4\n");
1672     InitBasicFS, Always, TestOutput (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command"; "/test-command 5"]], "\nResult5\n\n");
1676     InitBasicFS, Always, TestOutput (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1680     InitBasicFS, Always, TestOutput (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command"; "/test-command 7"]], "");
1684     InitBasicFS, Always, TestOutput (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command"; "/test-command 8"]], "\n");
1688     InitBasicFS, Always, TestOutput (
1689       [["upload"; "test-command"; "/test-command"];
1690        ["chmod"; "0o755"; "/test-command"];
1691        ["command"; "/test-command 9"]], "\n\n");
1692     InitBasicFS, Always, TestOutput (
1693       [["upload"; "test-command"; "/test-command"];
1694        ["chmod"; "0o755"; "/test-command"];
1695        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1696     InitBasicFS, Always, TestOutput (
1697       [["upload"; "test-command"; "/test-command"];
1698        ["chmod"; "0o755"; "/test-command"];
1699        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1700     InitBasicFS, Always, TestLastFail (
1701       [["upload"; "test-command"; "/test-command"];
1702        ["chmod"; "0o755"; "/test-command"];
1703        ["command"; "/test-command"]])],
1704    "run a command from the guest filesystem",
1705    "\
1706 This call runs a command from the guest filesystem.  The
1707 filesystem must be mounted, and must contain a compatible
1708 operating system (ie. something Linux, with the same
1709 or compatible processor architecture).
1710
1711 The single parameter is an argv-style list of arguments.
1712 The first element is the name of the program to run.
1713 Subsequent elements are parameters.  The list must be
1714 non-empty (ie. must contain a program name).  Note that
1715 the command runs directly, and is I<not> invoked via
1716 the shell (see C<guestfs_sh>).
1717
1718 The return value is anything printed to I<stdout> by
1719 the command.
1720
1721 If the command returns a non-zero exit status, then
1722 this function returns an error message.  The error message
1723 string is the content of I<stderr> from the command.
1724
1725 The C<$PATH> environment variable will contain at least
1726 C</usr/bin> and C</bin>.  If you require a program from
1727 another location, you should provide the full path in the
1728 first parameter.
1729
1730 Shared libraries and data files required by the program
1731 must be available on filesystems which are mounted in the
1732 correct places.  It is the caller's responsibility to ensure
1733 all filesystems that are needed are mounted at the right
1734 locations.");
1735
1736   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1737    [InitBasicFS, Always, TestOutputList (
1738       [["upload"; "test-command"; "/test-command"];
1739        ["chmod"; "0o755"; "/test-command"];
1740        ["command_lines"; "/test-command 1"]], ["Result1"]);
1741     InitBasicFS, Always, TestOutputList (
1742       [["upload"; "test-command"; "/test-command"];
1743        ["chmod"; "0o755"; "/test-command"];
1744        ["command_lines"; "/test-command 2"]], ["Result2"]);
1745     InitBasicFS, Always, TestOutputList (
1746       [["upload"; "test-command"; "/test-command"];
1747        ["chmod"; "0o755"; "/test-command"];
1748        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1749     InitBasicFS, Always, TestOutputList (
1750       [["upload"; "test-command"; "/test-command"];
1751        ["chmod"; "0o755"; "/test-command"];
1752        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1753     InitBasicFS, Always, TestOutputList (
1754       [["upload"; "test-command"; "/test-command"];
1755        ["chmod"; "0o755"; "/test-command"];
1756        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1757     InitBasicFS, Always, TestOutputList (
1758       [["upload"; "test-command"; "/test-command"];
1759        ["chmod"; "0o755"; "/test-command"];
1760        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1761     InitBasicFS, Always, TestOutputList (
1762       [["upload"; "test-command"; "/test-command"];
1763        ["chmod"; "0o755"; "/test-command"];
1764        ["command_lines"; "/test-command 7"]], []);
1765     InitBasicFS, Always, TestOutputList (
1766       [["upload"; "test-command"; "/test-command"];
1767        ["chmod"; "0o755"; "/test-command"];
1768        ["command_lines"; "/test-command 8"]], [""]);
1769     InitBasicFS, Always, TestOutputList (
1770       [["upload"; "test-command"; "/test-command"];
1771        ["chmod"; "0o755"; "/test-command"];
1772        ["command_lines"; "/test-command 9"]], ["";""]);
1773     InitBasicFS, Always, TestOutputList (
1774       [["upload"; "test-command"; "/test-command"];
1775        ["chmod"; "0o755"; "/test-command"];
1776        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1777     InitBasicFS, Always, TestOutputList (
1778       [["upload"; "test-command"; "/test-command"];
1779        ["chmod"; "0o755"; "/test-command"];
1780        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1781    "run a command, returning lines",
1782    "\
1783 This is the same as C<guestfs_command>, but splits the
1784 result into a list of lines.
1785
1786 See also: C<guestfs_sh_lines>");
1787
1788   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1789    [InitISOFS, Always, TestOutputStruct (
1790       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1791    "get file information",
1792    "\
1793 Returns file information for the given C<path>.
1794
1795 This is the same as the C<stat(2)> system call.");
1796
1797   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1798    [InitISOFS, Always, TestOutputStruct (
1799       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1800    "get file information for a symbolic link",
1801    "\
1802 Returns file information for the given C<path>.
1803
1804 This is the same as C<guestfs_stat> except that if C<path>
1805 is a symbolic link, then the link is stat-ed, not the file it
1806 refers to.
1807
1808 This is the same as the C<lstat(2)> system call.");
1809
1810   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1811    [InitISOFS, Always, TestOutputStruct (
1812       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1813    "get file system statistics",
1814    "\
1815 Returns file system statistics for any mounted file system.
1816 C<path> should be a file or directory in the mounted file system
1817 (typically it is the mount point itself, but it doesn't need to be).
1818
1819 This is the same as the C<statvfs(2)> system call.");
1820
1821   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1822    [], (* XXX test *)
1823    "get ext2/ext3/ext4 superblock details",
1824    "\
1825 This returns the contents of the ext2, ext3 or ext4 filesystem
1826 superblock on C<device>.
1827
1828 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1829 manpage for more details.  The list of fields returned isn't
1830 clearly defined, and depends on both the version of C<tune2fs>
1831 that libguestfs was built against, and the filesystem itself.");
1832
1833   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1834    [InitEmpty, Always, TestOutputTrue (
1835       [["blockdev_setro"; "/dev/sda"];
1836        ["blockdev_getro"; "/dev/sda"]])],
1837    "set block device to read-only",
1838    "\
1839 Sets the block device named C<device> to read-only.
1840
1841 This uses the L<blockdev(8)> command.");
1842
1843   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1844    [InitEmpty, Always, TestOutputFalse (
1845       [["blockdev_setrw"; "/dev/sda"];
1846        ["blockdev_getro"; "/dev/sda"]])],
1847    "set block device to read-write",
1848    "\
1849 Sets the block device named C<device> to read-write.
1850
1851 This uses the L<blockdev(8)> command.");
1852
1853   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1854    [InitEmpty, Always, TestOutputTrue (
1855       [["blockdev_setro"; "/dev/sda"];
1856        ["blockdev_getro"; "/dev/sda"]])],
1857    "is block device set to read-only",
1858    "\
1859 Returns a boolean indicating if the block device is read-only
1860 (true if read-only, false if not).
1861
1862 This uses the L<blockdev(8)> command.");
1863
1864   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1865    [InitEmpty, Always, TestOutputInt (
1866       [["blockdev_getss"; "/dev/sda"]], 512)],
1867    "get sectorsize of block device",
1868    "\
1869 This returns the size of sectors on a block device.
1870 Usually 512, but can be larger for modern devices.
1871
1872 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1873 for that).
1874
1875 This uses the L<blockdev(8)> command.");
1876
1877   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1878    [InitEmpty, Always, TestOutputInt (
1879       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1880    "get blocksize of block device",
1881    "\
1882 This returns the block size of a device.
1883
1884 (Note this is different from both I<size in blocks> and
1885 I<filesystem block size>).
1886
1887 This uses the L<blockdev(8)> command.");
1888
1889   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1890    [], (* XXX test *)
1891    "set blocksize of block device",
1892    "\
1893 This sets the block size of a device.
1894
1895 (Note this is different from both I<size in blocks> and
1896 I<filesystem block size>).
1897
1898 This uses the L<blockdev(8)> command.");
1899
1900   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1901    [InitEmpty, Always, TestOutputInt (
1902       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1903    "get total size of device in 512-byte sectors",
1904    "\
1905 This returns the size of the device in units of 512-byte sectors
1906 (even if the sectorsize isn't 512 bytes ... weird).
1907
1908 See also C<guestfs_blockdev_getss> for the real sector size of
1909 the device, and C<guestfs_blockdev_getsize64> for the more
1910 useful I<size in bytes>.
1911
1912 This uses the L<blockdev(8)> command.");
1913
1914   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1915    [InitEmpty, Always, TestOutputInt (
1916       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1917    "get total size of device in bytes",
1918    "\
1919 This returns the size of the device in bytes.
1920
1921 See also C<guestfs_blockdev_getsz>.
1922
1923 This uses the L<blockdev(8)> command.");
1924
1925   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1926    [InitEmpty, Always, TestRun
1927       [["blockdev_flushbufs"; "/dev/sda"]]],
1928    "flush device buffers",
1929    "\
1930 This tells the kernel to flush internal buffers associated
1931 with C<device>.
1932
1933 This uses the L<blockdev(8)> command.");
1934
1935   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1936    [InitEmpty, Always, TestRun
1937       [["blockdev_rereadpt"; "/dev/sda"]]],
1938    "reread partition table",
1939    "\
1940 Reread the partition table on C<device>.
1941
1942 This uses the L<blockdev(8)> command.");
1943
1944   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1945    [InitBasicFS, Always, TestOutput (
1946       (* Pick a file from cwd which isn't likely to change. *)
1947       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1948        ["checksum"; "md5"; "/COPYING.LIB"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "upload a file from the local machine",
1951    "\
1952 Upload local file C<filename> to C<remotefilename> on the
1953 filesystem.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_download>.");
1958
1959   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1960    [InitBasicFS, Always, TestOutput (
1961       (* Pick a file from cwd which isn't likely to change. *)
1962       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1963        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1964        ["upload"; "testdownload.tmp"; "/upload"];
1965        ["checksum"; "md5"; "/upload"]],
1966       Digest.to_hex (Digest.file "COPYING.LIB"))],
1967    "download a file to the local machine",
1968    "\
1969 Download file C<remotefilename> and save it as C<filename>
1970 on the local machine.
1971
1972 C<filename> can also be a named pipe.
1973
1974 See also C<guestfs_upload>, C<guestfs_cat>.");
1975
1976   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1977    [InitISOFS, Always, TestOutput (
1978       [["checksum"; "crc"; "/known-3"]], "2891671662");
1979     InitISOFS, Always, TestLastFail (
1980       [["checksum"; "crc"; "/notexists"]]);
1981     InitISOFS, Always, TestOutput (
1982       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1987     InitISOFS, Always, TestOutput (
1988       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1989     InitISOFS, Always, TestOutput (
1990       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1991     InitISOFS, Always, TestOutput (
1992       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1993     (* Test for RHBZ#579608, absolute symbolic links. *)
1994     InitISOFS, Always, TestOutput (
1995       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1996    "compute MD5, SHAx or CRC checksum of file",
1997    "\
1998 This call computes the MD5, SHAx or CRC checksum of the
1999 file named C<path>.
2000
2001 The type of checksum to compute is given by the C<csumtype>
2002 parameter which must have one of the following values:
2003
2004 =over 4
2005
2006 =item C<crc>
2007
2008 Compute the cyclic redundancy check (CRC) specified by POSIX
2009 for the C<cksum> command.
2010
2011 =item C<md5>
2012
2013 Compute the MD5 hash (using the C<md5sum> program).
2014
2015 =item C<sha1>
2016
2017 Compute the SHA1 hash (using the C<sha1sum> program).
2018
2019 =item C<sha224>
2020
2021 Compute the SHA224 hash (using the C<sha224sum> program).
2022
2023 =item C<sha256>
2024
2025 Compute the SHA256 hash (using the C<sha256sum> program).
2026
2027 =item C<sha384>
2028
2029 Compute the SHA384 hash (using the C<sha384sum> program).
2030
2031 =item C<sha512>
2032
2033 Compute the SHA512 hash (using the C<sha512sum> program).
2034
2035 =back
2036
2037 The checksum is returned as a printable string.
2038
2039 To get the checksum for a device, use C<guestfs_checksum_device>.
2040
2041 To get the checksums for many files, use C<guestfs_checksums_out>.");
2042
2043   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2044    [InitBasicFS, Always, TestOutput (
2045       [["tar_in"; "../images/helloworld.tar"; "/"];
2046        ["cat"; "/hello"]], "hello\n")],
2047    "unpack tarfile to directory",
2048    "\
2049 This command uploads and unpacks local file C<tarfile> (an
2050 I<uncompressed> tar file) into C<directory>.
2051
2052 To upload a compressed tarball, use C<guestfs_tgz_in>
2053 or C<guestfs_txz_in>.");
2054
2055   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2056    [],
2057    "pack directory into tarfile",
2058    "\
2059 This command packs the contents of C<directory> and downloads
2060 it to local file C<tarfile>.
2061
2062 To download a compressed tarball, use C<guestfs_tgz_out>
2063 or C<guestfs_txz_out>.");
2064
2065   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2066    [InitBasicFS, Always, TestOutput (
2067       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2068        ["cat"; "/hello"]], "hello\n")],
2069    "unpack compressed tarball to directory",
2070    "\
2071 This command uploads and unpacks local file C<tarball> (a
2072 I<gzip compressed> tar file) into C<directory>.
2073
2074 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2075
2076   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2077    [],
2078    "pack directory into compressed tarball",
2079    "\
2080 This command packs the contents of C<directory> and downloads
2081 it to local file C<tarball>.
2082
2083 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2084
2085   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2086    [InitBasicFS, Always, TestLastFail (
2087       [["umount"; "/"];
2088        ["mount_ro"; "/dev/sda1"; "/"];
2089        ["touch"; "/new"]]);
2090     InitBasicFS, Always, TestOutput (
2091       [["write_file"; "/new"; "data"; "0"];
2092        ["umount"; "/"];
2093        ["mount_ro"; "/dev/sda1"; "/"];
2094        ["cat"; "/new"]], "data")],
2095    "mount a guest disk, read-only",
2096    "\
2097 This is the same as the C<guestfs_mount> command, but it
2098 mounts the filesystem with the read-only (I<-o ro>) flag.");
2099
2100   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2101    [],
2102    "mount a guest disk with mount options",
2103    "\
2104 This is the same as the C<guestfs_mount> command, but it
2105 allows you to set the mount options as for the
2106 L<mount(8)> I<-o> flag.
2107
2108 If the C<options> parameter is an empty string, then
2109 no options are passed (all options default to whatever
2110 the filesystem uses).");
2111
2112   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2113    [],
2114    "mount a guest disk with mount options and vfstype",
2115    "\
2116 This is the same as the C<guestfs_mount> command, but it
2117 allows you to set both the mount options and the vfstype
2118 as for the L<mount(8)> I<-o> and I<-t> flags.");
2119
2120   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2121    [],
2122    "debugging and internals",
2123    "\
2124 The C<guestfs_debug> command exposes some internals of
2125 C<guestfsd> (the guestfs daemon) that runs inside the
2126 qemu subprocess.
2127
2128 There is no comprehensive help for this command.  You have
2129 to look at the file C<daemon/debug.c> in the libguestfs source
2130 to find out what you can do.");
2131
2132   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2133    [InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["lvremove"; "/dev/VG/LV1"];
2140        ["lvs"]], ["/dev/VG/LV2"]);
2141     InitEmpty, Always, TestOutputList (
2142       [["part_disk"; "/dev/sda"; "mbr"];
2143        ["pvcreate"; "/dev/sda1"];
2144        ["vgcreate"; "VG"; "/dev/sda1"];
2145        ["lvcreate"; "LV1"; "VG"; "50"];
2146        ["lvcreate"; "LV2"; "VG"; "50"];
2147        ["lvremove"; "/dev/VG"];
2148        ["lvs"]], []);
2149     InitEmpty, Always, TestOutputList (
2150       [["part_disk"; "/dev/sda"; "mbr"];
2151        ["pvcreate"; "/dev/sda1"];
2152        ["vgcreate"; "VG"; "/dev/sda1"];
2153        ["lvcreate"; "LV1"; "VG"; "50"];
2154        ["lvcreate"; "LV2"; "VG"; "50"];
2155        ["lvremove"; "/dev/VG"];
2156        ["vgs"]], ["VG"])],
2157    "remove an LVM logical volume",
2158    "\
2159 Remove an LVM logical volume C<device>, where C<device> is
2160 the path to the LV, such as C</dev/VG/LV>.
2161
2162 You can also remove all LVs in a volume group by specifying
2163 the VG name, C</dev/VG>.");
2164
2165   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2166    [InitEmpty, Always, TestOutputList (
2167       [["part_disk"; "/dev/sda"; "mbr"];
2168        ["pvcreate"; "/dev/sda1"];
2169        ["vgcreate"; "VG"; "/dev/sda1"];
2170        ["lvcreate"; "LV1"; "VG"; "50"];
2171        ["lvcreate"; "LV2"; "VG"; "50"];
2172        ["vgremove"; "VG"];
2173        ["lvs"]], []);
2174     InitEmpty, Always, TestOutputList (
2175       [["part_disk"; "/dev/sda"; "mbr"];
2176        ["pvcreate"; "/dev/sda1"];
2177        ["vgcreate"; "VG"; "/dev/sda1"];
2178        ["lvcreate"; "LV1"; "VG"; "50"];
2179        ["lvcreate"; "LV2"; "VG"; "50"];
2180        ["vgremove"; "VG"];
2181        ["vgs"]], [])],
2182    "remove an LVM volume group",
2183    "\
2184 Remove an LVM volume group C<vgname>, (for example C<VG>).
2185
2186 This also forcibly removes all logical volumes in the volume
2187 group (if any).");
2188
2189   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2190    [InitEmpty, Always, TestOutputListOfDevices (
2191       [["part_disk"; "/dev/sda"; "mbr"];
2192        ["pvcreate"; "/dev/sda1"];
2193        ["vgcreate"; "VG"; "/dev/sda1"];
2194        ["lvcreate"; "LV1"; "VG"; "50"];
2195        ["lvcreate"; "LV2"; "VG"; "50"];
2196        ["vgremove"; "VG"];
2197        ["pvremove"; "/dev/sda1"];
2198        ["lvs"]], []);
2199     InitEmpty, Always, TestOutputListOfDevices (
2200       [["part_disk"; "/dev/sda"; "mbr"];
2201        ["pvcreate"; "/dev/sda1"];
2202        ["vgcreate"; "VG"; "/dev/sda1"];
2203        ["lvcreate"; "LV1"; "VG"; "50"];
2204        ["lvcreate"; "LV2"; "VG"; "50"];
2205        ["vgremove"; "VG"];
2206        ["pvremove"; "/dev/sda1"];
2207        ["vgs"]], []);
2208     InitEmpty, Always, TestOutputListOfDevices (
2209       [["part_disk"; "/dev/sda"; "mbr"];
2210        ["pvcreate"; "/dev/sda1"];
2211        ["vgcreate"; "VG"; "/dev/sda1"];
2212        ["lvcreate"; "LV1"; "VG"; "50"];
2213        ["lvcreate"; "LV2"; "VG"; "50"];
2214        ["vgremove"; "VG"];
2215        ["pvremove"; "/dev/sda1"];
2216        ["pvs"]], [])],
2217    "remove an LVM physical volume",
2218    "\
2219 This wipes a physical volume C<device> so that LVM will no longer
2220 recognise it.
2221
2222 The implementation uses the C<pvremove> command which refuses to
2223 wipe physical volumes that contain any volume groups, so you have
2224 to remove those first.");
2225
2226   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2227    [InitBasicFS, Always, TestOutput (
2228       [["set_e2label"; "/dev/sda1"; "testlabel"];
2229        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2230    "set the ext2/3/4 filesystem label",
2231    "\
2232 This sets the ext2/3/4 filesystem label of the filesystem on
2233 C<device> to C<label>.  Filesystem labels are limited to
2234 16 characters.
2235
2236 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2237 to return the existing label on a filesystem.");
2238
2239   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2240    [],
2241    "get the ext2/3/4 filesystem label",
2242    "\
2243 This returns the ext2/3/4 filesystem label of the filesystem on
2244 C<device>.");
2245
2246   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2247    (let uuid = uuidgen () in
2248     [InitBasicFS, Always, TestOutput (
2249        [["set_e2uuid"; "/dev/sda1"; uuid];
2250         ["get_e2uuid"; "/dev/sda1"]], uuid);
2251      InitBasicFS, Always, TestOutput (
2252        [["set_e2uuid"; "/dev/sda1"; "clear"];
2253         ["get_e2uuid"; "/dev/sda1"]], "");
2254      (* We can't predict what UUIDs will be, so just check the commands run. *)
2255      InitBasicFS, Always, TestRun (
2256        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2257      InitBasicFS, Always, TestRun (
2258        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2259    "set the ext2/3/4 filesystem UUID",
2260    "\
2261 This sets the ext2/3/4 filesystem UUID of the filesystem on
2262 C<device> to C<uuid>.  The format of the UUID and alternatives
2263 such as C<clear>, C<random> and C<time> are described in the
2264 L<tune2fs(8)> manpage.
2265
2266 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2267 to return the existing UUID of a filesystem.");
2268
2269   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2270    [],
2271    "get the ext2/3/4 filesystem UUID",
2272    "\
2273 This returns the ext2/3/4 filesystem UUID of the filesystem on
2274 C<device>.");
2275
2276   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2277    [InitBasicFS, Always, TestOutputInt (
2278       [["umount"; "/dev/sda1"];
2279        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2280     InitBasicFS, Always, TestOutputInt (
2281       [["umount"; "/dev/sda1"];
2282        ["zero"; "/dev/sda1"];
2283        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2284    "run the filesystem checker",
2285    "\
2286 This runs the filesystem checker (fsck) on C<device> which
2287 should have filesystem type C<fstype>.
2288
2289 The returned integer is the status.  See L<fsck(8)> for the
2290 list of status codes from C<fsck>.
2291
2292 Notes:
2293
2294 =over 4
2295
2296 =item *
2297
2298 Multiple status codes can be summed together.
2299
2300 =item *
2301
2302 A non-zero return code can mean \"success\", for example if
2303 errors have been corrected on the filesystem.
2304
2305 =item *
2306
2307 Checking or repairing NTFS volumes is not supported
2308 (by linux-ntfs).
2309
2310 =back
2311
2312 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2313
2314   ("zero", (RErr, [Device "device"]), 85, [],
2315    [InitBasicFS, Always, TestOutput (
2316       [["umount"; "/dev/sda1"];
2317        ["zero"; "/dev/sda1"];
2318        ["file"; "/dev/sda1"]], "data")],
2319    "write zeroes to the device",
2320    "\
2321 This command writes zeroes over the first few blocks of C<device>.
2322
2323 How many blocks are zeroed isn't specified (but it's I<not> enough
2324 to securely wipe the device).  It should be sufficient to remove
2325 any partition tables, filesystem superblocks and so on.
2326
2327 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2328
2329   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2330    (* Test disabled because grub-install incompatible with virtio-blk driver.
2331     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2332     *)
2333    [InitBasicFS, Disabled, TestOutputTrue (
2334       [["grub_install"; "/"; "/dev/sda1"];
2335        ["is_dir"; "/boot"]])],
2336    "install GRUB",
2337    "\
2338 This command installs GRUB (the Grand Unified Bootloader) on
2339 C<device>, with the root directory being C<root>.");
2340
2341   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2342    [InitBasicFS, Always, TestOutput (
2343       [["write_file"; "/old"; "file content"; "0"];
2344        ["cp"; "/old"; "/new"];
2345        ["cat"; "/new"]], "file content");
2346     InitBasicFS, Always, TestOutputTrue (
2347       [["write_file"; "/old"; "file content"; "0"];
2348        ["cp"; "/old"; "/new"];
2349        ["is_file"; "/old"]]);
2350     InitBasicFS, Always, TestOutput (
2351       [["write_file"; "/old"; "file content"; "0"];
2352        ["mkdir"; "/dir"];
2353        ["cp"; "/old"; "/dir/new"];
2354        ["cat"; "/dir/new"]], "file content")],
2355    "copy a file",
2356    "\
2357 This copies a file from C<src> to C<dest> where C<dest> is
2358 either a destination filename or destination directory.");
2359
2360   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2361    [InitBasicFS, Always, TestOutput (
2362       [["mkdir"; "/olddir"];
2363        ["mkdir"; "/newdir"];
2364        ["write_file"; "/olddir/file"; "file content"; "0"];
2365        ["cp_a"; "/olddir"; "/newdir"];
2366        ["cat"; "/newdir/olddir/file"]], "file content")],
2367    "copy a file or directory recursively",
2368    "\
2369 This copies a file or directory from C<src> to C<dest>
2370 recursively using the C<cp -a> command.");
2371
2372   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2373    [InitBasicFS, Always, TestOutput (
2374       [["write_file"; "/old"; "file content"; "0"];
2375        ["mv"; "/old"; "/new"];
2376        ["cat"; "/new"]], "file content");
2377     InitBasicFS, Always, TestOutputFalse (
2378       [["write_file"; "/old"; "file content"; "0"];
2379        ["mv"; "/old"; "/new"];
2380        ["is_file"; "/old"]])],
2381    "move a file",
2382    "\
2383 This moves a file from C<src> to C<dest> where C<dest> is
2384 either a destination filename or destination directory.");
2385
2386   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2387    [InitEmpty, Always, TestRun (
2388       [["drop_caches"; "3"]])],
2389    "drop kernel page cache, dentries and inodes",
2390    "\
2391 This instructs the guest kernel to drop its page cache,
2392 and/or dentries and inode caches.  The parameter C<whattodrop>
2393 tells the kernel what precisely to drop, see
2394 L<http://linux-mm.org/Drop_Caches>
2395
2396 Setting C<whattodrop> to 3 should drop everything.
2397
2398 This automatically calls L<sync(2)> before the operation,
2399 so that the maximum guest memory is freed.");
2400
2401   ("dmesg", (RString "kmsgs", []), 91, [],
2402    [InitEmpty, Always, TestRun (
2403       [["dmesg"]])],
2404    "return kernel messages",
2405    "\
2406 This returns the kernel messages (C<dmesg> output) from
2407 the guest kernel.  This is sometimes useful for extended
2408 debugging of problems.
2409
2410 Another way to get the same information is to enable
2411 verbose messages with C<guestfs_set_verbose> or by setting
2412 the environment variable C<LIBGUESTFS_DEBUG=1> before
2413 running the program.");
2414
2415   ("ping_daemon", (RErr, []), 92, [],
2416    [InitEmpty, Always, TestRun (
2417       [["ping_daemon"]])],
2418    "ping the guest daemon",
2419    "\
2420 This is a test probe into the guestfs daemon running inside
2421 the qemu subprocess.  Calling this function checks that the
2422 daemon responds to the ping message, without affecting the daemon
2423 or attached block device(s) in any other way.");
2424
2425   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2426    [InitBasicFS, Always, TestOutputTrue (
2427       [["write_file"; "/file1"; "contents of a file"; "0"];
2428        ["cp"; "/file1"; "/file2"];
2429        ["equal"; "/file1"; "/file2"]]);
2430     InitBasicFS, Always, TestOutputFalse (
2431       [["write_file"; "/file1"; "contents of a file"; "0"];
2432        ["write_file"; "/file2"; "contents of another file"; "0"];
2433        ["equal"; "/file1"; "/file2"]]);
2434     InitBasicFS, Always, TestLastFail (
2435       [["equal"; "/file1"; "/file2"]])],
2436    "test if two files have equal contents",
2437    "\
2438 This compares the two files C<file1> and C<file2> and returns
2439 true if their content is exactly equal, or false otherwise.
2440
2441 The external L<cmp(1)> program is used for the comparison.");
2442
2443   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2444    [InitISOFS, Always, TestOutputList (
2445       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2446     InitISOFS, Always, TestOutputList (
2447       [["strings"; "/empty"]], []);
2448     (* Test for RHBZ#579608, absolute symbolic links. *)
2449     InitISOFS, Always, TestRun (
2450       [["strings"; "/abssymlink"]])],
2451    "print the printable strings in a file",
2452    "\
2453 This runs the L<strings(1)> command on a file and returns
2454 the list of printable strings found.");
2455
2456   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2457    [InitISOFS, Always, TestOutputList (
2458       [["strings_e"; "b"; "/known-5"]], []);
2459     InitBasicFS, Disabled, TestOutputList (
2460       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2461        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2462    "print the printable strings in a file",
2463    "\
2464 This is like the C<guestfs_strings> command, but allows you to
2465 specify the encoding of strings that are looked for in
2466 the source file C<path>.
2467
2468 Allowed encodings are:
2469
2470 =over 4
2471
2472 =item s
2473
2474 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2475 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2476
2477 =item S
2478
2479 Single 8-bit-byte characters.
2480
2481 =item b
2482
2483 16-bit big endian strings such as those encoded in
2484 UTF-16BE or UCS-2BE.
2485
2486 =item l (lower case letter L)
2487
2488 16-bit little endian such as UTF-16LE and UCS-2LE.
2489 This is useful for examining binaries in Windows guests.
2490
2491 =item B
2492
2493 32-bit big endian such as UCS-4BE.
2494
2495 =item L
2496
2497 32-bit little endian such as UCS-4LE.
2498
2499 =back
2500
2501 The returned strings are transcoded to UTF-8.");
2502
2503   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2504    [InitISOFS, Always, TestOutput (
2505       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2506     (* Test for RHBZ#501888c2 regression which caused large hexdump
2507      * commands to segfault.
2508      *)
2509     InitISOFS, Always, TestRun (
2510       [["hexdump"; "/100krandom"]]);
2511     (* Test for RHBZ#579608, absolute symbolic links. *)
2512     InitISOFS, Always, TestRun (
2513       [["hexdump"; "/abssymlink"]])],
2514    "dump a file in hexadecimal",
2515    "\
2516 This runs C<hexdump -C> on the given C<path>.  The result is
2517 the human-readable, canonical hex dump of the file.");
2518
2519   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2520    [InitNone, Always, TestOutput (
2521       [["part_disk"; "/dev/sda"; "mbr"];
2522        ["mkfs"; "ext3"; "/dev/sda1"];
2523        ["mount_options"; ""; "/dev/sda1"; "/"];
2524        ["write_file"; "/new"; "test file"; "0"];
2525        ["umount"; "/dev/sda1"];
2526        ["zerofree"; "/dev/sda1"];
2527        ["mount_options"; ""; "/dev/sda1"; "/"];
2528        ["cat"; "/new"]], "test file")],
2529    "zero unused inodes and disk blocks on ext2/3 filesystem",
2530    "\
2531 This runs the I<zerofree> program on C<device>.  This program
2532 claims to zero unused inodes and disk blocks on an ext2/3
2533 filesystem, thus making it possible to compress the filesystem
2534 more effectively.
2535
2536 You should B<not> run this program if the filesystem is
2537 mounted.
2538
2539 It is possible that using this program can damage the filesystem
2540 or data on the filesystem.");
2541
2542   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2543    [],
2544    "resize an LVM physical volume",
2545    "\
2546 This resizes (expands or shrinks) an existing LVM physical
2547 volume to match the new size of the underlying device.");
2548
2549   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2550                        Int "cyls"; Int "heads"; Int "sectors";
2551                        String "line"]), 99, [DangerWillRobinson],
2552    [],
2553    "modify a single partition on a block device",
2554    "\
2555 This runs L<sfdisk(8)> option to modify just the single
2556 partition C<n> (note: C<n> counts from 1).
2557
2558 For other parameters, see C<guestfs_sfdisk>.  You should usually
2559 pass C<0> for the cyls/heads/sectors parameters.
2560
2561 See also: C<guestfs_part_add>");
2562
2563   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2564    [],
2565    "display the partition table",
2566    "\
2567 This displays the partition table on C<device>, in the
2568 human-readable output of the L<sfdisk(8)> command.  It is
2569 not intended to be parsed.
2570
2571 See also: C<guestfs_part_list>");
2572
2573   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2574    [],
2575    "display the kernel geometry",
2576    "\
2577 This displays the kernel's idea of the geometry of C<device>.
2578
2579 The result is in human-readable format, and not designed to
2580 be parsed.");
2581
2582   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2583    [],
2584    "display the disk geometry from the partition table",
2585    "\
2586 This displays the disk geometry of C<device> read from the
2587 partition table.  Especially in the case where the underlying
2588 block device has been resized, this can be different from the
2589 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2590
2591 The result is in human-readable format, and not designed to
2592 be parsed.");
2593
2594   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2595    [],
2596    "activate or deactivate all volume groups",
2597    "\
2598 This command activates or (if C<activate> is false) deactivates
2599 all logical volumes in all volume groups.
2600 If activated, then they are made known to the
2601 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2602 then those devices disappear.
2603
2604 This command is the same as running C<vgchange -a y|n>");
2605
2606   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2607    [],
2608    "activate or deactivate some volume groups",
2609    "\
2610 This command activates or (if C<activate> is false) deactivates
2611 all logical volumes in the listed volume groups C<volgroups>.
2612 If activated, then they are made known to the
2613 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2614 then those devices disappear.
2615
2616 This command is the same as running C<vgchange -a y|n volgroups...>
2617
2618 Note that if C<volgroups> is an empty list then B<all> volume groups
2619 are activated or deactivated.");
2620
2621   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2622    [InitNone, Always, TestOutput (
2623       [["part_disk"; "/dev/sda"; "mbr"];
2624        ["pvcreate"; "/dev/sda1"];
2625        ["vgcreate"; "VG"; "/dev/sda1"];
2626        ["lvcreate"; "LV"; "VG"; "10"];
2627        ["mkfs"; "ext2"; "/dev/VG/LV"];
2628        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2629        ["write_file"; "/new"; "test content"; "0"];
2630        ["umount"; "/"];
2631        ["lvresize"; "/dev/VG/LV"; "20"];
2632        ["e2fsck_f"; "/dev/VG/LV"];
2633        ["resize2fs"; "/dev/VG/LV"];
2634        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2635        ["cat"; "/new"]], "test content");
2636     InitNone, Always, TestRun (
2637       (* Make an LV smaller to test RHBZ#587484. *)
2638       [["part_disk"; "/dev/sda"; "mbr"];
2639        ["pvcreate"; "/dev/sda1"];
2640        ["vgcreate"; "VG"; "/dev/sda1"];
2641        ["lvcreate"; "LV"; "VG"; "20"];
2642        ["lvresize"; "/dev/VG/LV"; "10"]])],
2643    "resize an LVM logical volume",
2644    "\
2645 This resizes (expands or shrinks) an existing LVM logical
2646 volume to C<mbytes>.  When reducing, data in the reduced part
2647 is lost.");
2648
2649   ("resize2fs", (RErr, [Device "device"]), 106, [],
2650    [], (* lvresize tests this *)
2651    "resize an ext2/ext3 filesystem",
2652    "\
2653 This resizes an ext2 or ext3 filesystem to match the size of
2654 the underlying device.
2655
2656 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2657 on the C<device> before calling this command.  For unknown reasons
2658 C<resize2fs> sometimes gives an error about this and sometimes not.
2659 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2660 calling this function.");
2661
2662   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2663    [InitBasicFS, Always, TestOutputList (
2664       [["find"; "/"]], ["lost+found"]);
2665     InitBasicFS, Always, TestOutputList (
2666       [["touch"; "/a"];
2667        ["mkdir"; "/b"];
2668        ["touch"; "/b/c"];
2669        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2670     InitBasicFS, Always, TestOutputList (
2671       [["mkdir_p"; "/a/b/c"];
2672        ["touch"; "/a/b/c/d"];
2673        ["find"; "/a/b/"]], ["c"; "c/d"])],
2674    "find all files and directories",
2675    "\
2676 This command lists out all files and directories, recursively,
2677 starting at C<directory>.  It is essentially equivalent to
2678 running the shell command C<find directory -print> but some
2679 post-processing happens on the output, described below.
2680
2681 This returns a list of strings I<without any prefix>.  Thus
2682 if the directory structure was:
2683
2684  /tmp/a
2685  /tmp/b
2686  /tmp/c/d
2687
2688 then the returned list from C<guestfs_find> C</tmp> would be
2689 4 elements:
2690
2691  a
2692  b
2693  c
2694  c/d
2695
2696 If C<directory> is not a directory, then this command returns
2697 an error.
2698
2699 The returned list is sorted.
2700
2701 See also C<guestfs_find0>.");
2702
2703   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2704    [], (* lvresize tests this *)
2705    "check an ext2/ext3 filesystem",
2706    "\
2707 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2708 filesystem checker on C<device>, noninteractively (C<-p>),
2709 even if the filesystem appears to be clean (C<-f>).
2710
2711 This command is only needed because of C<guestfs_resize2fs>
2712 (q.v.).  Normally you should use C<guestfs_fsck>.");
2713
2714   ("sleep", (RErr, [Int "secs"]), 109, [],
2715    [InitNone, Always, TestRun (
2716       [["sleep"; "1"]])],
2717    "sleep for some seconds",
2718    "\
2719 Sleep for C<secs> seconds.");
2720
2721   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2722    [InitNone, Always, TestOutputInt (
2723       [["part_disk"; "/dev/sda"; "mbr"];
2724        ["mkfs"; "ntfs"; "/dev/sda1"];
2725        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2726     InitNone, Always, TestOutputInt (
2727       [["part_disk"; "/dev/sda"; "mbr"];
2728        ["mkfs"; "ext2"; "/dev/sda1"];
2729        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2730    "probe NTFS volume",
2731    "\
2732 This command runs the L<ntfs-3g.probe(8)> command which probes
2733 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2734 be mounted read-write, and some cannot be mounted at all).
2735
2736 C<rw> is a boolean flag.  Set it to true if you want to test
2737 if the volume can be mounted read-write.  Set it to false if
2738 you want to test if the volume can be mounted read-only.
2739
2740 The return value is an integer which C<0> if the operation
2741 would succeed, or some non-zero value documented in the
2742 L<ntfs-3g.probe(8)> manual page.");
2743
2744   ("sh", (RString "output", [String "command"]), 111, [],
2745    [], (* XXX needs tests *)
2746    "run a command via the shell",
2747    "\
2748 This call runs a command from the guest filesystem via the
2749 guest's C</bin/sh>.
2750
2751 This is like C<guestfs_command>, but passes the command to:
2752
2753  /bin/sh -c \"command\"
2754
2755 Depending on the guest's shell, this usually results in
2756 wildcards being expanded, shell expressions being interpolated
2757 and so on.
2758
2759 All the provisos about C<guestfs_command> apply to this call.");
2760
2761   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2762    [], (* XXX needs tests *)
2763    "run a command via the shell returning lines",
2764    "\
2765 This is the same as C<guestfs_sh>, but splits the result
2766 into a list of lines.
2767
2768 See also: C<guestfs_command_lines>");
2769
2770   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2771    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2772     * code in stubs.c, since all valid glob patterns must start with "/".
2773     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2774     *)
2775    [InitBasicFS, Always, TestOutputList (
2776       [["mkdir_p"; "/a/b/c"];
2777        ["touch"; "/a/b/c/d"];
2778        ["touch"; "/a/b/c/e"];
2779        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2780     InitBasicFS, Always, TestOutputList (
2781       [["mkdir_p"; "/a/b/c"];
2782        ["touch"; "/a/b/c/d"];
2783        ["touch"; "/a/b/c/e"];
2784        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2785     InitBasicFS, Always, TestOutputList (
2786       [["mkdir_p"; "/a/b/c"];
2787        ["touch"; "/a/b/c/d"];
2788        ["touch"; "/a/b/c/e"];
2789        ["glob_expand"; "/a/*/x/*"]], [])],
2790    "expand a wildcard path",
2791    "\
2792 This command searches for all the pathnames matching
2793 C<pattern> according to the wildcard expansion rules
2794 used by the shell.
2795
2796 If no paths match, then this returns an empty list
2797 (note: not an error).
2798
2799 It is just a wrapper around the C L<glob(3)> function
2800 with flags C<GLOB_MARK|GLOB_BRACE>.
2801 See that manual page for more details.");
2802
2803   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2804    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2805       [["scrub_device"; "/dev/sdc"]])],
2806    "scrub (securely wipe) a device",
2807    "\
2808 This command writes patterns over C<device> to make data retrieval
2809 more difficult.
2810
2811 It is an interface to the L<scrub(1)> program.  See that
2812 manual page for more details.");
2813
2814   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2815    [InitBasicFS, Always, TestRun (
2816       [["write_file"; "/file"; "content"; "0"];
2817        ["scrub_file"; "/file"]])],
2818    "scrub (securely wipe) a file",
2819    "\
2820 This command writes patterns over a file to make data retrieval
2821 more difficult.
2822
2823 The file is I<removed> after scrubbing.
2824
2825 It is an interface to the L<scrub(1)> program.  See that
2826 manual page for more details.");
2827
2828   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2829    [], (* XXX needs testing *)
2830    "scrub (securely wipe) free space",
2831    "\
2832 This command creates the directory C<dir> and then fills it
2833 with files until the filesystem is full, and scrubs the files
2834 as for C<guestfs_scrub_file>, and deletes them.
2835 The intention is to scrub any free space on the partition
2836 containing C<dir>.
2837
2838 It is an interface to the L<scrub(1)> program.  See that
2839 manual page for more details.");
2840
2841   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2842    [InitBasicFS, Always, TestRun (
2843       [["mkdir"; "/tmp"];
2844        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2845    "create a temporary directory",
2846    "\
2847 This command creates a temporary directory.  The
2848 C<template> parameter should be a full pathname for the
2849 temporary directory name with the final six characters being
2850 \"XXXXXX\".
2851
2852 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2853 the second one being suitable for Windows filesystems.
2854
2855 The name of the temporary directory that was created
2856 is returned.
2857
2858 The temporary directory is created with mode 0700
2859 and is owned by root.
2860
2861 The caller is responsible for deleting the temporary
2862 directory and its contents after use.
2863
2864 See also: L<mkdtemp(3)>");
2865
2866   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2867    [InitISOFS, Always, TestOutputInt (
2868       [["wc_l"; "/10klines"]], 10000);
2869     (* Test for RHBZ#579608, absolute symbolic links. *)
2870     InitISOFS, Always, TestOutputInt (
2871       [["wc_l"; "/abssymlink"]], 10000)],
2872    "count lines in a file",
2873    "\
2874 This command counts the lines in a file, using the
2875 C<wc -l> external command.");
2876
2877   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2878    [InitISOFS, Always, TestOutputInt (
2879       [["wc_w"; "/10klines"]], 10000)],
2880    "count words in a file",
2881    "\
2882 This command counts the words in a file, using the
2883 C<wc -w> external command.");
2884
2885   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2886    [InitISOFS, Always, TestOutputInt (
2887       [["wc_c"; "/100kallspaces"]], 102400)],
2888    "count characters in a file",
2889    "\
2890 This command counts the characters in a file, using the
2891 C<wc -c> external command.");
2892
2893   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2894    [InitISOFS, Always, TestOutputList (
2895       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2896     (* Test for RHBZ#579608, absolute symbolic links. *)
2897     InitISOFS, Always, TestOutputList (
2898       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2899    "return first 10 lines of a file",
2900    "\
2901 This command returns up to the first 10 lines of a file as
2902 a list of strings.");
2903
2904   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2905    [InitISOFS, Always, TestOutputList (
2906       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2907     InitISOFS, Always, TestOutputList (
2908       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2909     InitISOFS, Always, TestOutputList (
2910       [["head_n"; "0"; "/10klines"]], [])],
2911    "return first N lines of a file",
2912    "\
2913 If the parameter C<nrlines> is a positive number, this returns the first
2914 C<nrlines> lines of the file C<path>.
2915
2916 If the parameter C<nrlines> is a negative number, this returns lines
2917 from the file C<path>, excluding the last C<nrlines> lines.
2918
2919 If the parameter C<nrlines> is zero, this returns an empty list.");
2920
2921   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2922    [InitISOFS, Always, TestOutputList (
2923       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2924    "return last 10 lines of a file",
2925    "\
2926 This command returns up to the last 10 lines of a file as
2927 a list of strings.");
2928
2929   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2930    [InitISOFS, Always, TestOutputList (
2931       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2932     InitISOFS, Always, TestOutputList (
2933       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2934     InitISOFS, Always, TestOutputList (
2935       [["tail_n"; "0"; "/10klines"]], [])],
2936    "return last N lines of a file",
2937    "\
2938 If the parameter C<nrlines> is a positive number, this returns the last
2939 C<nrlines> lines of the file C<path>.
2940
2941 If the parameter C<nrlines> is a negative number, this returns lines
2942 from the file C<path>, starting with the C<-nrlines>th line.
2943
2944 If the parameter C<nrlines> is zero, this returns an empty list.");
2945
2946   ("df", (RString "output", []), 125, [],
2947    [], (* XXX Tricky to test because it depends on the exact format
2948         * of the 'df' command and other imponderables.
2949         *)
2950    "report file system disk space usage",
2951    "\
2952 This command runs the C<df> command to report disk space used.
2953
2954 This command is mostly useful for interactive sessions.  It
2955 is I<not> intended that you try to parse the output string.
2956 Use C<statvfs> from programs.");
2957
2958   ("df_h", (RString "output", []), 126, [],
2959    [], (* XXX Tricky to test because it depends on the exact format
2960         * of the 'df' command and other imponderables.
2961         *)
2962    "report file system disk space usage (human readable)",
2963    "\
2964 This command runs the C<df -h> command to report disk space used
2965 in human-readable format.
2966
2967 This command is mostly useful for interactive sessions.  It
2968 is I<not> intended that you try to parse the output string.
2969 Use C<statvfs> from programs.");
2970
2971   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2972    [InitISOFS, Always, TestOutputInt (
2973       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2974    "estimate file space usage",
2975    "\
2976 This command runs the C<du -s> command to estimate file space
2977 usage for C<path>.
2978
2979 C<path> can be a file or a directory.  If C<path> is a directory
2980 then the estimate includes the contents of the directory and all
2981 subdirectories (recursively).
2982
2983 The result is the estimated size in I<kilobytes>
2984 (ie. units of 1024 bytes).");
2985
2986   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2987    [InitISOFS, Always, TestOutputList (
2988       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2989    "list files in an initrd",
2990    "\
2991 This command lists out files contained in an initrd.
2992
2993 The files are listed without any initial C</> character.  The
2994 files are listed in the order they appear (not necessarily
2995 alphabetical).  Directory names are listed as separate items.
2996
2997 Old Linux kernels (2.4 and earlier) used a compressed ext2
2998 filesystem as initrd.  We I<only> support the newer initramfs
2999 format (compressed cpio files).");
3000
3001   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3002    [],
3003    "mount a file using the loop device",
3004    "\
3005 This command lets you mount C<file> (a filesystem image
3006 in a file) on a mount point.  It is entirely equivalent to
3007 the command C<mount -o loop file mountpoint>.");
3008
3009   ("mkswap", (RErr, [Device "device"]), 130, [],
3010    [InitEmpty, Always, TestRun (
3011       [["part_disk"; "/dev/sda"; "mbr"];
3012        ["mkswap"; "/dev/sda1"]])],
3013    "create a swap partition",
3014    "\
3015 Create a swap partition on C<device>.");
3016
3017   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3018    [InitEmpty, Always, TestRun (
3019       [["part_disk"; "/dev/sda"; "mbr"];
3020        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3021    "create a swap partition with a label",
3022    "\
3023 Create a swap partition on C<device> with label C<label>.
3024
3025 Note that you cannot attach a swap label to a block device
3026 (eg. C</dev/sda>), just to a partition.  This appears to be
3027 a limitation of the kernel or swap tools.");
3028
3029   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3030    (let uuid = uuidgen () in
3031     [InitEmpty, Always, TestRun (
3032        [["part_disk"; "/dev/sda"; "mbr"];
3033         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3034    "create a swap partition with an explicit UUID",
3035    "\
3036 Create a swap partition on C<device> with UUID C<uuid>.");
3037
3038   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3039    [InitBasicFS, Always, TestOutputStruct (
3040       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3041        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3042        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3043     InitBasicFS, Always, TestOutputStruct (
3044       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3045        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3046    "make block, character or FIFO devices",
3047    "\
3048 This call creates block or character special devices, or
3049 named pipes (FIFOs).
3050
3051 The C<mode> parameter should be the mode, using the standard
3052 constants.  C<devmajor> and C<devminor> are the
3053 device major and minor numbers, only used when creating block
3054 and character special devices.
3055
3056 Note that, just like L<mknod(2)>, the mode must be bitwise
3057 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3058 just creates a regular file).  These constants are
3059 available in the standard Linux header files, or you can use
3060 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3061 which are wrappers around this command which bitwise OR
3062 in the appropriate constant for you.
3063
3064 The mode actually set is affected by the umask.");
3065
3066   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3067    [InitBasicFS, Always, TestOutputStruct (
3068       [["mkfifo"; "0o777"; "/node"];
3069        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3070    "make FIFO (named pipe)",
3071    "\
3072 This call creates a FIFO (named pipe) called C<path> with
3073 mode C<mode>.  It is just a convenient wrapper around
3074 C<guestfs_mknod>.
3075
3076 The mode actually set is affected by the umask.");
3077
3078   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3079    [InitBasicFS, Always, TestOutputStruct (
3080       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3081        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3082    "make block device node",
3083    "\
3084 This call creates a block device node called C<path> with
3085 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3086 It is just a convenient wrapper around C<guestfs_mknod>.
3087
3088 The mode actually set is affected by the umask.");
3089
3090   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3091    [InitBasicFS, Always, TestOutputStruct (
3092       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3093        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3094    "make char device node",
3095    "\
3096 This call creates a char device node called C<path> with
3097 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3098 It is just a convenient wrapper around C<guestfs_mknod>.
3099
3100 The mode actually set is affected by the umask.");
3101
3102   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3103    [InitEmpty, Always, TestOutputInt (
3104       [["umask"; "0o22"]], 0o22)],
3105    "set file mode creation mask (umask)",
3106    "\
3107 This function sets the mask used for creating new files and
3108 device nodes to C<mask & 0777>.
3109
3110 Typical umask values would be C<022> which creates new files
3111 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3112 C<002> which creates new files with permissions like
3113 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3114
3115 The default umask is C<022>.  This is important because it
3116 means that directories and device nodes will be created with
3117 C<0644> or C<0755> mode even if you specify C<0777>.
3118
3119 See also C<guestfs_get_umask>,
3120 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3121
3122 This call returns the previous umask.");
3123
3124   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3125    [],
3126    "read directories entries",
3127    "\
3128 This returns the list of directory entries in directory C<dir>.
3129
3130 All entries in the directory are returned, including C<.> and
3131 C<..>.  The entries are I<not> sorted, but returned in the same
3132 order as the underlying filesystem.
3133
3134 Also this call returns basic file type information about each
3135 file.  The C<ftyp> field will contain one of the following characters:
3136
3137 =over 4
3138
3139 =item 'b'
3140
3141 Block special
3142
3143 =item 'c'
3144
3145 Char special
3146
3147 =item 'd'
3148
3149 Directory
3150
3151 =item 'f'
3152
3153 FIFO (named pipe)
3154
3155 =item 'l'
3156
3157 Symbolic link
3158
3159 =item 'r'
3160
3161 Regular file
3162
3163 =item 's'
3164
3165 Socket
3166
3167 =item 'u'
3168
3169 Unknown file type
3170
3171 =item '?'
3172
3173 The L<readdir(3)> returned a C<d_type> field with an
3174 unexpected value
3175
3176 =back
3177
3178 This function is primarily intended for use by programs.  To
3179 get a simple list of names, use C<guestfs_ls>.  To get a printable
3180 directory for human consumption, use C<guestfs_ll>.");
3181
3182   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3183    [],
3184    "create partitions on a block device",
3185    "\
3186 This is a simplified interface to the C<guestfs_sfdisk>
3187 command, where partition sizes are specified in megabytes
3188 only (rounded to the nearest cylinder) and you don't need
3189 to specify the cyls, heads and sectors parameters which
3190 were rarely if ever used anyway.
3191
3192 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3193 and C<guestfs_part_disk>");
3194
3195   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3196    [],
3197    "determine file type inside a compressed file",
3198    "\
3199 This command runs C<file> after first decompressing C<path>
3200 using C<method>.
3201
3202 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3203
3204 Since 1.0.63, use C<guestfs_file> instead which can now
3205 process compressed files.");
3206
3207   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3208    [],
3209    "list extended attributes of a file or directory",
3210    "\
3211 This call lists the extended attributes of the file or directory
3212 C<path>.
3213
3214 At the system call level, this is a combination of the
3215 L<listxattr(2)> and L<getxattr(2)> calls.
3216
3217 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3218
3219   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3220    [],
3221    "list extended attributes of a file or directory",
3222    "\
3223 This is the same as C<guestfs_getxattrs>, but if C<path>
3224 is a symbolic link, then it returns the extended attributes
3225 of the link itself.");
3226
3227   ("setxattr", (RErr, [String "xattr";
3228                        String "val"; Int "vallen"; (* will be BufferIn *)
3229                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3230    [],
3231    "set extended attribute of a file or directory",
3232    "\
3233 This call sets the extended attribute named C<xattr>
3234 of the file C<path> to the value C<val> (of length C<vallen>).
3235 The value is arbitrary 8 bit data.
3236
3237 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3238
3239   ("lsetxattr", (RErr, [String "xattr";
3240                         String "val"; Int "vallen"; (* will be BufferIn *)
3241                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3242    [],
3243    "set extended attribute of a file or directory",
3244    "\
3245 This is the same as C<guestfs_setxattr>, but if C<path>
3246 is a symbolic link, then it sets an extended attribute
3247 of the link itself.");
3248
3249   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3250    [],
3251    "remove extended attribute of a file or directory",
3252    "\
3253 This call removes the extended attribute named C<xattr>
3254 of the file C<path>.
3255
3256 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3257
3258   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3259    [],
3260    "remove extended attribute of a file or directory",
3261    "\
3262 This is the same as C<guestfs_removexattr>, but if C<path>
3263 is a symbolic link, then it removes an extended attribute
3264 of the link itself.");
3265
3266   ("mountpoints", (RHashtable "mps", []), 147, [],
3267    [],
3268    "show mountpoints",
3269    "\
3270 This call is similar to C<guestfs_mounts>.  That call returns
3271 a list of devices.  This one returns a hash table (map) of
3272 device name to directory where the device is mounted.");
3273
3274   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3275    (* This is a special case: while you would expect a parameter
3276     * of type "Pathname", that doesn't work, because it implies
3277     * NEED_ROOT in the generated calling code in stubs.c, and
3278     * this function cannot use NEED_ROOT.
3279     *)
3280    [],
3281    "create a mountpoint",
3282    "\
3283 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3284 specialized calls that can be used to create extra mountpoints
3285 before mounting the first filesystem.
3286
3287 These calls are I<only> necessary in some very limited circumstances,
3288 mainly the case where you want to mount a mix of unrelated and/or
3289 read-only filesystems together.
3290
3291 For example, live CDs often contain a \"Russian doll\" nest of
3292 filesystems, an ISO outer layer, with a squashfs image inside, with
3293 an ext2/3 image inside that.  You can unpack this as follows
3294 in guestfish:
3295
3296  add-ro Fedora-11-i686-Live.iso
3297  run
3298  mkmountpoint /cd
3299  mkmountpoint /squash
3300  mkmountpoint /ext3
3301  mount /dev/sda /cd
3302  mount-loop /cd/LiveOS/squashfs.img /squash
3303  mount-loop /squash/LiveOS/ext3fs.img /ext3
3304
3305 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3306
3307   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3308    [],
3309    "remove a mountpoint",
3310    "\
3311 This calls removes a mountpoint that was previously created
3312 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3313 for full details.");
3314
3315   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3316    [InitISOFS, Always, TestOutputBuffer (
3317       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3318     (* Test various near large, large and too large files (RHBZ#589039). *)
3319     InitBasicFS, Always, TestLastFail (
3320       [["touch"; "/a"];
3321        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3322        ["read_file"; "/a"]]);
3323     InitBasicFS, Always, TestLastFail (
3324       [["touch"; "/a"];
3325        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3326        ["read_file"; "/a"]]);
3327     InitBasicFS, Always, TestLastFail (
3328       [["touch"; "/a"];
3329        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3330        ["read_file"; "/a"]])],
3331    "read a file",
3332    "\
3333 This calls returns the contents of the file C<path> as a
3334 buffer.
3335
3336 Unlike C<guestfs_cat>, this function can correctly
3337 handle files that contain embedded ASCII NUL characters.
3338 However unlike C<guestfs_download>, this function is limited
3339 in the total size of file that can be handled.");
3340
3341   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3342    [InitISOFS, Always, TestOutputList (
3343       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3344     InitISOFS, Always, TestOutputList (
3345       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3346     (* Test for RHBZ#579608, absolute symbolic links. *)
3347     InitISOFS, Always, TestOutputList (
3348       [["grep"; "nomatch"; "/abssymlink"]], [])],
3349    "return lines matching a pattern",
3350    "\
3351 This calls the external C<grep> program and returns the
3352 matching lines.");
3353
3354   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3355    [InitISOFS, Always, TestOutputList (
3356       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3357    "return lines matching a pattern",
3358    "\
3359 This calls the external C<egrep> program and returns the
3360 matching lines.");
3361
3362   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3363    [InitISOFS, Always, TestOutputList (
3364       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3365    "return lines matching a pattern",
3366    "\
3367 This calls the external C<fgrep> program and returns the
3368 matching lines.");
3369
3370   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3371    [InitISOFS, Always, TestOutputList (
3372       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<grep -i> program and returns the
3376 matching lines.");
3377
3378   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<egrep -i> program and returns the
3384 matching lines.");
3385
3386   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<fgrep -i> program and returns the
3392 matching lines.");
3393
3394   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<zgrep> program and returns the
3400 matching lines.");
3401
3402   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<zegrep> program and returns the
3408 matching lines.");
3409
3410   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3411    [InitISOFS, Always, TestOutputList (
3412       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3413    "return lines matching a pattern",
3414    "\
3415 This calls the external C<zfgrep> program and returns the
3416 matching lines.");
3417
3418   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3419    [InitISOFS, Always, TestOutputList (
3420       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3421    "return lines matching a pattern",
3422    "\
3423 This calls the external C<zgrep -i> program and returns the
3424 matching lines.");
3425
3426   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3427    [InitISOFS, Always, TestOutputList (
3428       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3429    "return lines matching a pattern",
3430    "\
3431 This calls the external C<zegrep -i> program and returns the
3432 matching lines.");
3433
3434   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3435    [InitISOFS, Always, TestOutputList (
3436       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3437    "return lines matching a pattern",
3438    "\
3439 This calls the external C<zfgrep -i> program and returns the
3440 matching lines.");
3441
3442   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3443    [InitISOFS, Always, TestOutput (
3444       [["realpath"; "/../directory"]], "/directory")],
3445    "canonicalized absolute pathname",
3446    "\
3447 Return the canonicalized absolute pathname of C<path>.  The
3448 returned path has no C<.>, C<..> or symbolic link path elements.");
3449
3450   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3451    [InitBasicFS, Always, TestOutputStruct (
3452       [["touch"; "/a"];
3453        ["ln"; "/a"; "/b"];
3454        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3455    "create a hard link",
3456    "\
3457 This command creates a hard link using the C<ln> command.");
3458
3459   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3460    [InitBasicFS, Always, TestOutputStruct (
3461       [["touch"; "/a"];
3462        ["touch"; "/b"];
3463        ["ln_f"; "/a"; "/b"];
3464        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3465    "create a hard link",
3466    "\
3467 This command creates a hard link using the C<ln -f> command.
3468 The C<-f> option removes the link (C<linkname>) if it exists already.");
3469
3470   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3471    [InitBasicFS, Always, TestOutputStruct (
3472       [["touch"; "/a"];
3473        ["ln_s"; "a"; "/b"];
3474        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3475    "create a symbolic link",
3476    "\
3477 This command creates a symbolic link using the C<ln -s> command.");
3478
3479   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3480    [InitBasicFS, Always, TestOutput (
3481       [["mkdir_p"; "/a/b"];
3482        ["touch"; "/a/b/c"];
3483        ["ln_sf"; "../d"; "/a/b/c"];
3484        ["readlink"; "/a/b/c"]], "../d")],
3485    "create a symbolic link",
3486    "\
3487 This command creates a symbolic link using the C<ln -sf> command,
3488 The C<-f> option removes the link (C<linkname>) if it exists already.");
3489
3490   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3491    [] (* XXX tested above *),
3492    "read the target of a symbolic link",
3493    "\
3494 This command reads the target of a symbolic link.");
3495
3496   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3497    [InitBasicFS, Always, TestOutputStruct (
3498       [["fallocate"; "/a"; "1000000"];
3499        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3500    "preallocate a file in the guest filesystem",
3501    "\
3502 This command preallocates a file (containing zero bytes) named
3503 C<path> of size C<len> bytes.  If the file exists already, it
3504 is overwritten.
3505
3506 Do not confuse this with the guestfish-specific
3507 C<alloc> command which allocates a file in the host and
3508 attaches it as a device.");
3509
3510   ("swapon_device", (RErr, [Device "device"]), 170, [],
3511    [InitPartition, Always, TestRun (
3512       [["mkswap"; "/dev/sda1"];
3513        ["swapon_device"; "/dev/sda1"];
3514        ["swapoff_device"; "/dev/sda1"]])],
3515    "enable swap on device",
3516    "\
3517 This command enables the libguestfs appliance to use the
3518 swap device or partition named C<device>.  The increased
3519 memory is made available for all commands, for example
3520 those run using C<guestfs_command> or C<guestfs_sh>.
3521
3522 Note that you should not swap to existing guest swap
3523 partitions unless you know what you are doing.  They may
3524 contain hibernation information, or other information that
3525 the guest doesn't want you to trash.  You also risk leaking
3526 information about the host to the guest this way.  Instead,
3527 attach a new host device to the guest and swap on that.");
3528
3529   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3530    [], (* XXX tested by swapon_device *)
3531    "disable swap on device",
3532    "\
3533 This command disables the libguestfs appliance swap
3534 device or partition named C<device>.
3535 See C<guestfs_swapon_device>.");
3536
3537   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3538    [InitBasicFS, Always, TestRun (
3539       [["fallocate"; "/swap"; "8388608"];
3540        ["mkswap_file"; "/swap"];
3541        ["swapon_file"; "/swap"];
3542        ["swapoff_file"; "/swap"]])],
3543    "enable swap on file",
3544    "\
3545 This command enables swap to a file.
3546 See C<guestfs_swapon_device> for other notes.");
3547
3548   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3549    [], (* XXX tested by swapon_file *)
3550    "disable swap on file",
3551    "\
3552 This command disables the libguestfs appliance swap on file.");
3553
3554   ("swapon_label", (RErr, [String "label"]), 174, [],
3555    [InitEmpty, Always, TestRun (
3556       [["part_disk"; "/dev/sdb"; "mbr"];
3557        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3558        ["swapon_label"; "swapit"];
3559        ["swapoff_label"; "swapit"];
3560        ["zero"; "/dev/sdb"];
3561        ["blockdev_rereadpt"; "/dev/sdb"]])],
3562    "enable swap on labeled swap partition",
3563    "\
3564 This command enables swap to a labeled swap partition.
3565 See C<guestfs_swapon_device> for other notes.");
3566
3567   ("swapoff_label", (RErr, [String "label"]), 175, [],
3568    [], (* XXX tested by swapon_label *)
3569    "disable swap on labeled swap partition",
3570    "\
3571 This command disables the libguestfs appliance swap on
3572 labeled swap partition.");
3573
3574   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3575    (let uuid = uuidgen () in
3576     [InitEmpty, Always, TestRun (
3577        [["mkswap_U"; uuid; "/dev/sdb"];
3578         ["swapon_uuid"; uuid];
3579         ["swapoff_uuid"; uuid]])]),
3580    "enable swap on swap partition by UUID",
3581    "\
3582 This command enables swap to a swap partition with the given UUID.
3583 See C<guestfs_swapon_device> for other notes.");
3584
3585   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3586    [], (* XXX tested by swapon_uuid *)
3587    "disable swap on swap partition by UUID",
3588    "\
3589 This command disables the libguestfs appliance swap partition
3590 with the given UUID.");
3591
3592   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3593    [InitBasicFS, Always, TestRun (
3594       [["fallocate"; "/swap"; "8388608"];
3595        ["mkswap_file"; "/swap"]])],
3596    "create a swap file",
3597    "\
3598 Create a swap file.
3599
3600 This command just writes a swap file signature to an existing
3601 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3602
3603   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3604    [InitISOFS, Always, TestRun (
3605       [["inotify_init"; "0"]])],
3606    "create an inotify handle",
3607    "\
3608 This command creates a new inotify handle.
3609 The inotify subsystem can be used to notify events which happen to
3610 objects in the guest filesystem.
3611
3612 C<maxevents> is the maximum number of events which will be
3613 queued up between calls to C<guestfs_inotify_read> or
3614 C<guestfs_inotify_files>.
3615 If this is passed as C<0>, then the kernel (or previously set)
3616 default is used.  For Linux 2.6.29 the default was 16384 events.
3617 Beyond this limit, the kernel throws away events, but records
3618 the fact that it threw them away by setting a flag
3619 C<IN_Q_OVERFLOW> in the returned structure list (see
3620 C<guestfs_inotify_read>).
3621
3622 Before any events are generated, you have to add some
3623 watches to the internal watch list.  See:
3624 C<guestfs_inotify_add_watch>,
3625 C<guestfs_inotify_rm_watch> and
3626 C<guestfs_inotify_watch_all>.
3627
3628 Queued up events should be read periodically by calling
3629 C<guestfs_inotify_read>
3630 (or C<guestfs_inotify_files> which is just a helpful
3631 wrapper around C<guestfs_inotify_read>).  If you don't
3632 read the events out often enough then you risk the internal
3633 queue overflowing.
3634
3635 The handle should be closed after use by calling
3636 C<guestfs_inotify_close>.  This also removes any
3637 watches automatically.
3638
3639 See also L<inotify(7)> for an overview of the inotify interface
3640 as exposed by the Linux kernel, which is roughly what we expose
3641 via libguestfs.  Note that there is one global inotify handle
3642 per libguestfs instance.");
3643
3644   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3645    [InitBasicFS, Always, TestOutputList (
3646       [["inotify_init"; "0"];
3647        ["inotify_add_watch"; "/"; "1073741823"];
3648        ["touch"; "/a"];
3649        ["touch"; "/b"];
3650        ["inotify_files"]], ["a"; "b"])],
3651    "add an inotify watch",
3652    "\
3653 Watch C<path> for the events listed in C<mask>.
3654
3655 Note that if C<path> is a directory then events within that
3656 directory are watched, but this does I<not> happen recursively
3657 (in subdirectories).
3658
3659 Note for non-C or non-Linux callers: the inotify events are
3660 defined by the Linux kernel ABI and are listed in
3661 C</usr/include/sys/inotify.h>.");
3662
3663   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3664    [],
3665    "remove an inotify watch",
3666    "\
3667 Remove a previously defined inotify watch.
3668 See C<guestfs_inotify_add_watch>.");
3669
3670   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3671    [],
3672    "return list of inotify events",
3673    "\
3674 Return the complete queue of events that have happened
3675 since the previous read call.
3676
3677 If no events have happened, this returns an empty list.
3678
3679 I<Note>: In order to make sure that all events have been
3680 read, you must call this function repeatedly until it
3681 returns an empty list.  The reason is that the call will
3682 read events up to the maximum appliance-to-host message
3683 size and leave remaining events in the queue.");
3684
3685   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3686    [],
3687    "return list of watched files that had events",
3688    "\
3689 This function is a helpful wrapper around C<guestfs_inotify_read>
3690 which just returns a list of pathnames of objects that were
3691 touched.  The returned pathnames are sorted and deduplicated.");
3692
3693   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3694    [],
3695    "close the inotify handle",
3696    "\
3697 This closes the inotify handle which was previously
3698 opened by inotify_init.  It removes all watches, throws
3699 away any pending events, and deallocates all resources.");
3700
3701   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3702    [],
3703    "set SELinux security context",
3704    "\
3705 This sets the SELinux security context of the daemon
3706 to the string C<context>.
3707
3708 See the documentation about SELINUX in L<guestfs(3)>.");
3709
3710   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3711    [],
3712    "get SELinux security context",
3713    "\
3714 This gets the SELinux security context of the daemon.
3715
3716 See the documentation about SELINUX in L<guestfs(3)>,
3717 and C<guestfs_setcon>");
3718
3719   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3720    [InitEmpty, Always, TestOutput (
3721       [["part_disk"; "/dev/sda"; "mbr"];
3722        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3723        ["mount_options"; ""; "/dev/sda1"; "/"];
3724        ["write_file"; "/new"; "new file contents"; "0"];
3725        ["cat"; "/new"]], "new file contents")],
3726    "make a filesystem with block size",
3727    "\
3728 This call is similar to C<guestfs_mkfs>, but it allows you to
3729 control the block size of the resulting filesystem.  Supported
3730 block sizes depend on the filesystem type, but typically they
3731 are C<1024>, C<2048> or C<4096> only.");
3732
3733   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3734    [InitEmpty, Always, TestOutput (
3735       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3736        ["mke2journal"; "4096"; "/dev/sda1"];
3737        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
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",
3742    "\
3743 This creates an ext2 external journal on C<device>.  It is equivalent
3744 to the command:
3745
3746  mke2fs -O journal_dev -b blocksize device");
3747
3748   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3749    [InitEmpty, Always, TestOutput (
3750       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3751        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3752        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3753        ["mount_options"; ""; "/dev/sda2"; "/"];
3754        ["write_file"; "/new"; "new file contents"; "0"];
3755        ["cat"; "/new"]], "new file contents")],
3756    "make ext2/3/4 external journal with label",
3757    "\
3758 This creates an ext2 external journal on C<device> with label C<label>.");
3759
3760   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3761    (let uuid = uuidgen () in
3762     [InitEmpty, Always, TestOutput (
3763        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3764         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3765         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3766         ["mount_options"; ""; "/dev/sda2"; "/"];
3767         ["write_file"; "/new"; "new file contents"; "0"];
3768         ["cat"; "/new"]], "new file contents")]),
3769    "make ext2/3/4 external journal with UUID",
3770    "\
3771 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3772
3773   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3774    [],
3775    "make ext2/3/4 filesystem with external journal",
3776    "\
3777 This creates an ext2/3/4 filesystem on C<device> with
3778 an external journal on C<journal>.  It is equivalent
3779 to the command:
3780
3781  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3782
3783 See also C<guestfs_mke2journal>.");
3784
3785   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3786    [],
3787    "make ext2/3/4 filesystem with external journal",
3788    "\
3789 This creates an ext2/3/4 filesystem on C<device> with
3790 an external journal on the journal labeled C<label>.
3791
3792 See also C<guestfs_mke2journal_L>.");
3793
3794   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3795    [],
3796    "make ext2/3/4 filesystem with external journal",
3797    "\
3798 This creates an ext2/3/4 filesystem on C<device> with
3799 an external journal on the journal with UUID C<uuid>.
3800
3801 See also C<guestfs_mke2journal_U>.");
3802
3803   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3804    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3805    "load a kernel module",
3806    "\
3807 This loads a kernel module in the appliance.
3808
3809 The kernel module must have been whitelisted when libguestfs
3810 was built (see C<appliance/kmod.whitelist.in> in the source).");
3811
3812   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3813    [InitNone, Always, TestOutput (
3814       [["echo_daemon"; "This is a test"]], "This is a test"
3815     )],
3816    "echo arguments back to the client",
3817    "\
3818 This command concatenate the list of C<words> passed with single spaces between
3819 them and returns the resulting string.
3820
3821 You can use this command to test the connection through to the daemon.
3822
3823 See also C<guestfs_ping_daemon>.");
3824
3825   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3826    [], (* There is a regression test for this. *)
3827    "find all files and directories, returning NUL-separated list",
3828    "\
3829 This command lists out all files and directories, recursively,
3830 starting at C<directory>, placing the resulting list in the
3831 external file called C<files>.
3832
3833 This command works the same way as C<guestfs_find> with the
3834 following exceptions:
3835
3836 =over 4
3837
3838 =item *
3839
3840 The resulting list is written to an external file.
3841
3842 =item *
3843
3844 Items (filenames) in the result are separated
3845 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3846
3847 =item *
3848
3849 This command is not limited in the number of names that it
3850 can return.
3851
3852 =item *
3853
3854 The result list is not sorted.
3855
3856 =back");
3857
3858   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3859    [InitISOFS, Always, TestOutput (
3860       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3861     InitISOFS, Always, TestOutput (
3862       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3863     InitISOFS, Always, TestOutput (
3864       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3865     InitISOFS, Always, TestLastFail (
3866       [["case_sensitive_path"; "/Known-1/"]]);
3867     InitBasicFS, Always, TestOutput (
3868       [["mkdir"; "/a"];
3869        ["mkdir"; "/a/bbb"];
3870        ["touch"; "/a/bbb/c"];
3871        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3872     InitBasicFS, Always, TestOutput (
3873       [["mkdir"; "/a"];
3874        ["mkdir"; "/a/bbb"];
3875        ["touch"; "/a/bbb/c"];
3876        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3877     InitBasicFS, Always, TestLastFail (
3878       [["mkdir"; "/a"];
3879        ["mkdir"; "/a/bbb"];
3880        ["touch"; "/a/bbb/c"];
3881        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3882    "return true path on case-insensitive filesystem",
3883    "\
3884 This can be used to resolve case insensitive paths on
3885 a filesystem which is case sensitive.  The use case is
3886 to resolve paths which you have read from Windows configuration
3887 files or the Windows Registry, to the true path.
3888
3889 The command handles a peculiarity of the Linux ntfs-3g
3890 filesystem driver (and probably others), which is that although
3891 the underlying filesystem is case-insensitive, the driver
3892 exports the filesystem to Linux as case-sensitive.
3893
3894 One consequence of this is that special directories such
3895 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3896 (or other things) depending on the precise details of how
3897 they were created.  In Windows itself this would not be
3898 a problem.
3899
3900 Bug or feature?  You decide:
3901 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3902
3903 This function resolves the true case of each element in the
3904 path and returns the case-sensitive path.
3905
3906 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3907 might return C<\"/WINDOWS/system32\"> (the exact return value
3908 would depend on details of how the directories were originally
3909 created under Windows).
3910
3911 I<Note>:
3912 This function does not handle drive names, backslashes etc.
3913
3914 See also C<guestfs_realpath>.");
3915
3916   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3917    [InitBasicFS, Always, TestOutput (
3918       [["vfs_type"; "/dev/sda1"]], "ext2")],
3919    "get the Linux VFS type corresponding to a mounted device",
3920    "\
3921 This command gets the block device type corresponding to
3922 a mounted device called C<device>.
3923
3924 Usually the result is the name of the Linux VFS module that
3925 is used to mount this device (probably determined automatically
3926 if you used the C<guestfs_mount> call).");
3927
3928   ("truncate", (RErr, [Pathname "path"]), 199, [],
3929    [InitBasicFS, Always, TestOutputStruct (
3930       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3931        ["truncate"; "/test"];
3932        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3933    "truncate a file to zero size",
3934    "\
3935 This command truncates C<path> to a zero-length file.  The
3936 file must exist already.");
3937
3938   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3939    [InitBasicFS, Always, TestOutputStruct (
3940       [["touch"; "/test"];
3941        ["truncate_size"; "/test"; "1000"];
3942        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3943    "truncate a file to a particular size",
3944    "\
3945 This command truncates C<path> to size C<size> bytes.  The file
3946 must exist already.  If the file is smaller than C<size> then
3947 the file is extended to the required size with null bytes.");
3948
3949   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3950    [InitBasicFS, Always, TestOutputStruct (
3951       [["touch"; "/test"];
3952        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3953        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3954    "set timestamp of a file with nanosecond precision",
3955    "\
3956 This command sets the timestamps of a file with nanosecond
3957 precision.
3958
3959 C<atsecs, atnsecs> are the last access time (atime) in secs and
3960 nanoseconds from the epoch.
3961
3962 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3963 secs and nanoseconds from the epoch.
3964
3965 If the C<*nsecs> field contains the special value C<-1> then
3966 the corresponding timestamp is set to the current time.  (The
3967 C<*secs> field is ignored in this case).
3968
3969 If the C<*nsecs> field contains the special value C<-2> then
3970 the corresponding timestamp is left unchanged.  (The
3971 C<*secs> field is ignored in this case).");
3972
3973   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3974    [InitBasicFS, Always, TestOutputStruct (
3975       [["mkdir_mode"; "/test"; "0o111"];
3976        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3977    "create a directory with a particular mode",
3978    "\
3979 This command creates a directory, setting the initial permissions
3980 of the directory to C<mode>.
3981
3982 For common Linux filesystems, the actual mode which is set will
3983 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3984 interpret the mode in other ways.
3985
3986 See also C<guestfs_mkdir>, C<guestfs_umask>");
3987
3988   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3989    [], (* XXX *)
3990    "change file owner and group",
3991    "\
3992 Change the file owner to C<owner> and group to C<group>.
3993 This is like C<guestfs_chown> but if C<path> is a symlink then
3994 the link itself is changed, not the target.
3995
3996 Only numeric uid and gid are supported.  If you want to use
3997 names, you will need to locate and parse the password file
3998 yourself (Augeas support makes this relatively easy).");
3999
4000   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4001    [], (* XXX *)
4002    "lstat on multiple files",
4003    "\
4004 This call allows you to perform the C<guestfs_lstat> operation
4005 on multiple files, where all files are in the directory C<path>.
4006 C<names> is the list of files from this directory.
4007
4008 On return you get a list of stat structs, with a one-to-one
4009 correspondence to the C<names> list.  If any name did not exist
4010 or could not be lstat'd, then the C<ino> field of that structure
4011 is set to C<-1>.
4012
4013 This call is intended for programs that want to efficiently
4014 list a directory contents without making many round-trips.
4015 See also C<guestfs_lxattrlist> for a similarly efficient call
4016 for getting extended attributes.  Very long directory listings
4017 might cause the protocol message size to be exceeded, causing
4018 this call to fail.  The caller must split up such requests
4019 into smaller groups of names.");
4020
4021   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4022    [], (* XXX *)
4023    "lgetxattr on multiple files",
4024    "\
4025 This call allows you to get the extended attributes
4026 of multiple files, where all files are in the directory C<path>.
4027 C<names> is the list of files from this directory.
4028
4029 On return you get a flat list of xattr structs which must be
4030 interpreted sequentially.  The first xattr struct always has a zero-length
4031 C<attrname>.  C<attrval> in this struct is zero-length
4032 to indicate there was an error doing C<lgetxattr> for this
4033 file, I<or> is a C string which is a decimal number
4034 (the number of following attributes for this file, which could
4035 be C<\"0\">).  Then after the first xattr struct are the
4036 zero or more attributes for the first named file.
4037 This repeats for the second and subsequent files.
4038
4039 This call is intended for programs that want to efficiently
4040 list a directory contents without making many round-trips.
4041 See also C<guestfs_lstatlist> for a similarly efficient call
4042 for getting standard stats.  Very long directory listings
4043 might cause the protocol message size to be exceeded, causing
4044 this call to fail.  The caller must split up such requests
4045 into smaller groups of names.");
4046
4047   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4048    [], (* XXX *)
4049    "readlink on multiple files",
4050    "\
4051 This call allows you to do a C<readlink> operation
4052 on multiple files, where all files are in the directory C<path>.
4053 C<names> is the list of files from this directory.
4054
4055 On return you get a list of strings, with a one-to-one
4056 correspondence to the C<names> list.  Each string is the
4057 value of the symbol link.
4058
4059 If the C<readlink(2)> operation fails on any name, then
4060 the corresponding result string is the empty string C<\"\">.
4061 However the whole operation is completed even if there
4062 were C<readlink(2)> errors, and so you can call this
4063 function with names where you don't know if they are
4064 symbolic links already (albeit slightly less efficient).
4065
4066 This call is intended for programs that want to efficiently
4067 list a directory contents without making many round-trips.
4068 Very long directory listings might cause the protocol
4069 message size to be exceeded, causing
4070 this call to fail.  The caller must split up such requests
4071 into smaller groups of names.");
4072
4073   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4074    [InitISOFS, Always, TestOutputBuffer (
4075       [["pread"; "/known-4"; "1"; "3"]], "\n");
4076     InitISOFS, Always, TestOutputBuffer (
4077       [["pread"; "/empty"; "0"; "100"]], "")],
4078    "read part of a file",
4079    "\
4080 This command lets you read part of a file.  It reads C<count>
4081 bytes of the file, starting at C<offset>, from file C<path>.
4082
4083 This may read fewer bytes than requested.  For further details
4084 see the L<pread(2)> system call.");
4085
4086   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4087    [InitEmpty, Always, TestRun (
4088       [["part_init"; "/dev/sda"; "gpt"]])],
4089    "create an empty partition table",
4090    "\
4091 This creates an empty partition table on C<device> of one of the
4092 partition types listed below.  Usually C<parttype> should be
4093 either C<msdos> or C<gpt> (for large disks).
4094
4095 Initially there are no partitions.  Following this, you should
4096 call C<guestfs_part_add> for each partition required.
4097
4098 Possible values for C<parttype> are:
4099
4100 =over 4
4101
4102 =item B<efi> | B<gpt>
4103
4104 Intel EFI / GPT partition table.
4105
4106 This is recommended for >= 2 TB partitions that will be accessed
4107 from Linux and Intel-based Mac OS X.  It also has limited backwards
4108 compatibility with the C<mbr> format.
4109
4110 =item B<mbr> | B<msdos>
4111
4112 The standard PC \"Master Boot Record\" (MBR) format used
4113 by MS-DOS and Windows.  This partition type will B<only> work
4114 for device sizes up to 2 TB.  For large disks we recommend
4115 using C<gpt>.
4116
4117 =back
4118
4119 Other partition table types that may work but are not
4120 supported include:
4121
4122 =over 4
4123
4124 =item B<aix>
4125
4126 AIX disk labels.
4127
4128 =item B<amiga> | B<rdb>
4129
4130 Amiga \"Rigid Disk Block\" format.
4131
4132 =item B<bsd>
4133
4134 BSD disk labels.
4135
4136 =item B<dasd>
4137
4138 DASD, used on IBM mainframes.
4139
4140 =item B<dvh>
4141
4142 MIPS/SGI volumes.
4143
4144 =item B<mac>
4145
4146 Old Mac partition format.  Modern Macs use C<gpt>.
4147
4148 =item B<pc98>
4149
4150 NEC PC-98 format, common in Japan apparently.
4151
4152 =item B<sun>
4153
4154 Sun disk labels.
4155
4156 =back");
4157
4158   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4159    [InitEmpty, Always, TestRun (
4160       [["part_init"; "/dev/sda"; "mbr"];
4161        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4162     InitEmpty, Always, TestRun (
4163       [["part_init"; "/dev/sda"; "gpt"];
4164        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4165        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4166     InitEmpty, Always, TestRun (
4167       [["part_init"; "/dev/sda"; "mbr"];
4168        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4169        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4170        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4171        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4172    "add a partition to the device",
4173    "\
4174 This command adds a partition to C<device>.  If there is no partition
4175 table on the device, call C<guestfs_part_init> first.
4176
4177 The C<prlogex> parameter is the type of partition.  Normally you
4178 should pass C<p> or C<primary> here, but MBR partition tables also
4179 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4180 types.
4181
4182 C<startsect> and C<endsect> are the start and end of the partition
4183 in I<sectors>.  C<endsect> may be negative, which means it counts
4184 backwards from the end of the disk (C<-1> is the last sector).
4185
4186 Creating a partition which covers the whole disk is not so easy.
4187 Use C<guestfs_part_disk> to do that.");
4188
4189   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4190    [InitEmpty, Always, TestRun (
4191       [["part_disk"; "/dev/sda"; "mbr"]]);
4192     InitEmpty, Always, TestRun (
4193       [["part_disk"; "/dev/sda"; "gpt"]])],
4194    "partition whole disk with a single primary partition",
4195    "\
4196 This command is simply a combination of C<guestfs_part_init>
4197 followed by C<guestfs_part_add> to create a single primary partition
4198 covering the whole disk.
4199
4200 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4201 but other possible values are described in C<guestfs_part_init>.");
4202
4203   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4204    [InitEmpty, Always, TestRun (
4205       [["part_disk"; "/dev/sda"; "mbr"];
4206        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4207    "make a partition bootable",
4208    "\
4209 This sets the bootable flag on partition numbered C<partnum> on
4210 device C<device>.  Note that partitions are numbered from 1.
4211
4212 The bootable flag is used by some operating systems (notably
4213 Windows) to determine which partition to boot from.  It is by
4214 no means universally recognized.");
4215
4216   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4217    [InitEmpty, Always, TestRun (
4218       [["part_disk"; "/dev/sda"; "gpt"];
4219        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4220    "set partition name",
4221    "\
4222 This sets the partition name on partition numbered C<partnum> on
4223 device C<device>.  Note that partitions are numbered from 1.
4224
4225 The partition name can only be set on certain types of partition
4226 table.  This works on C<gpt> but not on C<mbr> partitions.");
4227
4228   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4229    [], (* XXX Add a regression test for this. *)
4230    "list partitions on a device",
4231    "\
4232 This command parses the partition table on C<device> and
4233 returns the list of partitions found.
4234
4235 The fields in the returned structure are:
4236
4237 =over 4
4238
4239 =item B<part_num>
4240
4241 Partition number, counting from 1.
4242
4243 =item B<part_start>
4244
4245 Start of the partition I<in bytes>.  To get sectors you have to
4246 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4247
4248 =item B<part_end>
4249
4250 End of the partition in bytes.
4251
4252 =item B<part_size>
4253
4254 Size of the partition in bytes.
4255
4256 =back");
4257
4258   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4259    [InitEmpty, Always, TestOutput (
4260       [["part_disk"; "/dev/sda"; "gpt"];
4261        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4262    "get the partition table type",
4263    "\
4264 This command examines the partition table on C<device> and
4265 returns the partition table type (format) being used.
4266
4267 Common return values include: C<msdos> (a DOS/Windows style MBR
4268 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4269 values are possible, although unusual.  See C<guestfs_part_init>
4270 for a full list.");
4271
4272   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4273    [InitBasicFS, Always, TestOutputBuffer (
4274       [["fill"; "0x63"; "10"; "/test"];
4275        ["read_file"; "/test"]], "cccccccccc")],
4276    "fill a file with octets",
4277    "\
4278 This command creates a new file called C<path>.  The initial
4279 content of the file is C<len> octets of C<c>, where C<c>
4280 must be a number in the range C<[0..255]>.
4281
4282 To fill a file with zero bytes (sparsely), it is
4283 much more efficient to use C<guestfs_truncate_size>.
4284 To create a file with a pattern of repeating bytes
4285 use C<guestfs_fill_pattern>.");
4286
4287   ("available", (RErr, [StringList "groups"]), 216, [],
4288    [InitNone, Always, TestRun [["available"; ""]]],
4289    "test availability of some parts of the API",
4290    "\
4291 This command is used to check the availability of some
4292 groups of functionality in the appliance, which not all builds of
4293 the libguestfs appliance will be able to provide.
4294
4295 The libguestfs groups, and the functions that those
4296 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4297
4298 The argument C<groups> is a list of group names, eg:
4299 C<[\"inotify\", \"augeas\"]> would check for the availability of
4300 the Linux inotify functions and Augeas (configuration file
4301 editing) functions.
4302
4303 The command returns no error if I<all> requested groups are available.
4304
4305 It fails with an error if one or more of the requested
4306 groups is unavailable in the appliance.
4307
4308 If an unknown group name is included in the
4309 list of groups then an error is always returned.
4310
4311 I<Notes:>
4312
4313 =over 4
4314
4315 =item *
4316
4317 You must call C<guestfs_launch> before calling this function.
4318
4319 The reason is because we don't know what groups are
4320 supported by the appliance/daemon until it is running and can
4321 be queried.
4322
4323 =item *
4324
4325 If a group of functions is available, this does not necessarily
4326 mean that they will work.  You still have to check for errors
4327 when calling individual API functions even if they are
4328 available.
4329
4330 =item *
4331
4332 It is usually the job of distro packagers to build
4333 complete functionality into the libguestfs appliance.
4334 Upstream libguestfs, if built from source with all
4335 requirements satisfied, will support everything.
4336
4337 =item *
4338
4339 This call was added in version C<1.0.80>.  In previous
4340 versions of libguestfs all you could do would be to speculatively
4341 execute a command to find out if the daemon implemented it.
4342 See also C<guestfs_version>.
4343
4344 =back");
4345
4346   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4347    [InitBasicFS, Always, TestOutputBuffer (
4348       [["write_file"; "/src"; "hello, world"; "0"];
4349        ["dd"; "/src"; "/dest"];
4350        ["read_file"; "/dest"]], "hello, world")],
4351    "copy from source to destination using dd",
4352    "\
4353 This command copies from one source device or file C<src>
4354 to another destination device or file C<dest>.  Normally you
4355 would use this to copy to or from a device or partition, for
4356 example to duplicate a filesystem.
4357
4358 If the destination is a device, it must be as large or larger
4359 than the source file or device, otherwise the copy will fail.
4360 This command cannot do partial copies (see C<guestfs_copy_size>).");
4361
4362   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4363    [InitBasicFS, Always, TestOutputInt (
4364       [["write_file"; "/file"; "hello, world"; "0"];
4365        ["filesize"; "/file"]], 12)],
4366    "return the size of the file in bytes",
4367    "\
4368 This command returns the size of C<file> in bytes.
4369
4370 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4371 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4372 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4373
4374   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4375    [InitBasicFSonLVM, Always, TestOutputList (
4376       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4377        ["lvs"]], ["/dev/VG/LV2"])],
4378    "rename an LVM logical volume",
4379    "\
4380 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4381
4382   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4383    [InitBasicFSonLVM, Always, TestOutputList (
4384       [["umount"; "/"];
4385        ["vg_activate"; "false"; "VG"];
4386        ["vgrename"; "VG"; "VG2"];
4387        ["vg_activate"; "true"; "VG2"];
4388        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4389        ["vgs"]], ["VG2"])],
4390    "rename an LVM volume group",
4391    "\
4392 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4393
4394   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4395    [InitISOFS, Always, TestOutputBuffer (
4396       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4397    "list the contents of a single file in an initrd",
4398    "\
4399 This command unpacks the file C<filename> from the initrd file
4400 called C<initrdpath>.  The filename must be given I<without> the
4401 initial C</> character.
4402
4403 For example, in guestfish you could use the following command
4404 to examine the boot script (usually called C</init>)
4405 contained in a Linux initrd or initramfs image:
4406
4407  initrd-cat /boot/initrd-<version>.img init
4408
4409 See also C<guestfs_initrd_list>.");
4410
4411   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4412    [],
4413    "get the UUID of a physical volume",
4414    "\
4415 This command returns the UUID of the LVM PV C<device>.");
4416
4417   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4418    [],
4419    "get the UUID of a volume group",
4420    "\
4421 This command returns the UUID of the LVM VG named C<vgname>.");
4422
4423   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4424    [],
4425    "get the UUID of a logical volume",
4426    "\
4427 This command returns the UUID of the LVM LV C<device>.");
4428
4429   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4430    [],
4431    "get the PV UUIDs containing the volume group",
4432    "\
4433 Given a VG called C<vgname>, this returns the UUIDs of all
4434 the physical volumes that this volume group resides on.
4435
4436 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4437 calls to associate physical volumes and volume groups.
4438
4439 See also C<guestfs_vglvuuids>.");
4440
4441   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4442    [],
4443    "get the LV UUIDs of all LVs in the volume group",
4444    "\
4445 Given a VG called C<vgname>, this returns the UUIDs of all
4446 the logical volumes created in this volume group.
4447
4448 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4449 calls to associate logical volumes and volume groups.
4450
4451 See also C<guestfs_vgpvuuids>.");
4452
4453   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4454    [InitBasicFS, Always, TestOutputBuffer (
4455       [["write_file"; "/src"; "hello, world"; "0"];
4456        ["copy_size"; "/src"; "/dest"; "5"];
4457        ["read_file"; "/dest"]], "hello")],
4458    "copy size bytes from source to destination using dd",
4459    "\
4460 This command copies exactly C<size> bytes from one source device
4461 or file C<src> to another destination device or file C<dest>.
4462
4463 Note this will fail if the source is too short or if the destination
4464 is not large enough.");
4465
4466   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4467    [InitBasicFSonLVM, Always, TestRun (
4468       [["zero_device"; "/dev/VG/LV"]])],
4469    "write zeroes to an entire device",
4470    "\
4471 This command writes zeroes over the entire C<device>.  Compare
4472 with C<guestfs_zero> which just zeroes the first few blocks of
4473 a device.");
4474
4475   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4476    [InitBasicFS, Always, TestOutput (
4477       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4478        ["cat"; "/hello"]], "hello\n")],
4479    "unpack compressed tarball to directory",
4480    "\
4481 This command uploads and unpacks local file C<tarball> (an
4482 I<xz compressed> tar file) into C<directory>.");
4483
4484   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4485    [],
4486    "pack directory into compressed tarball",
4487    "\
4488 This command packs the contents of C<directory> and downloads
4489 it to local file C<tarball> (as an xz compressed tar archive).");
4490
4491   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4492    [],
4493    "resize an NTFS filesystem",
4494    "\
4495 This command resizes an NTFS filesystem, expanding or
4496 shrinking it to the size of the underlying device.
4497 See also L<ntfsresize(8)>.");
4498
4499   ("vgscan", (RErr, []), 232, [],
4500    [InitEmpty, Always, TestRun (
4501       [["vgscan"]])],
4502    "rescan for LVM physical volumes, volume groups and logical volumes",
4503    "\
4504 This rescans all block devices and rebuilds the list of LVM
4505 physical volumes, volume groups and logical volumes.");
4506
4507   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4508    [InitEmpty, Always, TestRun (
4509       [["part_init"; "/dev/sda"; "mbr"];
4510        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4511        ["part_del"; "/dev/sda"; "1"]])],
4512    "delete a partition",
4513    "\
4514 This command deletes the partition numbered C<partnum> on C<device>.
4515
4516 Note that in the case of MBR partitioning, deleting an
4517 extended partition also deletes any logical partitions
4518 it contains.");
4519
4520   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4521    [InitEmpty, Always, TestOutputTrue (
4522       [["part_init"; "/dev/sda"; "mbr"];
4523        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4524        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4525        ["part_get_bootable"; "/dev/sda"; "1"]])],
4526    "return true if a partition is bootable",
4527    "\
4528 This command returns true if the partition C<partnum> on
4529 C<device> has the bootable flag set.
4530
4531 See also C<guestfs_part_set_bootable>.");
4532
4533   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4534    [InitEmpty, Always, TestOutputInt (
4535       [["part_init"; "/dev/sda"; "mbr"];
4536        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4537        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4538        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4539    "get the MBR type byte (ID byte) from a partition",
4540    "\
4541 Returns the MBR type byte (also known as the ID byte) from
4542 the numbered partition C<partnum>.
4543
4544 Note that only MBR (old DOS-style) partitions have type bytes.
4545 You will get undefined results for other partition table
4546 types (see C<guestfs_part_get_parttype>).");
4547
4548   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4549    [], (* tested by part_get_mbr_id *)
4550    "set the MBR type byte (ID byte) of a partition",
4551    "\
4552 Sets the MBR type byte (also known as the ID byte) of
4553 the numbered partition C<partnum> to C<idbyte>.  Note
4554 that the type bytes quoted in most documentation are
4555 in fact hexadecimal numbers, but usually documented
4556 without any leading \"0x\" which might be confusing.
4557
4558 Note that only MBR (old DOS-style) partitions have type bytes.
4559 You will get undefined results for other partition table
4560 types (see C<guestfs_part_get_parttype>).");
4561
4562   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4563    [InitISOFS, Always, TestOutput (
4564       [["checksum_device"; "md5"; "/dev/sdd"]],
4565       (Digest.to_hex (Digest.file "images/test.iso")))],
4566    "compute MD5, SHAx or CRC checksum of the contents of a device",
4567    "\
4568 This call computes the MD5, SHAx or CRC checksum of the
4569 contents of the device named C<device>.  For the types of
4570 checksums supported see the C<guestfs_checksum> command.");
4571
4572   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4573    [InitNone, Always, TestRun (
4574       [["part_disk"; "/dev/sda"; "mbr"];
4575        ["pvcreate"; "/dev/sda1"];
4576        ["vgcreate"; "VG"; "/dev/sda1"];
4577        ["lvcreate"; "LV"; "VG"; "10"];
4578        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4579    "expand an LV to fill free space",
4580    "\
4581 This expands an existing logical volume C<lv> so that it fills
4582 C<pc>% of the remaining free space in the volume group.  Commonly
4583 you would call this with pc = 100 which expands the logical volume
4584 as much as possible, using all remaining free space in the volume
4585 group.");
4586
4587   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4588    [], (* XXX Augeas code needs tests. *)
4589    "clear Augeas path",
4590    "\
4591 Set the value associated with C<path> to C<NULL>.  This
4592 is the same as the L<augtool(1)> C<clear> command.");
4593
4594   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4595    [InitEmpty, Always, TestOutputInt (
4596       [["get_umask"]], 0o22)],
4597    "get the current umask",
4598    "\
4599 Return the current umask.  By default the umask is C<022>
4600 unless it has been set by calling C<guestfs_umask>.");
4601
4602   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4603    [],
4604    "upload a file to the appliance (internal use only)",
4605    "\
4606 The C<guestfs_debug_upload> command uploads a file to
4607 the libguestfs appliance.
4608
4609 There is no comprehensive help for this command.  You have
4610 to look at the file C<daemon/debug.c> in the libguestfs source
4611 to find out what it is for.");
4612
4613   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4614    [InitBasicFS, Always, TestOutput (
4615       [["base64_in"; "../images/hello.b64"; "/hello"];
4616        ["cat"; "/hello"]], "hello\n")],
4617    "upload base64-encoded data to file",
4618    "\
4619 This command uploads base64-encoded data from C<base64file>
4620 to C<filename>.");
4621
4622   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4623    [],
4624    "download file and encode as base64",
4625    "\
4626 This command downloads the contents of C<filename>, writing
4627 it out to local file C<base64file> encoded as base64.");
4628
4629   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4630    [],
4631    "compute MD5, SHAx or CRC checksum of files in a directory",
4632    "\
4633 This command computes the checksums of all regular files in
4634 C<directory> and then emits a list of those checksums to
4635 the local output file C<sumsfile>.
4636
4637 This can be used for verifying the integrity of a virtual
4638 machine.  However to be properly secure you should pay
4639 attention to the output of the checksum command (it uses
4640 the ones from GNU coreutils).  In particular when the
4641 filename is not printable, coreutils uses a special
4642 backslash syntax.  For more information, see the GNU
4643 coreutils info file.");
4644
4645   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4646    [InitBasicFS, Always, TestOutputBuffer (
4647       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4648        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4649    "fill a file with a repeating pattern of bytes",
4650    "\
4651 This function is like C<guestfs_fill> except that it creates
4652 a new file of length C<len> containing the repeating pattern
4653 of bytes in C<pattern>.  The pattern is truncated if necessary
4654 to ensure the length of the file is exactly C<len> bytes.");
4655
4656 ]
4657
4658 let all_functions = non_daemon_functions @ daemon_functions
4659
4660 (* In some places we want the functions to be displayed sorted
4661  * alphabetically, so this is useful:
4662  *)
4663 let all_functions_sorted =
4664   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4665                compare n1 n2) all_functions
4666
4667 (* This is used to generate the src/MAX_PROC_NR file which
4668  * contains the maximum procedure number, a surrogate for the
4669  * ABI version number.  See src/Makefile.am for the details.
4670  *)
4671 let max_proc_nr =
4672   let proc_nrs = List.map (
4673     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4674   ) daemon_functions in
4675   List.fold_left max 0 proc_nrs
4676
4677 (* Field types for structures. *)
4678 type field =
4679   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4680   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4681   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4682   | FUInt32
4683   | FInt32
4684   | FUInt64
4685   | FInt64
4686   | FBytes                      (* Any int measure that counts bytes. *)
4687   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4688   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4689
4690 (* Because we generate extra parsing code for LVM command line tools,
4691  * we have to pull out the LVM columns separately here.
4692  *)
4693 let lvm_pv_cols = [
4694   "pv_name", FString;
4695   "pv_uuid", FUUID;
4696   "pv_fmt", FString;
4697   "pv_size", FBytes;
4698   "dev_size", FBytes;
4699   "pv_free", FBytes;
4700   "pv_used", FBytes;
4701   "pv_attr", FString (* XXX *);
4702   "pv_pe_count", FInt64;
4703   "pv_pe_alloc_count", FInt64;
4704   "pv_tags", FString;
4705   "pe_start", FBytes;
4706   "pv_mda_count", FInt64;
4707   "pv_mda_free", FBytes;
4708   (* Not in Fedora 10:
4709      "pv_mda_size", FBytes;
4710   *)
4711 ]
4712 let lvm_vg_cols = [
4713   "vg_name", FString;
4714   "vg_uuid", FUUID;
4715   "vg_fmt", FString;
4716   "vg_attr", FString (* XXX *);
4717   "vg_size", FBytes;
4718   "vg_free", FBytes;
4719   "vg_sysid", FString;
4720   "vg_extent_size", FBytes;
4721   "vg_extent_count", FInt64;
4722   "vg_free_count", FInt64;
4723   "max_lv", FInt64;
4724   "max_pv", FInt64;
4725   "pv_count", FInt64;
4726   "lv_count", FInt64;
4727   "snap_count", FInt64;
4728   "vg_seqno", FInt64;
4729   "vg_tags", FString;
4730   "vg_mda_count", FInt64;
4731   "vg_mda_free", FBytes;
4732   (* Not in Fedora 10:
4733      "vg_mda_size", FBytes;
4734   *)
4735 ]
4736 let lvm_lv_cols = [
4737   "lv_name", FString;
4738   "lv_uuid", FUUID;
4739   "lv_attr", FString (* XXX *);
4740   "lv_major", FInt64;
4741   "lv_minor", FInt64;
4742   "lv_kernel_major", FInt64;
4743   "lv_kernel_minor", FInt64;
4744   "lv_size", FBytes;
4745   "seg_count", FInt64;
4746   "origin", FString;
4747   "snap_percent", FOptPercent;
4748   "copy_percent", FOptPercent;
4749   "move_pv", FString;
4750   "lv_tags", FString;
4751   "mirror_log", FString;
4752   "modules", FString;
4753 ]
4754
4755 (* Names and fields in all structures (in RStruct and RStructList)
4756  * that we support.
4757  *)
4758 let structs = [
4759   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4760    * not use this struct in any new code.
4761    *)
4762   "int_bool", [
4763     "i", FInt32;                (* for historical compatibility *)
4764     "b", FInt32;                (* for historical compatibility *)
4765   ];
4766
4767   (* LVM PVs, VGs, LVs. *)
4768   "lvm_pv", lvm_pv_cols;
4769   "lvm_vg", lvm_vg_cols;
4770   "lvm_lv", lvm_lv_cols;
4771
4772   (* Column names and types from stat structures.
4773    * NB. Can't use things like 'st_atime' because glibc header files
4774    * define some of these as macros.  Ugh.
4775    *)
4776   "stat", [
4777     "dev", FInt64;
4778     "ino", FInt64;
4779     "mode", FInt64;
4780     "nlink", FInt64;
4781     "uid", FInt64;
4782     "gid", FInt64;
4783     "rdev", FInt64;
4784     "size", FInt64;
4785     "blksize", FInt64;
4786     "blocks", FInt64;
4787     "atime", FInt64;
4788     "mtime", FInt64;
4789     "ctime", FInt64;
4790   ];
4791   "statvfs", [
4792     "bsize", FInt64;
4793     "frsize", FInt64;
4794     "blocks", FInt64;
4795     "bfree", FInt64;
4796     "bavail", FInt64;
4797     "files", FInt64;
4798     "ffree", FInt64;
4799     "favail", FInt64;
4800     "fsid", FInt64;
4801     "flag", FInt64;
4802     "namemax", FInt64;
4803   ];
4804
4805   (* Column names in dirent structure. *)
4806   "dirent", [
4807     "ino", FInt64;
4808     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4809     "ftyp", FChar;
4810     "name", FString;
4811   ];
4812
4813   (* Version numbers. *)
4814   "version", [
4815     "major", FInt64;
4816     "minor", FInt64;
4817     "release", FInt64;
4818     "extra", FString;
4819   ];
4820
4821   (* Extended attribute. *)
4822   "xattr", [
4823     "attrname", FString;
4824     "attrval", FBuffer;
4825   ];
4826
4827   (* Inotify events. *)
4828   "inotify_event", [
4829     "in_wd", FInt64;
4830     "in_mask", FUInt32;
4831     "in_cookie", FUInt32;
4832     "in_name", FString;
4833   ];
4834
4835   (* Partition table entry. *)
4836   "partition", [
4837     "part_num", FInt32;
4838     "part_start", FBytes;
4839     "part_end", FBytes;
4840     "part_size", FBytes;
4841   ];
4842 ] (* end of structs *)
4843
4844 (* Ugh, Java has to be different ..
4845  * These names are also used by the Haskell bindings.
4846  *)
4847 let java_structs = [
4848   "int_bool", "IntBool";
4849   "lvm_pv", "PV";
4850   "lvm_vg", "VG";
4851   "lvm_lv", "LV";
4852   "stat", "Stat";
4853   "statvfs", "StatVFS";
4854   "dirent", "Dirent";
4855   "version", "Version";
4856   "xattr", "XAttr";
4857   "inotify_event", "INotifyEvent";
4858   "partition", "Partition";
4859 ]
4860
4861 (* What structs are actually returned. *)
4862 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4863
4864 (* Returns a list of RStruct/RStructList structs that are returned
4865  * by any function.  Each element of returned list is a pair:
4866  *
4867  * (structname, RStructOnly)
4868  *    == there exists function which returns RStruct (_, structname)
4869  * (structname, RStructListOnly)
4870  *    == there exists function which returns RStructList (_, structname)
4871  * (structname, RStructAndList)
4872  *    == there are functions returning both RStruct (_, structname)
4873  *                                      and RStructList (_, structname)
4874  *)
4875 let rstructs_used_by functions =
4876   (* ||| is a "logical OR" for rstructs_used_t *)
4877   let (|||) a b =
4878     match a, b with
4879     | RStructAndList, _
4880     | _, RStructAndList -> RStructAndList
4881     | RStructOnly, RStructListOnly
4882     | RStructListOnly, RStructOnly -> RStructAndList
4883     | RStructOnly, RStructOnly -> RStructOnly
4884     | RStructListOnly, RStructListOnly -> RStructListOnly
4885   in
4886
4887   let h = Hashtbl.create 13 in
4888
4889   (* if elem->oldv exists, update entry using ||| operator,
4890    * else just add elem->newv to the hash
4891    *)
4892   let update elem newv =
4893     try  let oldv = Hashtbl.find h elem in
4894          Hashtbl.replace h elem (newv ||| oldv)
4895     with Not_found -> Hashtbl.add h elem newv
4896   in
4897
4898   List.iter (
4899     fun (_, style, _, _, _, _, _) ->
4900       match fst style with
4901       | RStruct (_, structname) -> update structname RStructOnly
4902       | RStructList (_, structname) -> update structname RStructListOnly
4903       | _ -> ()
4904   ) functions;
4905
4906   (* return key->values as a list of (key,value) *)
4907   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4908
4909 (* Used for testing language bindings. *)
4910 type callt =
4911   | CallString of string
4912   | CallOptString of string option
4913   | CallStringList of string list
4914   | CallInt of int
4915   | CallInt64 of int64
4916   | CallBool of bool
4917   | CallBuffer of string
4918
4919 (* Used to memoize the result of pod2text. *)
4920 let pod2text_memo_filename = "src/.pod2text.data"
4921 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4922   try
4923     let chan = open_in pod2text_memo_filename in
4924     let v = input_value chan in
4925     close_in chan;
4926     v
4927   with
4928     _ -> Hashtbl.create 13
4929 let pod2text_memo_updated () =
4930   let chan = open_out pod2text_memo_filename in
4931   output_value chan pod2text_memo;
4932   close_out chan
4933
4934 (* Useful functions.
4935  * Note we don't want to use any external OCaml libraries which
4936  * makes this a bit harder than it should be.
4937  *)
4938 module StringMap = Map.Make (String)
4939
4940 let failwithf fs = ksprintf failwith fs
4941
4942 let unique = let i = ref 0 in fun () -> incr i; !i
4943
4944 let replace_char s c1 c2 =
4945   let s2 = String.copy s in
4946   let r = ref false in
4947   for i = 0 to String.length s2 - 1 do
4948     if String.unsafe_get s2 i = c1 then (
4949       String.unsafe_set s2 i c2;
4950       r := true
4951     )
4952   done;
4953   if not !r then s else s2
4954
4955 let isspace c =
4956   c = ' '
4957   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4958
4959 let triml ?(test = isspace) str =
4960   let i = ref 0 in
4961   let n = ref (String.length str) in
4962   while !n > 0 && test str.[!i]; do
4963     decr n;
4964     incr i
4965   done;
4966   if !i = 0 then str
4967   else String.sub str !i !n
4968
4969 let trimr ?(test = isspace) str =
4970   let n = ref (String.length str) in
4971   while !n > 0 && test str.[!n-1]; do
4972     decr n
4973   done;
4974   if !n = String.length str then str
4975   else String.sub str 0 !n
4976
4977 let trim ?(test = isspace) str =
4978   trimr ~test (triml ~test str)
4979
4980 let rec find s sub =
4981   let len = String.length s in
4982   let sublen = String.length sub in
4983   let rec loop i =
4984     if i <= len-sublen then (
4985       let rec loop2 j =
4986         if j < sublen then (
4987           if s.[i+j] = sub.[j] then loop2 (j+1)
4988           else -1
4989         ) else
4990           i (* found *)
4991       in
4992       let r = loop2 0 in
4993       if r = -1 then loop (i+1) else r
4994     ) else
4995       -1 (* not found *)
4996   in
4997   loop 0
4998
4999 let rec replace_str s s1 s2 =
5000   let len = String.length s in
5001   let sublen = String.length s1 in
5002   let i = find s s1 in
5003   if i = -1 then s
5004   else (
5005     let s' = String.sub s 0 i in
5006     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5007     s' ^ s2 ^ replace_str s'' s1 s2
5008   )
5009
5010 let rec string_split sep str =
5011   let len = String.length str in
5012   let seplen = String.length sep in
5013   let i = find str sep in
5014   if i = -1 then [str]
5015   else (
5016     let s' = String.sub str 0 i in
5017     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5018     s' :: string_split sep s''
5019   )
5020
5021 let files_equal n1 n2 =
5022   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5023   match Sys.command cmd with
5024   | 0 -> true
5025   | 1 -> false
5026   | i -> failwithf "%s: failed with error code %d" cmd i
5027
5028 let rec filter_map f = function
5029   | [] -> []
5030   | x :: xs ->
5031       match f x with
5032       | Some y -> y :: filter_map f xs
5033       | None -> filter_map f xs
5034
5035 let rec find_map f = function
5036   | [] -> raise Not_found
5037   | x :: xs ->
5038       match f x with
5039       | Some y -> y
5040       | None -> find_map f xs
5041
5042 let iteri f xs =
5043   let rec loop i = function
5044     | [] -> ()
5045     | x :: xs -> f i x; loop (i+1) xs
5046   in
5047   loop 0 xs
5048
5049 let mapi f xs =
5050   let rec loop i = function
5051     | [] -> []
5052     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5053   in
5054   loop 0 xs
5055
5056 let count_chars c str =
5057   let count = ref 0 in
5058   for i = 0 to String.length str - 1 do
5059     if c = String.unsafe_get str i then incr count
5060   done;
5061   !count
5062
5063 let explode str =
5064   let r = ref [] in
5065   for i = 0 to String.length str - 1 do
5066     let c = String.unsafe_get str i in
5067     r := c :: !r;
5068   done;
5069   List.rev !r
5070
5071 let map_chars f str =
5072   List.map f (explode str)
5073
5074 let name_of_argt = function
5075   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5076   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5077   | FileIn n | FileOut n | BufferIn n -> n
5078
5079 let java_name_of_struct typ =
5080   try List.assoc typ java_structs
5081   with Not_found ->
5082     failwithf
5083       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5084
5085 let cols_of_struct typ =
5086   try List.assoc typ structs
5087   with Not_found ->
5088     failwithf "cols_of_struct: unknown struct %s" typ
5089
5090 let seq_of_test = function
5091   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5092   | TestOutputListOfDevices (s, _)
5093   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5094   | TestOutputTrue s | TestOutputFalse s
5095   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5096   | TestOutputStruct (s, _)
5097   | TestLastFail s -> s
5098
5099 (* Handling for function flags. *)
5100 let protocol_limit_warning =
5101   "Because of the message protocol, there is a transfer limit
5102 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5103
5104 let danger_will_robinson =
5105   "B<This command is dangerous.  Without careful use you
5106 can easily destroy all your data>."
5107
5108 let deprecation_notice flags =
5109   try
5110     let alt =
5111       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5112     let txt =
5113       sprintf "This function is deprecated.
5114 In new code, use the C<%s> call instead.
5115
5116 Deprecated functions will not be removed from the API, but the
5117 fact that they are deprecated indicates that there are problems
5118 with correct use of these functions." alt in
5119     Some txt
5120   with
5121     Not_found -> None
5122
5123 (* Create list of optional groups. *)
5124 let optgroups =
5125   let h = Hashtbl.create 13 in
5126   List.iter (
5127     fun (name, _, _, flags, _, _, _) ->
5128       List.iter (
5129         function
5130         | Optional group ->
5131             let names = try Hashtbl.find h group with Not_found -> [] in
5132             Hashtbl.replace h group (name :: names)
5133         | _ -> ()
5134       ) flags
5135   ) daemon_functions;
5136   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5137   let groups =
5138     List.map (
5139       fun group -> group, List.sort compare (Hashtbl.find h group)
5140     ) groups in
5141   List.sort (fun x y -> compare (fst x) (fst y)) groups
5142
5143 (* Check function names etc. for consistency. *)
5144 let check_functions () =
5145   let contains_uppercase str =
5146     let len = String.length str in
5147     let rec loop i =
5148       if i >= len then false
5149       else (
5150         let c = str.[i] in
5151         if c >= 'A' && c <= 'Z' then true
5152         else loop (i+1)
5153       )
5154     in
5155     loop 0
5156   in
5157
5158   (* Check function names. *)
5159   List.iter (
5160     fun (name, _, _, _, _, _, _) ->
5161       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5162         failwithf "function name %s does not need 'guestfs' prefix" name;
5163       if name = "" then
5164         failwithf "function name is empty";
5165       if name.[0] < 'a' || name.[0] > 'z' then
5166         failwithf "function name %s must start with lowercase a-z" name;
5167       if String.contains name '-' then
5168         failwithf "function name %s should not contain '-', use '_' instead."
5169           name
5170   ) all_functions;
5171
5172   (* Check function parameter/return names. *)
5173   List.iter (
5174     fun (name, style, _, _, _, _, _) ->
5175       let check_arg_ret_name n =
5176         if contains_uppercase n then
5177           failwithf "%s param/ret %s should not contain uppercase chars"
5178             name n;
5179         if String.contains n '-' || String.contains n '_' then
5180           failwithf "%s param/ret %s should not contain '-' or '_'"
5181             name n;
5182         if n = "value" then
5183           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;
5184         if n = "int" || n = "char" || n = "short" || n = "long" then
5185           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5186         if n = "i" || n = "n" then
5187           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5188         if n = "argv" || n = "args" then
5189           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5190
5191         (* List Haskell, OCaml and C keywords here.
5192          * http://www.haskell.org/haskellwiki/Keywords
5193          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5194          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5195          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5196          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5197          * Omitting _-containing words, since they're handled above.
5198          * Omitting the OCaml reserved word, "val", is ok,
5199          * and saves us from renaming several parameters.
5200          *)
5201         let reserved = [
5202           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5203           "char"; "class"; "const"; "constraint"; "continue"; "data";
5204           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5205           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5206           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5207           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5208           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5209           "interface";
5210           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5211           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5212           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5213           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5214           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5215           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5216           "volatile"; "when"; "where"; "while";
5217           ] in
5218         if List.mem n reserved then
5219           failwithf "%s has param/ret using reserved word %s" name n;
5220       in
5221
5222       (match fst style with
5223        | RErr -> ()
5224        | RInt n | RInt64 n | RBool n
5225        | RConstString n | RConstOptString n | RString n
5226        | RStringList n | RStruct (n, _) | RStructList (n, _)
5227        | RHashtable n | RBufferOut n ->
5228            check_arg_ret_name n
5229       );
5230       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5231   ) all_functions;
5232
5233   (* Check short descriptions. *)
5234   List.iter (
5235     fun (name, _, _, _, _, shortdesc, _) ->
5236       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5237         failwithf "short description of %s should begin with lowercase." name;
5238       let c = shortdesc.[String.length shortdesc-1] in
5239       if c = '\n' || c = '.' then
5240         failwithf "short description of %s should not end with . or \\n." name
5241   ) all_functions;
5242
5243   (* Check long descriptions. *)
5244   List.iter (
5245     fun (name, _, _, _, _, _, longdesc) ->
5246       if longdesc.[String.length longdesc-1] = '\n' then
5247         failwithf "long description of %s should not end with \\n." name
5248   ) all_functions;
5249
5250   (* Check proc_nrs. *)
5251   List.iter (
5252     fun (name, _, proc_nr, _, _, _, _) ->
5253       if proc_nr <= 0 then
5254         failwithf "daemon function %s should have proc_nr > 0" name
5255   ) daemon_functions;
5256
5257   List.iter (
5258     fun (name, _, proc_nr, _, _, _, _) ->
5259       if proc_nr <> -1 then
5260         failwithf "non-daemon function %s should have proc_nr -1" name
5261   ) non_daemon_functions;
5262
5263   let proc_nrs =
5264     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5265       daemon_functions in
5266   let proc_nrs =
5267     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5268   let rec loop = function
5269     | [] -> ()
5270     | [_] -> ()
5271     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5272         loop rest
5273     | (name1,nr1) :: (name2,nr2) :: _ ->
5274         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5275           name1 name2 nr1 nr2
5276   in
5277   loop proc_nrs;
5278
5279   (* Check tests. *)
5280   List.iter (
5281     function
5282       (* Ignore functions that have no tests.  We generate a
5283        * warning when the user does 'make check' instead.
5284        *)
5285     | name, _, _, _, [], _, _ -> ()
5286     | name, _, _, _, tests, _, _ ->
5287         let funcs =
5288           List.map (
5289             fun (_, _, test) ->
5290               match seq_of_test test with
5291               | [] ->
5292                   failwithf "%s has a test containing an empty sequence" name
5293               | cmds -> List.map List.hd cmds
5294           ) tests in
5295         let funcs = List.flatten funcs in
5296
5297         let tested = List.mem name funcs in
5298
5299         if not tested then
5300           failwithf "function %s has tests but does not test itself" name
5301   ) all_functions
5302
5303 (* 'pr' prints to the current output file. *)
5304 let chan = ref Pervasives.stdout
5305 let lines = ref 0
5306 let pr fs =
5307   ksprintf
5308     (fun str ->
5309        let i = count_chars '\n' str in
5310        lines := !lines + i;
5311        output_string !chan str
5312     ) fs
5313
5314 let copyright_years =
5315   let this_year = 1900 + (localtime (time ())).tm_year in
5316   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5317
5318 (* Generate a header block in a number of standard styles. *)
5319 type comment_style =
5320     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5321 type license = GPLv2plus | LGPLv2plus
5322
5323 let generate_header ?(extra_inputs = []) comment license =
5324   let inputs = "src/generator.ml" :: extra_inputs in
5325   let c = match comment with
5326     | CStyle ->         pr "/* "; " *"
5327     | CPlusPlusStyle -> pr "// "; "//"
5328     | HashStyle ->      pr "# ";  "#"
5329     | OCamlStyle ->     pr "(* "; " *"
5330     | HaskellStyle ->   pr "{- "; "  " in
5331   pr "libguestfs generated file\n";
5332   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5333   List.iter (pr "%s   %s\n" c) inputs;
5334   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5335   pr "%s\n" c;
5336   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5337   pr "%s\n" c;
5338   (match license with
5339    | GPLv2plus ->
5340        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5341        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5342        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5343        pr "%s (at your option) any later version.\n" c;
5344        pr "%s\n" c;
5345        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5346        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5347        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5348        pr "%s GNU General Public License for more details.\n" c;
5349        pr "%s\n" c;
5350        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5351        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5352        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5353
5354    | LGPLv2plus ->
5355        pr "%s This library is free software; you can redistribute it and/or\n" c;
5356        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5357        pr "%s License as published by the Free Software Foundation; either\n" c;
5358        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5359        pr "%s\n" c;
5360        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5361        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5362        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5363        pr "%s Lesser General Public License for more details.\n" c;
5364        pr "%s\n" c;
5365        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5366        pr "%s License along with this library; if not, write to the Free Software\n" c;
5367        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5368   );
5369   (match comment with
5370    | CStyle -> pr " */\n"
5371    | CPlusPlusStyle
5372    | HashStyle -> ()
5373    | OCamlStyle -> pr " *)\n"
5374    | HaskellStyle -> pr "-}\n"
5375   );
5376   pr "\n"
5377
5378 (* Start of main code generation functions below this line. *)
5379
5380 (* Generate the pod documentation for the C API. *)
5381 let rec generate_actions_pod () =
5382   List.iter (
5383     fun (shortname, style, _, flags, _, _, longdesc) ->
5384       if not (List.mem NotInDocs flags) then (
5385         let name = "guestfs_" ^ shortname in
5386         pr "=head2 %s\n\n" name;
5387         pr " ";
5388         generate_prototype ~extern:false ~handle:"g" name style;
5389         pr "\n\n";
5390         pr "%s\n\n" longdesc;
5391         (match fst style with
5392          | RErr ->
5393              pr "This function returns 0 on success or -1 on error.\n\n"
5394          | RInt _ ->
5395              pr "On error this function returns -1.\n\n"
5396          | RInt64 _ ->
5397              pr "On error this function returns -1.\n\n"
5398          | RBool _ ->
5399              pr "This function returns a C truth value on success or -1 on error.\n\n"
5400          | RConstString _ ->
5401              pr "This function returns a string, or NULL on error.
5402 The string is owned by the guest handle and must I<not> be freed.\n\n"
5403          | RConstOptString _ ->
5404              pr "This function returns a string which may be NULL.
5405 There is way to return an error from this function.
5406 The string is owned by the guest handle and must I<not> be freed.\n\n"
5407          | RString _ ->
5408              pr "This function returns a string, or NULL on error.
5409 I<The caller must free the returned string after use>.\n\n"
5410          | RStringList _ ->
5411              pr "This function returns a NULL-terminated array of strings
5412 (like L<environ(3)>), or NULL if there was an error.
5413 I<The caller must free the strings and the array after use>.\n\n"
5414          | RStruct (_, typ) ->
5415              pr "This function returns a C<struct guestfs_%s *>,
5416 or NULL if there was an error.
5417 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5418          | RStructList (_, typ) ->
5419              pr "This function returns a C<struct guestfs_%s_list *>
5420 (see E<lt>guestfs-structs.hE<gt>),
5421 or NULL if there was an error.
5422 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5423          | RHashtable _ ->
5424              pr "This function returns a NULL-terminated array of
5425 strings, or NULL if there was an error.
5426 The array of strings will always have length C<2n+1>, where
5427 C<n> keys and values alternate, followed by the trailing NULL entry.
5428 I<The caller must free the strings and the array after use>.\n\n"
5429          | RBufferOut _ ->
5430              pr "This function returns a buffer, or NULL on error.
5431 The size of the returned buffer is written to C<*size_r>.
5432 I<The caller must free the returned buffer after use>.\n\n"
5433         );
5434         if List.mem ProtocolLimitWarning flags then
5435           pr "%s\n\n" protocol_limit_warning;
5436         if List.mem DangerWillRobinson flags then
5437           pr "%s\n\n" danger_will_robinson;
5438         match deprecation_notice flags with
5439         | None -> ()
5440         | Some txt -> pr "%s\n\n" txt
5441       )
5442   ) all_functions_sorted
5443
5444 and generate_structs_pod () =
5445   (* Structs documentation. *)
5446   List.iter (
5447     fun (typ, cols) ->
5448       pr "=head2 guestfs_%s\n" typ;
5449       pr "\n";
5450       pr " struct guestfs_%s {\n" typ;
5451       List.iter (
5452         function
5453         | name, FChar -> pr "   char %s;\n" name
5454         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5455         | name, FInt32 -> pr "   int32_t %s;\n" name
5456         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5457         | name, FInt64 -> pr "   int64_t %s;\n" name
5458         | name, FString -> pr "   char *%s;\n" name
5459         | name, FBuffer ->
5460             pr "   /* The next two fields describe a byte array. */\n";
5461             pr "   uint32_t %s_len;\n" name;
5462             pr "   char *%s;\n" name
5463         | name, FUUID ->
5464             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5465             pr "   char %s[32];\n" name
5466         | name, FOptPercent ->
5467             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5468             pr "   float %s;\n" name
5469       ) cols;
5470       pr " };\n";
5471       pr " \n";
5472       pr " struct guestfs_%s_list {\n" typ;
5473       pr "   uint32_t len; /* Number of elements in list. */\n";
5474       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5475       pr " };\n";
5476       pr " \n";
5477       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5478       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5479         typ typ;
5480       pr "\n"
5481   ) structs
5482
5483 and generate_availability_pod () =
5484   (* Availability documentation. *)
5485   pr "=over 4\n";
5486   pr "\n";
5487   List.iter (
5488     fun (group, functions) ->
5489       pr "=item B<%s>\n" group;
5490       pr "\n";
5491       pr "The following functions:\n";
5492       List.iter (pr "L</guestfs_%s>\n") functions;
5493       pr "\n"
5494   ) optgroups;
5495   pr "=back\n";
5496   pr "\n"
5497
5498 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5499  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5500  *
5501  * We have to use an underscore instead of a dash because otherwise
5502  * rpcgen generates incorrect code.
5503  *
5504  * This header is NOT exported to clients, but see also generate_structs_h.
5505  *)
5506 and generate_xdr () =
5507   generate_header CStyle LGPLv2plus;
5508
5509   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5510   pr "typedef string str<>;\n";
5511   pr "\n";
5512
5513   (* Internal structures. *)
5514   List.iter (
5515     function
5516     | typ, cols ->
5517         pr "struct guestfs_int_%s {\n" typ;
5518         List.iter (function
5519                    | name, FChar -> pr "  char %s;\n" name
5520                    | name, FString -> pr "  string %s<>;\n" name
5521                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5522                    | name, FUUID -> pr "  opaque %s[32];\n" name
5523                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5524                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5525                    | name, FOptPercent -> pr "  float %s;\n" name
5526                   ) cols;
5527         pr "};\n";
5528         pr "\n";
5529         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5530         pr "\n";
5531   ) structs;
5532
5533   List.iter (
5534     fun (shortname, style, _, _, _, _, _) ->
5535       let name = "guestfs_" ^ shortname in
5536
5537       (match snd style with
5538        | [] -> ()
5539        | args ->
5540            pr "struct %s_args {\n" name;
5541            List.iter (
5542              function
5543              | Pathname n | Device n | Dev_or_Path n | String n ->
5544                  pr "  string %s<>;\n" n
5545              | OptString n -> pr "  str *%s;\n" n
5546              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5547              | Bool n -> pr "  bool %s;\n" n
5548              | Int n -> pr "  int %s;\n" n
5549              | Int64 n -> pr "  hyper %s;\n" n
5550              | BufferIn n ->
5551                  pr "  opaque %s<>;\n" n
5552              | FileIn _ | FileOut _ -> ()
5553            ) args;
5554            pr "};\n\n"
5555       );
5556       (match fst style with
5557        | RErr -> ()
5558        | RInt n ->
5559            pr "struct %s_ret {\n" name;
5560            pr "  int %s;\n" n;
5561            pr "};\n\n"
5562        | RInt64 n ->
5563            pr "struct %s_ret {\n" name;
5564            pr "  hyper %s;\n" n;
5565            pr "};\n\n"
5566        | RBool n ->
5567            pr "struct %s_ret {\n" name;
5568            pr "  bool %s;\n" n;
5569            pr "};\n\n"
5570        | RConstString _ | RConstOptString _ ->
5571            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5572        | RString n ->
5573            pr "struct %s_ret {\n" name;
5574            pr "  string %s<>;\n" n;
5575            pr "};\n\n"
5576        | RStringList n ->
5577            pr "struct %s_ret {\n" name;
5578            pr "  str %s<>;\n" n;
5579            pr "};\n\n"
5580        | RStruct (n, typ) ->
5581            pr "struct %s_ret {\n" name;
5582            pr "  guestfs_int_%s %s;\n" typ n;
5583            pr "};\n\n"
5584        | RStructList (n, typ) ->
5585            pr "struct %s_ret {\n" name;
5586            pr "  guestfs_int_%s_list %s;\n" typ n;
5587            pr "};\n\n"
5588        | RHashtable n ->
5589            pr "struct %s_ret {\n" name;
5590            pr "  str %s<>;\n" n;
5591            pr "};\n\n"
5592        | RBufferOut n ->
5593            pr "struct %s_ret {\n" name;
5594            pr "  opaque %s<>;\n" n;
5595            pr "};\n\n"
5596       );
5597   ) daemon_functions;
5598
5599   (* Table of procedure numbers. *)
5600   pr "enum guestfs_procedure {\n";
5601   List.iter (
5602     fun (shortname, _, proc_nr, _, _, _, _) ->
5603       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5604   ) daemon_functions;
5605   pr "  GUESTFS_PROC_NR_PROCS\n";
5606   pr "};\n";
5607   pr "\n";
5608
5609   (* Having to choose a maximum message size is annoying for several
5610    * reasons (it limits what we can do in the API), but it (a) makes
5611    * the protocol a lot simpler, and (b) provides a bound on the size
5612    * of the daemon which operates in limited memory space.
5613    *)
5614   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5615   pr "\n";
5616
5617   (* Message header, etc. *)
5618   pr "\
5619 /* The communication protocol is now documented in the guestfs(3)
5620  * manpage.
5621  */
5622
5623 const GUESTFS_PROGRAM = 0x2000F5F5;
5624 const GUESTFS_PROTOCOL_VERSION = 1;
5625
5626 /* These constants must be larger than any possible message length. */
5627 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5628 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5629
5630 enum guestfs_message_direction {
5631   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5632   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5633 };
5634
5635 enum guestfs_message_status {
5636   GUESTFS_STATUS_OK = 0,
5637   GUESTFS_STATUS_ERROR = 1
5638 };
5639
5640 const GUESTFS_ERROR_LEN = 256;
5641
5642 struct guestfs_message_error {
5643   string error_message<GUESTFS_ERROR_LEN>;
5644 };
5645
5646 struct guestfs_message_header {
5647   unsigned prog;                     /* GUESTFS_PROGRAM */
5648   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5649   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5650   guestfs_message_direction direction;
5651   unsigned serial;                   /* message serial number */
5652   guestfs_message_status status;
5653 };
5654
5655 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5656
5657 struct guestfs_chunk {
5658   int cancel;                        /* if non-zero, transfer is cancelled */
5659   /* data size is 0 bytes if the transfer has finished successfully */
5660   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5661 };
5662 "
5663
5664 (* Generate the guestfs-structs.h file. *)
5665 and generate_structs_h () =
5666   generate_header CStyle LGPLv2plus;
5667
5668   (* This is a public exported header file containing various
5669    * structures.  The structures are carefully written to have
5670    * exactly the same in-memory format as the XDR structures that
5671    * we use on the wire to the daemon.  The reason for creating
5672    * copies of these structures here is just so we don't have to
5673    * export the whole of guestfs_protocol.h (which includes much
5674    * unrelated and XDR-dependent stuff that we don't want to be
5675    * public, or required by clients).
5676    *
5677    * To reiterate, we will pass these structures to and from the
5678    * client with a simple assignment or memcpy, so the format
5679    * must be identical to what rpcgen / the RFC defines.
5680    *)
5681
5682   (* Public structures. *)
5683   List.iter (
5684     fun (typ, cols) ->
5685       pr "struct guestfs_%s {\n" typ;
5686       List.iter (
5687         function
5688         | name, FChar -> pr "  char %s;\n" name
5689         | name, FString -> pr "  char *%s;\n" name
5690         | name, FBuffer ->
5691             pr "  uint32_t %s_len;\n" name;
5692             pr "  char *%s;\n" name
5693         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5694         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5695         | name, FInt32 -> pr "  int32_t %s;\n" name
5696         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5697         | name, FInt64 -> pr "  int64_t %s;\n" name
5698         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5699       ) cols;
5700       pr "};\n";
5701       pr "\n";
5702       pr "struct guestfs_%s_list {\n" typ;
5703       pr "  uint32_t len;\n";
5704       pr "  struct guestfs_%s *val;\n" typ;
5705       pr "};\n";
5706       pr "\n";
5707       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5708       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5709       pr "\n"
5710   ) structs
5711
5712 (* Generate the guestfs-actions.h file. *)
5713 and generate_actions_h () =
5714   generate_header CStyle LGPLv2plus;
5715   List.iter (
5716     fun (shortname, style, _, _, _, _, _) ->
5717       let name = "guestfs_" ^ shortname in
5718       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5719         name style
5720   ) all_functions
5721
5722 (* Generate the guestfs-internal-actions.h file. *)
5723 and generate_internal_actions_h () =
5724   generate_header CStyle LGPLv2plus;
5725   List.iter (
5726     fun (shortname, style, _, _, _, _, _) ->
5727       let name = "guestfs__" ^ shortname in
5728       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5729         name style
5730   ) non_daemon_functions
5731
5732 (* Generate the client-side dispatch stubs. *)
5733 and generate_client_actions () =
5734   generate_header CStyle LGPLv2plus;
5735
5736   pr "\
5737 #include <stdio.h>
5738 #include <stdlib.h>
5739 #include <stdint.h>
5740 #include <string.h>
5741 #include <inttypes.h>
5742
5743 #include \"guestfs.h\"
5744 #include \"guestfs-internal.h\"
5745 #include \"guestfs-internal-actions.h\"
5746 #include \"guestfs_protocol.h\"
5747
5748 #define error guestfs_error
5749 //#define perrorf guestfs_perrorf
5750 #define safe_malloc guestfs_safe_malloc
5751 #define safe_realloc guestfs_safe_realloc
5752 //#define safe_strdup guestfs_safe_strdup
5753 #define safe_memdup guestfs_safe_memdup
5754
5755 /* Check the return message from a call for validity. */
5756 static int
5757 check_reply_header (guestfs_h *g,
5758                     const struct guestfs_message_header *hdr,
5759                     unsigned int proc_nr, unsigned int serial)
5760 {
5761   if (hdr->prog != GUESTFS_PROGRAM) {
5762     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5763     return -1;
5764   }
5765   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5766     error (g, \"wrong protocol version (%%d/%%d)\",
5767            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5768     return -1;
5769   }
5770   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5771     error (g, \"unexpected message direction (%%d/%%d)\",
5772            hdr->direction, GUESTFS_DIRECTION_REPLY);
5773     return -1;
5774   }
5775   if (hdr->proc != proc_nr) {
5776     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5777     return -1;
5778   }
5779   if (hdr->serial != serial) {
5780     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5781     return -1;
5782   }
5783
5784   return 0;
5785 }
5786
5787 /* Check we are in the right state to run a high-level action. */
5788 static int
5789 check_state (guestfs_h *g, const char *caller)
5790 {
5791   if (!guestfs__is_ready (g)) {
5792     if (guestfs__is_config (g) || guestfs__is_launching (g))
5793       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5794         caller);
5795     else
5796       error (g, \"%%s called from the wrong state, %%d != READY\",
5797         caller, guestfs__get_state (g));
5798     return -1;
5799   }
5800   return 0;
5801 }
5802
5803 ";
5804
5805   (* Generate code to generate guestfish call traces. *)
5806   let trace_call shortname style =
5807     pr "  if (guestfs__get_trace (g)) {\n";
5808
5809     let needs_i =
5810       List.exists (function
5811                    | StringList _ | DeviceList _ -> true
5812                    | _ -> false) (snd style) in
5813     if needs_i then (
5814       pr "    int i;\n";
5815       pr "\n"
5816     );
5817
5818     pr "    printf (\"%s\");\n" shortname;
5819     List.iter (
5820       function
5821       | String n                        (* strings *)
5822       | Device n
5823       | Pathname n
5824       | Dev_or_Path n
5825       | FileIn n
5826       | FileOut n
5827       | BufferIn n ->
5828           (* guestfish doesn't support string escaping, so neither do we *)
5829           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5830       | OptString n ->                  (* string option *)
5831           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5832           pr "    else printf (\" null\");\n"
5833       | StringList n
5834       | DeviceList n ->                 (* string list *)
5835           pr "    putchar (' ');\n";
5836           pr "    putchar ('\"');\n";
5837           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5838           pr "      if (i > 0) putchar (' ');\n";
5839           pr "      fputs (%s[i], stdout);\n" n;
5840           pr "    }\n";
5841           pr "    putchar ('\"');\n";
5842       | Bool n ->                       (* boolean *)
5843           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5844       | Int n ->                        (* int *)
5845           pr "    printf (\" %%d\", %s);\n" n
5846       | Int64 n ->
5847           pr "    printf (\" %%\" PRIi64, %s);\n" n
5848     ) (snd style);
5849     pr "    putchar ('\\n');\n";
5850     pr "  }\n";
5851     pr "\n";
5852   in
5853
5854   (* For non-daemon functions, generate a wrapper around each function. *)
5855   List.iter (
5856     fun (shortname, style, _, _, _, _, _) ->
5857       let name = "guestfs_" ^ shortname in
5858
5859       generate_prototype ~extern:false ~semicolon:false ~newline:true
5860         ~handle:"g" name style;
5861       pr "{\n";
5862       trace_call shortname style;
5863       pr "  return guestfs__%s " shortname;
5864       generate_c_call_args ~handle:"g" style;
5865       pr ";\n";
5866       pr "}\n";
5867       pr "\n"
5868   ) non_daemon_functions;
5869
5870   (* Client-side stubs for each function. *)
5871   List.iter (
5872     fun (shortname, style, _, _, _, _, _) ->
5873       let name = "guestfs_" ^ shortname in
5874
5875       (* Generate the action stub. *)
5876       generate_prototype ~extern:false ~semicolon:false ~newline:true
5877         ~handle:"g" name style;
5878
5879       let error_code =
5880         match fst style with
5881         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5882         | RConstString _ | RConstOptString _ ->
5883             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5884         | RString _ | RStringList _
5885         | RStruct _ | RStructList _
5886         | RHashtable _ | RBufferOut _ ->
5887             "NULL" in
5888
5889       pr "{\n";
5890
5891       (match snd style with
5892        | [] -> ()
5893        | _ -> pr "  struct %s_args args;\n" name
5894       );
5895
5896       pr "  guestfs_message_header hdr;\n";
5897       pr "  guestfs_message_error err;\n";
5898       let has_ret =
5899         match fst style with
5900         | RErr -> false
5901         | RConstString _ | RConstOptString _ ->
5902             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5903         | RInt _ | RInt64 _
5904         | RBool _ | RString _ | RStringList _
5905         | RStruct _ | RStructList _
5906         | RHashtable _ | RBufferOut _ ->
5907             pr "  struct %s_ret ret;\n" name;
5908             true in
5909
5910       pr "  int serial;\n";
5911       pr "  int r;\n";
5912       pr "\n";
5913       trace_call shortname style;
5914       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5915         shortname error_code;
5916       pr "  guestfs___set_busy (g);\n";
5917       pr "\n";
5918
5919       (* Send the main header and arguments. *)
5920       (match snd style with
5921        | [] ->
5922            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5923              (String.uppercase shortname)
5924        | args ->
5925            List.iter (
5926              function
5927              | Pathname n | Device n | Dev_or_Path n | String n ->
5928                  pr "  args.%s = (char *) %s;\n" n n
5929              | OptString n ->
5930                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5931              | StringList n | DeviceList n ->
5932                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5933                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5934              | Bool n ->
5935                  pr "  args.%s = %s;\n" n n
5936              | Int n ->
5937                  pr "  args.%s = %s;\n" n n
5938              | Int64 n ->
5939                  pr "  args.%s = %s;\n" n n
5940              | FileIn _ | FileOut _ -> ()
5941              | BufferIn n ->
5942                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
5943                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
5944                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
5945                    shortname;
5946                  pr "    guestfs___end_busy (g);\n";
5947                  pr "    return %s;\n" error_code;
5948                  pr "  }\n";
5949                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
5950                  pr "  args.%s.%s_len = %s_size;\n" n n n
5951            ) args;
5952            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5953              (String.uppercase shortname);
5954            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5955              name;
5956       );
5957       pr "  if (serial == -1) {\n";
5958       pr "    guestfs___end_busy (g);\n";
5959       pr "    return %s;\n" error_code;
5960       pr "  }\n";
5961       pr "\n";
5962
5963       (* Send any additional files (FileIn) requested. *)
5964       let need_read_reply_label = ref false in
5965       List.iter (
5966         function
5967         | FileIn n ->
5968             pr "  r = guestfs___send_file (g, %s);\n" n;
5969             pr "  if (r == -1) {\n";
5970             pr "    guestfs___end_busy (g);\n";
5971             pr "    return %s;\n" error_code;
5972             pr "  }\n";
5973             pr "  if (r == -2) /* daemon cancelled */\n";
5974             pr "    goto read_reply;\n";
5975             need_read_reply_label := true;
5976             pr "\n";
5977         | _ -> ()
5978       ) (snd style);
5979
5980       (* Wait for the reply from the remote end. *)
5981       if !need_read_reply_label then pr " read_reply:\n";
5982       pr "  memset (&hdr, 0, sizeof hdr);\n";
5983       pr "  memset (&err, 0, sizeof err);\n";
5984       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5985       pr "\n";
5986       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5987       if not has_ret then
5988         pr "NULL, NULL"
5989       else
5990         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5991       pr ");\n";
5992
5993       pr "  if (r == -1) {\n";
5994       pr "    guestfs___end_busy (g);\n";
5995       pr "    return %s;\n" error_code;
5996       pr "  }\n";
5997       pr "\n";
5998
5999       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6000         (String.uppercase shortname);
6001       pr "    guestfs___end_busy (g);\n";
6002       pr "    return %s;\n" error_code;
6003       pr "  }\n";
6004       pr "\n";
6005
6006       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6007       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6008       pr "    free (err.error_message);\n";
6009       pr "    guestfs___end_busy (g);\n";
6010       pr "    return %s;\n" error_code;
6011       pr "  }\n";
6012       pr "\n";
6013
6014       (* Expecting to receive further files (FileOut)? *)
6015       List.iter (
6016         function
6017         | FileOut n ->
6018             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6019             pr "    guestfs___end_busy (g);\n";
6020             pr "    return %s;\n" error_code;
6021             pr "  }\n";
6022             pr "\n";
6023         | _ -> ()
6024       ) (snd style);
6025
6026       pr "  guestfs___end_busy (g);\n";
6027
6028       (match fst style with
6029        | RErr -> pr "  return 0;\n"
6030        | RInt n | RInt64 n | RBool n ->
6031            pr "  return ret.%s;\n" n
6032        | RConstString _ | RConstOptString _ ->
6033            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6034        | RString n ->
6035            pr "  return ret.%s; /* caller will free */\n" n
6036        | RStringList n | RHashtable n ->
6037            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6038            pr "  ret.%s.%s_val =\n" n n;
6039            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6040            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6041              n n;
6042            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6043            pr "  return ret.%s.%s_val;\n" n n
6044        | RStruct (n, _) ->
6045            pr "  /* caller will free this */\n";
6046            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6047        | RStructList (n, _) ->
6048            pr "  /* caller will free this */\n";
6049            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6050        | RBufferOut n ->
6051            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6052            pr "   * _val might be NULL here.  To make the API saner for\n";
6053            pr "   * callers, we turn this case into a unique pointer (using\n";
6054            pr "   * malloc(1)).\n";
6055            pr "   */\n";
6056            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6057            pr "    *size_r = ret.%s.%s_len;\n" n n;
6058            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6059            pr "  } else {\n";
6060            pr "    free (ret.%s.%s_val);\n" n n;
6061            pr "    char *p = safe_malloc (g, 1);\n";
6062            pr "    *size_r = ret.%s.%s_len;\n" n n;
6063            pr "    return p;\n";
6064            pr "  }\n";
6065       );
6066
6067       pr "}\n\n"
6068   ) daemon_functions;
6069
6070   (* Functions to free structures. *)
6071   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6072   pr " * structure format is identical to the XDR format.  See note in\n";
6073   pr " * generator.ml.\n";
6074   pr " */\n";
6075   pr "\n";
6076
6077   List.iter (
6078     fun (typ, _) ->
6079       pr "void\n";
6080       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6081       pr "{\n";
6082       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6083       pr "  free (x);\n";
6084       pr "}\n";
6085       pr "\n";
6086
6087       pr "void\n";
6088       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6089       pr "{\n";
6090       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6091       pr "  free (x);\n";
6092       pr "}\n";
6093       pr "\n";
6094
6095   ) structs;
6096
6097 (* Generate daemon/actions.h. *)
6098 and generate_daemon_actions_h () =
6099   generate_header CStyle GPLv2plus;
6100
6101   pr "#include \"../src/guestfs_protocol.h\"\n";
6102   pr "\n";
6103
6104   List.iter (
6105     fun (name, style, _, _, _, _, _) ->
6106       generate_prototype
6107         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6108         name style;
6109   ) daemon_functions
6110
6111 (* Generate the linker script which controls the visibility of
6112  * symbols in the public ABI and ensures no other symbols get
6113  * exported accidentally.
6114  *)
6115 and generate_linker_script () =
6116   generate_header HashStyle GPLv2plus;
6117
6118   let globals = [
6119     "guestfs_create";
6120     "guestfs_close";
6121     "guestfs_get_error_handler";
6122     "guestfs_get_out_of_memory_handler";
6123     "guestfs_last_error";
6124     "guestfs_set_error_handler";
6125     "guestfs_set_launch_done_callback";
6126     "guestfs_set_log_message_callback";
6127     "guestfs_set_out_of_memory_handler";
6128     "guestfs_set_subprocess_quit_callback";
6129
6130     (* Unofficial parts of the API: the bindings code use these
6131      * functions, so it is useful to export them.
6132      *)
6133     "guestfs_safe_calloc";
6134     "guestfs_safe_malloc";
6135   ] in
6136   let functions =
6137     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6138       all_functions in
6139   let structs =
6140     List.concat (
6141       List.map (fun (typ, _) ->
6142                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6143         structs
6144     ) in
6145   let globals = List.sort compare (globals @ functions @ structs) in
6146
6147   pr "{\n";
6148   pr "    global:\n";
6149   List.iter (pr "        %s;\n") globals;
6150   pr "\n";
6151
6152   pr "    local:\n";
6153   pr "        *;\n";
6154   pr "};\n"
6155
6156 (* Generate the server-side stubs. *)
6157 and generate_daemon_actions () =
6158   generate_header CStyle GPLv2plus;
6159
6160   pr "#include <config.h>\n";
6161   pr "\n";
6162   pr "#include <stdio.h>\n";
6163   pr "#include <stdlib.h>\n";
6164   pr "#include <string.h>\n";
6165   pr "#include <inttypes.h>\n";
6166   pr "#include <rpc/types.h>\n";
6167   pr "#include <rpc/xdr.h>\n";
6168   pr "\n";
6169   pr "#include \"daemon.h\"\n";
6170   pr "#include \"c-ctype.h\"\n";
6171   pr "#include \"../src/guestfs_protocol.h\"\n";
6172   pr "#include \"actions.h\"\n";
6173   pr "\n";
6174
6175   List.iter (
6176     fun (name, style, _, _, _, _, _) ->
6177       (* Generate server-side stubs. *)
6178       pr "static void %s_stub (XDR *xdr_in)\n" name;
6179       pr "{\n";
6180       let error_code =
6181         match fst style with
6182         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6183         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6184         | RBool _ -> pr "  int r;\n"; "-1"
6185         | RConstString _ | RConstOptString _ ->
6186             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6187         | RString _ -> pr "  char *r;\n"; "NULL"
6188         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6189         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6190         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6191         | RBufferOut _ ->
6192             pr "  size_t size = 1;\n";
6193             pr "  char *r;\n";
6194             "NULL" in
6195
6196       (match snd style with
6197        | [] -> ()
6198        | args ->
6199            pr "  struct guestfs_%s_args args;\n" name;
6200            List.iter (
6201              function
6202              | Device n | Dev_or_Path n
6203              | Pathname n
6204              | String n -> ()
6205              | OptString n -> pr "  char *%s;\n" n
6206              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6207              | Bool n -> pr "  int %s;\n" n
6208              | Int n -> pr "  int %s;\n" n
6209              | Int64 n -> pr "  int64_t %s;\n" n
6210              | FileIn _ | FileOut _ -> ()
6211              | BufferIn n ->
6212                  pr "  const char *%s;\n" n;
6213                  pr "  size_t %s_size;\n" n
6214            ) args
6215       );
6216       pr "\n";
6217
6218       let is_filein =
6219         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6220
6221       (match snd style with
6222        | [] -> ()
6223        | args ->
6224            pr "  memset (&args, 0, sizeof args);\n";
6225            pr "\n";
6226            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6227            if is_filein then
6228              pr "    if (cancel_receive () != -2)\n";
6229            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6230            pr "    goto done;\n";
6231            pr "  }\n";
6232            let pr_args n =
6233              pr "  char *%s = args.%s;\n" n n
6234            in
6235            let pr_list_handling_code n =
6236              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6237              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6238              pr "  if (%s == NULL) {\n" n;
6239              if is_filein then
6240                pr "    if (cancel_receive () != -2)\n";
6241              pr "      reply_with_perror (\"realloc\");\n";
6242              pr "    goto done;\n";
6243              pr "  }\n";
6244              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6245              pr "  args.%s.%s_val = %s;\n" n n n;
6246            in
6247            List.iter (
6248              function
6249              | Pathname n ->
6250                  pr_args n;
6251                  pr "  ABS_PATH (%s, %s, goto done);\n"
6252                    n (if is_filein then "cancel_receive ()" else "0");
6253              | Device n ->
6254                  pr_args n;
6255                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6256                    n (if is_filein then "cancel_receive ()" else "0");
6257              | Dev_or_Path n ->
6258                  pr_args n;
6259                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6260                    n (if is_filein then "cancel_receive ()" else "0");
6261              | String n -> pr_args n
6262              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6263              | StringList n ->
6264                  pr_list_handling_code n;
6265              | DeviceList n ->
6266                  pr_list_handling_code n;
6267                  pr "  /* Ensure that each is a device,\n";
6268                  pr "   * and perform device name translation. */\n";
6269                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6270                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6271                    (if is_filein then "cancel_receive ()" else "0");
6272                  pr "  }\n";
6273              | Bool n -> pr "  %s = args.%s;\n" n n
6274              | Int n -> pr "  %s = args.%s;\n" n n
6275              | Int64 n -> pr "  %s = args.%s;\n" n n
6276              | FileIn _ | FileOut _ -> ()
6277              | BufferIn n ->
6278                  pr "  %s = args.%s.%s_val;\n" n n n;
6279                  pr "  %s_size = args.%s.%s_len;\n" n n n
6280            ) args;
6281            pr "\n"
6282       );
6283
6284       (* this is used at least for do_equal *)
6285       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6286         (* Emit NEED_ROOT just once, even when there are two or
6287            more Pathname args *)
6288         pr "  NEED_ROOT (%s, goto done);\n"
6289           (if is_filein then "cancel_receive ()" else "0");
6290       );
6291
6292       (* Don't want to call the impl with any FileIn or FileOut
6293        * parameters, since these go "outside" the RPC protocol.
6294        *)
6295       let args' =
6296         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6297           (snd style) in
6298       pr "  r = do_%s " name;
6299       generate_c_call_args (fst style, args');
6300       pr ";\n";
6301
6302       (match fst style with
6303        | RErr | RInt _ | RInt64 _ | RBool _
6304        | RConstString _ | RConstOptString _
6305        | RString _ | RStringList _ | RHashtable _
6306        | RStruct (_, _) | RStructList (_, _) ->
6307            pr "  if (r == %s)\n" error_code;
6308            pr "    /* do_%s has already called reply_with_error */\n" name;
6309            pr "    goto done;\n";
6310            pr "\n"
6311        | RBufferOut _ ->
6312            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6313            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6314            pr "   */\n";
6315            pr "  if (size == 1 && r == %s)\n" error_code;
6316            pr "    /* do_%s has already called reply_with_error */\n" name;
6317            pr "    goto done;\n";
6318            pr "\n"
6319       );
6320
6321       (* If there are any FileOut parameters, then the impl must
6322        * send its own reply.
6323        *)
6324       let no_reply =
6325         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6326       if no_reply then
6327         pr "  /* do_%s has already sent a reply */\n" name
6328       else (
6329         match fst style with
6330         | RErr -> pr "  reply (NULL, NULL);\n"
6331         | RInt n | RInt64 n | RBool n ->
6332             pr "  struct guestfs_%s_ret ret;\n" name;
6333             pr "  ret.%s = r;\n" n;
6334             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6335               name
6336         | RConstString _ | RConstOptString _ ->
6337             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6338         | RString n ->
6339             pr "  struct guestfs_%s_ret ret;\n" name;
6340             pr "  ret.%s = r;\n" n;
6341             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6342               name;
6343             pr "  free (r);\n"
6344         | RStringList n | RHashtable n ->
6345             pr "  struct guestfs_%s_ret ret;\n" name;
6346             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6347             pr "  ret.%s.%s_val = r;\n" n n;
6348             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6349               name;
6350             pr "  free_strings (r);\n"
6351         | RStruct (n, _) ->
6352             pr "  struct guestfs_%s_ret ret;\n" name;
6353             pr "  ret.%s = *r;\n" n;
6354             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6355               name;
6356             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6357               name
6358         | RStructList (n, _) ->
6359             pr "  struct guestfs_%s_ret ret;\n" name;
6360             pr "  ret.%s = *r;\n" n;
6361             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6362               name;
6363             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6364               name
6365         | RBufferOut n ->
6366             pr "  struct guestfs_%s_ret ret;\n" name;
6367             pr "  ret.%s.%s_val = r;\n" n n;
6368             pr "  ret.%s.%s_len = size;\n" n n;
6369             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6370               name;
6371             pr "  free (r);\n"
6372       );
6373
6374       (* Free the args. *)
6375       pr "done:\n";
6376       (match snd style with
6377        | [] -> ()
6378        | _ ->
6379            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6380              name
6381       );
6382       pr "  return;\n";
6383       pr "}\n\n";
6384   ) daemon_functions;
6385
6386   (* Dispatch function. *)
6387   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6388   pr "{\n";
6389   pr "  switch (proc_nr) {\n";
6390
6391   List.iter (
6392     fun (name, style, _, _, _, _, _) ->
6393       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6394       pr "      %s_stub (xdr_in);\n" name;
6395       pr "      break;\n"
6396   ) daemon_functions;
6397
6398   pr "    default:\n";
6399   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";
6400   pr "  }\n";
6401   pr "}\n";
6402   pr "\n";
6403
6404   (* LVM columns and tokenization functions. *)
6405   (* XXX This generates crap code.  We should rethink how we
6406    * do this parsing.
6407    *)
6408   List.iter (
6409     function
6410     | typ, cols ->
6411         pr "static const char *lvm_%s_cols = \"%s\";\n"
6412           typ (String.concat "," (List.map fst cols));
6413         pr "\n";
6414
6415         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6416         pr "{\n";
6417         pr "  char *tok, *p, *next;\n";
6418         pr "  int i, j;\n";
6419         pr "\n";
6420         (*
6421           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6422           pr "\n";
6423         *)
6424         pr "  if (!str) {\n";
6425         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6426         pr "    return -1;\n";
6427         pr "  }\n";
6428         pr "  if (!*str || c_isspace (*str)) {\n";
6429         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6430         pr "    return -1;\n";
6431         pr "  }\n";
6432         pr "  tok = str;\n";
6433         List.iter (
6434           fun (name, coltype) ->
6435             pr "  if (!tok) {\n";
6436             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6437             pr "    return -1;\n";
6438             pr "  }\n";
6439             pr "  p = strchrnul (tok, ',');\n";
6440             pr "  if (*p) next = p+1; else next = NULL;\n";
6441             pr "  *p = '\\0';\n";
6442             (match coltype with
6443              | FString ->
6444                  pr "  r->%s = strdup (tok);\n" name;
6445                  pr "  if (r->%s == NULL) {\n" name;
6446                  pr "    perror (\"strdup\");\n";
6447                  pr "    return -1;\n";
6448                  pr "  }\n"
6449              | FUUID ->
6450                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6451                  pr "    if (tok[j] == '\\0') {\n";
6452                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6453                  pr "      return -1;\n";
6454                  pr "    } else if (tok[j] != '-')\n";
6455                  pr "      r->%s[i++] = tok[j];\n" name;
6456                  pr "  }\n";
6457              | FBytes ->
6458                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6459                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6460                  pr "    return -1;\n";
6461                  pr "  }\n";
6462              | FInt64 ->
6463                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6464                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6465                  pr "    return -1;\n";
6466                  pr "  }\n";
6467              | FOptPercent ->
6468                  pr "  if (tok[0] == '\\0')\n";
6469                  pr "    r->%s = -1;\n" name;
6470                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6471                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6472                  pr "    return -1;\n";
6473                  pr "  }\n";
6474              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6475                  assert false (* can never be an LVM column *)
6476             );
6477             pr "  tok = next;\n";
6478         ) cols;
6479
6480         pr "  if (tok != NULL) {\n";
6481         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6482         pr "    return -1;\n";
6483         pr "  }\n";
6484         pr "  return 0;\n";
6485         pr "}\n";
6486         pr "\n";
6487
6488         pr "guestfs_int_lvm_%s_list *\n" typ;
6489         pr "parse_command_line_%ss (void)\n" typ;
6490         pr "{\n";
6491         pr "  char *out, *err;\n";
6492         pr "  char *p, *pend;\n";
6493         pr "  int r, i;\n";
6494         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6495         pr "  void *newp;\n";
6496         pr "\n";
6497         pr "  ret = malloc (sizeof *ret);\n";
6498         pr "  if (!ret) {\n";
6499         pr "    reply_with_perror (\"malloc\");\n";
6500         pr "    return NULL;\n";
6501         pr "  }\n";
6502         pr "\n";
6503         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6504         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6505         pr "\n";
6506         pr "  r = command (&out, &err,\n";
6507         pr "           \"lvm\", \"%ss\",\n" typ;
6508         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6509         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6510         pr "  if (r == -1) {\n";
6511         pr "    reply_with_error (\"%%s\", err);\n";
6512         pr "    free (out);\n";
6513         pr "    free (err);\n";
6514         pr "    free (ret);\n";
6515         pr "    return NULL;\n";
6516         pr "  }\n";
6517         pr "\n";
6518         pr "  free (err);\n";
6519         pr "\n";
6520         pr "  /* Tokenize each line of the output. */\n";
6521         pr "  p = out;\n";
6522         pr "  i = 0;\n";
6523         pr "  while (p) {\n";
6524         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6525         pr "    if (pend) {\n";
6526         pr "      *pend = '\\0';\n";
6527         pr "      pend++;\n";
6528         pr "    }\n";
6529         pr "\n";
6530         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6531         pr "      p++;\n";
6532         pr "\n";
6533         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6534         pr "      p = pend;\n";
6535         pr "      continue;\n";
6536         pr "    }\n";
6537         pr "\n";
6538         pr "    /* Allocate some space to store this next entry. */\n";
6539         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6540         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6541         pr "    if (newp == NULL) {\n";
6542         pr "      reply_with_perror (\"realloc\");\n";
6543         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6544         pr "      free (ret);\n";
6545         pr "      free (out);\n";
6546         pr "      return NULL;\n";
6547         pr "    }\n";
6548         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6549         pr "\n";
6550         pr "    /* Tokenize the next entry. */\n";
6551         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6552         pr "    if (r == -1) {\n";
6553         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6554         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6555         pr "      free (ret);\n";
6556         pr "      free (out);\n";
6557         pr "      return NULL;\n";
6558         pr "    }\n";
6559         pr "\n";
6560         pr "    ++i;\n";
6561         pr "    p = pend;\n";
6562         pr "  }\n";
6563         pr "\n";
6564         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6565         pr "\n";
6566         pr "  free (out);\n";
6567         pr "  return ret;\n";
6568         pr "}\n"
6569
6570   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6571
6572 (* Generate a list of function names, for debugging in the daemon.. *)
6573 and generate_daemon_names () =
6574   generate_header CStyle GPLv2plus;
6575
6576   pr "#include <config.h>\n";
6577   pr "\n";
6578   pr "#include \"daemon.h\"\n";
6579   pr "\n";
6580
6581   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6582   pr "const char *function_names[] = {\n";
6583   List.iter (
6584     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6585   ) daemon_functions;
6586   pr "};\n";
6587
6588 (* Generate the optional groups for the daemon to implement
6589  * guestfs_available.
6590  *)
6591 and generate_daemon_optgroups_c () =
6592   generate_header CStyle GPLv2plus;
6593
6594   pr "#include <config.h>\n";
6595   pr "\n";
6596   pr "#include \"daemon.h\"\n";
6597   pr "#include \"optgroups.h\"\n";
6598   pr "\n";
6599
6600   pr "struct optgroup optgroups[] = {\n";
6601   List.iter (
6602     fun (group, _) ->
6603       pr "  { \"%s\", optgroup_%s_available },\n" group group
6604   ) optgroups;
6605   pr "  { NULL, NULL }\n";
6606   pr "};\n"
6607
6608 and generate_daemon_optgroups_h () =
6609   generate_header CStyle GPLv2plus;
6610
6611   List.iter (
6612     fun (group, _) ->
6613       pr "extern int optgroup_%s_available (void);\n" group
6614   ) optgroups
6615
6616 (* Generate the tests. *)
6617 and generate_tests () =
6618   generate_header CStyle GPLv2plus;
6619
6620   pr "\
6621 #include <stdio.h>
6622 #include <stdlib.h>
6623 #include <string.h>
6624 #include <unistd.h>
6625 #include <sys/types.h>
6626 #include <fcntl.h>
6627
6628 #include \"guestfs.h\"
6629 #include \"guestfs-internal.h\"
6630
6631 static guestfs_h *g;
6632 static int suppress_error = 0;
6633
6634 static void print_error (guestfs_h *g, void *data, const char *msg)
6635 {
6636   if (!suppress_error)
6637     fprintf (stderr, \"%%s\\n\", msg);
6638 }
6639
6640 /* FIXME: nearly identical code appears in fish.c */
6641 static void print_strings (char *const *argv)
6642 {
6643   int argc;
6644
6645   for (argc = 0; argv[argc] != NULL; ++argc)
6646     printf (\"\\t%%s\\n\", argv[argc]);
6647 }
6648
6649 /*
6650 static void print_table (char const *const *argv)
6651 {
6652   int i;
6653
6654   for (i = 0; argv[i] != NULL; i += 2)
6655     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6656 }
6657 */
6658
6659 ";
6660
6661   (* Generate a list of commands which are not tested anywhere. *)
6662   pr "static void no_test_warnings (void)\n";
6663   pr "{\n";
6664
6665   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6666   List.iter (
6667     fun (_, _, _, _, tests, _, _) ->
6668       let tests = filter_map (
6669         function
6670         | (_, (Always|If _|Unless _), test) -> Some test
6671         | (_, Disabled, _) -> None
6672       ) tests in
6673       let seq = List.concat (List.map seq_of_test tests) in
6674       let cmds_tested = List.map List.hd seq in
6675       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6676   ) all_functions;
6677
6678   List.iter (
6679     fun (name, _, _, _, _, _, _) ->
6680       if not (Hashtbl.mem hash name) then
6681         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6682   ) all_functions;
6683
6684   pr "}\n";
6685   pr "\n";
6686
6687   (* Generate the actual tests.  Note that we generate the tests
6688    * in reverse order, deliberately, so that (in general) the
6689    * newest tests run first.  This makes it quicker and easier to
6690    * debug them.
6691    *)
6692   let test_names =
6693     List.map (
6694       fun (name, _, _, flags, tests, _, _) ->
6695         mapi (generate_one_test name flags) tests
6696     ) (List.rev all_functions) in
6697   let test_names = List.concat test_names in
6698   let nr_tests = List.length test_names in
6699
6700   pr "\
6701 int main (int argc, char *argv[])
6702 {
6703   char c = 0;
6704   unsigned long int n_failed = 0;
6705   const char *filename;
6706   int fd;
6707   int nr_tests, test_num = 0;
6708
6709   setbuf (stdout, NULL);
6710
6711   no_test_warnings ();
6712
6713   g = guestfs_create ();
6714   if (g == NULL) {
6715     printf (\"guestfs_create FAILED\\n\");
6716     exit (EXIT_FAILURE);
6717   }
6718
6719   guestfs_set_error_handler (g, print_error, NULL);
6720
6721   guestfs_set_path (g, \"../appliance\");
6722
6723   filename = \"test1.img\";
6724   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6725   if (fd == -1) {
6726     perror (filename);
6727     exit (EXIT_FAILURE);
6728   }
6729   if (lseek (fd, %d, SEEK_SET) == -1) {
6730     perror (\"lseek\");
6731     close (fd);
6732     unlink (filename);
6733     exit (EXIT_FAILURE);
6734   }
6735   if (write (fd, &c, 1) == -1) {
6736     perror (\"write\");
6737     close (fd);
6738     unlink (filename);
6739     exit (EXIT_FAILURE);
6740   }
6741   if (close (fd) == -1) {
6742     perror (filename);
6743     unlink (filename);
6744     exit (EXIT_FAILURE);
6745   }
6746   if (guestfs_add_drive (g, filename) == -1) {
6747     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6748     exit (EXIT_FAILURE);
6749   }
6750
6751   filename = \"test2.img\";
6752   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6753   if (fd == -1) {
6754     perror (filename);
6755     exit (EXIT_FAILURE);
6756   }
6757   if (lseek (fd, %d, SEEK_SET) == -1) {
6758     perror (\"lseek\");
6759     close (fd);
6760     unlink (filename);
6761     exit (EXIT_FAILURE);
6762   }
6763   if (write (fd, &c, 1) == -1) {
6764     perror (\"write\");
6765     close (fd);
6766     unlink (filename);
6767     exit (EXIT_FAILURE);
6768   }
6769   if (close (fd) == -1) {
6770     perror (filename);
6771     unlink (filename);
6772     exit (EXIT_FAILURE);
6773   }
6774   if (guestfs_add_drive (g, filename) == -1) {
6775     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6776     exit (EXIT_FAILURE);
6777   }
6778
6779   filename = \"test3.img\";
6780   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6781   if (fd == -1) {
6782     perror (filename);
6783     exit (EXIT_FAILURE);
6784   }
6785   if (lseek (fd, %d, SEEK_SET) == -1) {
6786     perror (\"lseek\");
6787     close (fd);
6788     unlink (filename);
6789     exit (EXIT_FAILURE);
6790   }
6791   if (write (fd, &c, 1) == -1) {
6792     perror (\"write\");
6793     close (fd);
6794     unlink (filename);
6795     exit (EXIT_FAILURE);
6796   }
6797   if (close (fd) == -1) {
6798     perror (filename);
6799     unlink (filename);
6800     exit (EXIT_FAILURE);
6801   }
6802   if (guestfs_add_drive (g, filename) == -1) {
6803     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6804     exit (EXIT_FAILURE);
6805   }
6806
6807   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6808     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6809     exit (EXIT_FAILURE);
6810   }
6811
6812   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6813   alarm (600);
6814
6815   if (guestfs_launch (g) == -1) {
6816     printf (\"guestfs_launch FAILED\\n\");
6817     exit (EXIT_FAILURE);
6818   }
6819
6820   /* Cancel previous alarm. */
6821   alarm (0);
6822
6823   nr_tests = %d;
6824
6825 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6826
6827   iteri (
6828     fun i test_name ->
6829       pr "  test_num++;\n";
6830       pr "  if (guestfs_get_verbose (g))\n";
6831       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6832       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6833       pr "  if (%s () == -1) {\n" test_name;
6834       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6835       pr "    n_failed++;\n";
6836       pr "  }\n";
6837   ) test_names;
6838   pr "\n";
6839
6840   pr "  guestfs_close (g);\n";
6841   pr "  unlink (\"test1.img\");\n";
6842   pr "  unlink (\"test2.img\");\n";
6843   pr "  unlink (\"test3.img\");\n";
6844   pr "\n";
6845
6846   pr "  if (n_failed > 0) {\n";
6847   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6848   pr "    exit (EXIT_FAILURE);\n";
6849   pr "  }\n";
6850   pr "\n";
6851
6852   pr "  exit (EXIT_SUCCESS);\n";
6853   pr "}\n"
6854
6855 and generate_one_test name flags i (init, prereq, test) =
6856   let test_name = sprintf "test_%s_%d" name i in
6857
6858   pr "\
6859 static int %s_skip (void)
6860 {
6861   const char *str;
6862
6863   str = getenv (\"TEST_ONLY\");
6864   if (str)
6865     return strstr (str, \"%s\") == NULL;
6866   str = getenv (\"SKIP_%s\");
6867   if (str && STREQ (str, \"1\")) return 1;
6868   str = getenv (\"SKIP_TEST_%s\");
6869   if (str && STREQ (str, \"1\")) return 1;
6870   return 0;
6871 }
6872
6873 " test_name name (String.uppercase test_name) (String.uppercase name);
6874
6875   (match prereq with
6876    | Disabled | Always -> ()
6877    | If code | Unless code ->
6878        pr "static int %s_prereq (void)\n" test_name;
6879        pr "{\n";
6880        pr "  %s\n" code;
6881        pr "}\n";
6882        pr "\n";
6883   );
6884
6885   pr "\
6886 static int %s (void)
6887 {
6888   if (%s_skip ()) {
6889     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6890     return 0;
6891   }
6892
6893 " test_name test_name test_name;
6894
6895   (* Optional functions should only be tested if the relevant
6896    * support is available in the daemon.
6897    *)
6898   List.iter (
6899     function
6900     | Optional group ->
6901         pr "  {\n";
6902         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6903         pr "    int r;\n";
6904         pr "    suppress_error = 1;\n";
6905         pr "    r = guestfs_available (g, (char **) groups);\n";
6906         pr "    suppress_error = 0;\n";
6907         pr "    if (r == -1) {\n";
6908         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6909         pr "      return 0;\n";
6910         pr "    }\n";
6911         pr "  }\n";
6912     | _ -> ()
6913   ) flags;
6914
6915   (match prereq with
6916    | Disabled ->
6917        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6918    | If _ ->
6919        pr "  if (! %s_prereq ()) {\n" test_name;
6920        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6921        pr "    return 0;\n";
6922        pr "  }\n";
6923        pr "\n";
6924        generate_one_test_body name i test_name init test;
6925    | Unless _ ->
6926        pr "  if (%s_prereq ()) {\n" test_name;
6927        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6928        pr "    return 0;\n";
6929        pr "  }\n";
6930        pr "\n";
6931        generate_one_test_body name i test_name init test;
6932    | Always ->
6933        generate_one_test_body name i test_name init test
6934   );
6935
6936   pr "  return 0;\n";
6937   pr "}\n";
6938   pr "\n";
6939   test_name
6940
6941 and generate_one_test_body name i test_name init test =
6942   (match init with
6943    | InitNone (* XXX at some point, InitNone and InitEmpty became
6944                * folded together as the same thing.  Really we should
6945                * make InitNone do nothing at all, but the tests may
6946                * need to be checked to make sure this is OK.
6947                *)
6948    | InitEmpty ->
6949        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6950        List.iter (generate_test_command_call test_name)
6951          [["blockdev_setrw"; "/dev/sda"];
6952           ["umount_all"];
6953           ["lvm_remove_all"]]
6954    | InitPartition ->
6955        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6956        List.iter (generate_test_command_call test_name)
6957          [["blockdev_setrw"; "/dev/sda"];
6958           ["umount_all"];
6959           ["lvm_remove_all"];
6960           ["part_disk"; "/dev/sda"; "mbr"]]
6961    | InitBasicFS ->
6962        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6963        List.iter (generate_test_command_call test_name)
6964          [["blockdev_setrw"; "/dev/sda"];
6965           ["umount_all"];
6966           ["lvm_remove_all"];
6967           ["part_disk"; "/dev/sda"; "mbr"];
6968           ["mkfs"; "ext2"; "/dev/sda1"];
6969           ["mount_options"; ""; "/dev/sda1"; "/"]]
6970    | InitBasicFSonLVM ->
6971        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6972          test_name;
6973        List.iter (generate_test_command_call test_name)
6974          [["blockdev_setrw"; "/dev/sda"];
6975           ["umount_all"];
6976           ["lvm_remove_all"];
6977           ["part_disk"; "/dev/sda"; "mbr"];
6978           ["pvcreate"; "/dev/sda1"];
6979           ["vgcreate"; "VG"; "/dev/sda1"];
6980           ["lvcreate"; "LV"; "VG"; "8"];
6981           ["mkfs"; "ext2"; "/dev/VG/LV"];
6982           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6983    | InitISOFS ->
6984        pr "  /* InitISOFS for %s */\n" test_name;
6985        List.iter (generate_test_command_call test_name)
6986          [["blockdev_setrw"; "/dev/sda"];
6987           ["umount_all"];
6988           ["lvm_remove_all"];
6989           ["mount_ro"; "/dev/sdd"; "/"]]
6990   );
6991
6992   let get_seq_last = function
6993     | [] ->
6994         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6995           test_name
6996     | seq ->
6997         let seq = List.rev seq in
6998         List.rev (List.tl seq), List.hd seq
6999   in
7000
7001   match test with
7002   | TestRun seq ->
7003       pr "  /* TestRun for %s (%d) */\n" name i;
7004       List.iter (generate_test_command_call test_name) seq
7005   | TestOutput (seq, expected) ->
7006       pr "  /* TestOutput for %s (%d) */\n" name i;
7007       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7008       let seq, last = get_seq_last seq in
7009       let test () =
7010         pr "    if (STRNEQ (r, expected)) {\n";
7011         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7012         pr "      return -1;\n";
7013         pr "    }\n"
7014       in
7015       List.iter (generate_test_command_call test_name) seq;
7016       generate_test_command_call ~test test_name last
7017   | TestOutputList (seq, expected) ->
7018       pr "  /* TestOutputList for %s (%d) */\n" name i;
7019       let seq, last = get_seq_last seq in
7020       let test () =
7021         iteri (
7022           fun i str ->
7023             pr "    if (!r[%d]) {\n" i;
7024             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7025             pr "      print_strings (r);\n";
7026             pr "      return -1;\n";
7027             pr "    }\n";
7028             pr "    {\n";
7029             pr "      const char *expected = \"%s\";\n" (c_quote str);
7030             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7031             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7032             pr "        return -1;\n";
7033             pr "      }\n";
7034             pr "    }\n"
7035         ) expected;
7036         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7037         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7038           test_name;
7039         pr "      print_strings (r);\n";
7040         pr "      return -1;\n";
7041         pr "    }\n"
7042       in
7043       List.iter (generate_test_command_call test_name) seq;
7044       generate_test_command_call ~test test_name last
7045   | TestOutputListOfDevices (seq, expected) ->
7046       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7047       let seq, last = get_seq_last seq in
7048       let test () =
7049         iteri (
7050           fun i str ->
7051             pr "    if (!r[%d]) {\n" i;
7052             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7053             pr "      print_strings (r);\n";
7054             pr "      return -1;\n";
7055             pr "    }\n";
7056             pr "    {\n";
7057             pr "      const char *expected = \"%s\";\n" (c_quote str);
7058             pr "      r[%d][5] = 's';\n" i;
7059             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7060             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7061             pr "        return -1;\n";
7062             pr "      }\n";
7063             pr "    }\n"
7064         ) expected;
7065         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7066         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7067           test_name;
7068         pr "      print_strings (r);\n";
7069         pr "      return -1;\n";
7070         pr "    }\n"
7071       in
7072       List.iter (generate_test_command_call test_name) seq;
7073       generate_test_command_call ~test test_name last
7074   | TestOutputInt (seq, expected) ->
7075       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7076       let seq, last = get_seq_last seq in
7077       let test () =
7078         pr "    if (r != %d) {\n" expected;
7079         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7080           test_name expected;
7081         pr "               (int) r);\n";
7082         pr "      return -1;\n";
7083         pr "    }\n"
7084       in
7085       List.iter (generate_test_command_call test_name) seq;
7086       generate_test_command_call ~test test_name last
7087   | TestOutputIntOp (seq, op, expected) ->
7088       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7089       let seq, last = get_seq_last seq in
7090       let test () =
7091         pr "    if (! (r %s %d)) {\n" op expected;
7092         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7093           test_name op expected;
7094         pr "               (int) r);\n";
7095         pr "      return -1;\n";
7096         pr "    }\n"
7097       in
7098       List.iter (generate_test_command_call test_name) seq;
7099       generate_test_command_call ~test test_name last
7100   | TestOutputTrue seq ->
7101       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7102       let seq, last = get_seq_last seq in
7103       let test () =
7104         pr "    if (!r) {\n";
7105         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7106           test_name;
7107         pr "      return -1;\n";
7108         pr "    }\n"
7109       in
7110       List.iter (generate_test_command_call test_name) seq;
7111       generate_test_command_call ~test test_name last
7112   | TestOutputFalse seq ->
7113       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7114       let seq, last = get_seq_last seq in
7115       let test () =
7116         pr "    if (r) {\n";
7117         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7118           test_name;
7119         pr "      return -1;\n";
7120         pr "    }\n"
7121       in
7122       List.iter (generate_test_command_call test_name) seq;
7123       generate_test_command_call ~test test_name last
7124   | TestOutputLength (seq, expected) ->
7125       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7126       let seq, last = get_seq_last seq in
7127       let test () =
7128         pr "    int j;\n";
7129         pr "    for (j = 0; j < %d; ++j)\n" expected;
7130         pr "      if (r[j] == NULL) {\n";
7131         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7132           test_name;
7133         pr "        print_strings (r);\n";
7134         pr "        return -1;\n";
7135         pr "      }\n";
7136         pr "    if (r[j] != NULL) {\n";
7137         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7138           test_name;
7139         pr "      print_strings (r);\n";
7140         pr "      return -1;\n";
7141         pr "    }\n"
7142       in
7143       List.iter (generate_test_command_call test_name) seq;
7144       generate_test_command_call ~test test_name last
7145   | TestOutputBuffer (seq, expected) ->
7146       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7147       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7148       let seq, last = get_seq_last seq in
7149       let len = String.length expected in
7150       let test () =
7151         pr "    if (size != %d) {\n" len;
7152         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7153         pr "      return -1;\n";
7154         pr "    }\n";
7155         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7156         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7157         pr "      return -1;\n";
7158         pr "    }\n"
7159       in
7160       List.iter (generate_test_command_call test_name) seq;
7161       generate_test_command_call ~test test_name last
7162   | TestOutputStruct (seq, checks) ->
7163       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7164       let seq, last = get_seq_last seq in
7165       let test () =
7166         List.iter (
7167           function
7168           | CompareWithInt (field, expected) ->
7169               pr "    if (r->%s != %d) {\n" field expected;
7170               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7171                 test_name field expected;
7172               pr "               (int) r->%s);\n" field;
7173               pr "      return -1;\n";
7174               pr "    }\n"
7175           | CompareWithIntOp (field, op, expected) ->
7176               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7177               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7178                 test_name field op expected;
7179               pr "               (int) r->%s);\n" field;
7180               pr "      return -1;\n";
7181               pr "    }\n"
7182           | CompareWithString (field, expected) ->
7183               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7184               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7185                 test_name field expected;
7186               pr "               r->%s);\n" field;
7187               pr "      return -1;\n";
7188               pr "    }\n"
7189           | CompareFieldsIntEq (field1, field2) ->
7190               pr "    if (r->%s != r->%s) {\n" field1 field2;
7191               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7192                 test_name field1 field2;
7193               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7194               pr "      return -1;\n";
7195               pr "    }\n"
7196           | CompareFieldsStrEq (field1, field2) ->
7197               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7198               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7199                 test_name field1 field2;
7200               pr "               r->%s, r->%s);\n" field1 field2;
7201               pr "      return -1;\n";
7202               pr "    }\n"
7203         ) checks
7204       in
7205       List.iter (generate_test_command_call test_name) seq;
7206       generate_test_command_call ~test test_name last
7207   | TestLastFail seq ->
7208       pr "  /* TestLastFail for %s (%d) */\n" name i;
7209       let seq, last = get_seq_last seq in
7210       List.iter (generate_test_command_call test_name) seq;
7211       generate_test_command_call test_name ~expect_error:true last
7212
7213 (* Generate the code to run a command, leaving the result in 'r'.
7214  * If you expect to get an error then you should set expect_error:true.
7215  *)
7216 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7217   match cmd with
7218   | [] -> assert false
7219   | name :: args ->
7220       (* Look up the command to find out what args/ret it has. *)
7221       let style =
7222         try
7223           let _, style, _, _, _, _, _ =
7224             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7225           style
7226         with Not_found ->
7227           failwithf "%s: in test, command %s was not found" test_name name in
7228
7229       if List.length (snd style) <> List.length args then
7230         failwithf "%s: in test, wrong number of args given to %s"
7231           test_name name;
7232
7233       pr "  {\n";
7234
7235       List.iter (
7236         function
7237         | OptString n, "NULL" -> ()
7238         | Pathname n, arg
7239         | Device n, arg
7240         | Dev_or_Path n, arg
7241         | String n, arg
7242         | OptString n, arg ->
7243             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7244         | BufferIn n, arg ->
7245             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7246             pr "    size_t %s_size = %d;\n" n (String.length arg)
7247         | Int _, _
7248         | Int64 _, _
7249         | Bool _, _
7250         | FileIn _, _ | FileOut _, _ -> ()
7251         | StringList n, "" | DeviceList n, "" ->
7252             pr "    const char *const %s[1] = { NULL };\n" n
7253         | StringList n, arg | DeviceList n, arg ->
7254             let strs = string_split " " arg in
7255             iteri (
7256               fun i str ->
7257                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7258             ) strs;
7259             pr "    const char *const %s[] = {\n" n;
7260             iteri (
7261               fun i _ -> pr "      %s_%d,\n" n i
7262             ) strs;
7263             pr "      NULL\n";
7264             pr "    };\n";
7265       ) (List.combine (snd style) args);
7266
7267       let error_code =
7268         match fst style with
7269         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7270         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7271         | RConstString _ | RConstOptString _ ->
7272             pr "    const char *r;\n"; "NULL"
7273         | RString _ -> pr "    char *r;\n"; "NULL"
7274         | RStringList _ | RHashtable _ ->
7275             pr "    char **r;\n";
7276             pr "    int i;\n";
7277             "NULL"
7278         | RStruct (_, typ) ->
7279             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7280         | RStructList (_, typ) ->
7281             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7282         | RBufferOut _ ->
7283             pr "    char *r;\n";
7284             pr "    size_t size;\n";
7285             "NULL" in
7286
7287       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7288       pr "    r = guestfs_%s (g" name;
7289
7290       (* Generate the parameters. *)
7291       List.iter (
7292         function
7293         | OptString _, "NULL" -> pr ", NULL"
7294         | Pathname n, _
7295         | Device n, _ | Dev_or_Path n, _
7296         | String n, _
7297         | OptString n, _ ->
7298             pr ", %s" n
7299         | BufferIn n, _ ->
7300             pr ", %s, %s_size" n n
7301         | FileIn _, arg | FileOut _, arg ->
7302             pr ", \"%s\"" (c_quote arg)
7303         | StringList n, _ | DeviceList n, _ ->
7304             pr ", (char **) %s" n
7305         | Int _, arg ->
7306             let i =
7307               try int_of_string arg
7308               with Failure "int_of_string" ->
7309                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7310             pr ", %d" i
7311         | Int64 _, arg ->
7312             let i =
7313               try Int64.of_string arg
7314               with Failure "int_of_string" ->
7315                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7316             pr ", %Ld" i
7317         | Bool _, arg ->
7318             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7319       ) (List.combine (snd style) args);
7320
7321       (match fst style with
7322        | RBufferOut _ -> pr ", &size"
7323        | _ -> ()
7324       );
7325
7326       pr ");\n";
7327
7328       if not expect_error then
7329         pr "    if (r == %s)\n" error_code
7330       else
7331         pr "    if (r != %s)\n" error_code;
7332       pr "      return -1;\n";
7333
7334       (* Insert the test code. *)
7335       (match test with
7336        | None -> ()
7337        | Some f -> f ()
7338       );
7339
7340       (match fst style with
7341        | RErr | RInt _ | RInt64 _ | RBool _
7342        | RConstString _ | RConstOptString _ -> ()
7343        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7344        | RStringList _ | RHashtable _ ->
7345            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7346            pr "      free (r[i]);\n";
7347            pr "    free (r);\n"
7348        | RStruct (_, typ) ->
7349            pr "    guestfs_free_%s (r);\n" typ
7350        | RStructList (_, typ) ->
7351            pr "    guestfs_free_%s_list (r);\n" typ
7352       );
7353
7354       pr "  }\n"
7355
7356 and c_quote str =
7357   let str = replace_str str "\r" "\\r" in
7358   let str = replace_str str "\n" "\\n" in
7359   let str = replace_str str "\t" "\\t" in
7360   let str = replace_str str "\000" "\\0" in
7361   str
7362
7363 (* Generate a lot of different functions for guestfish. *)
7364 and generate_fish_cmds () =
7365   generate_header CStyle GPLv2plus;
7366
7367   let all_functions =
7368     List.filter (
7369       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7370     ) all_functions in
7371   let all_functions_sorted =
7372     List.filter (
7373       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7374     ) all_functions_sorted in
7375
7376   pr "#include <config.h>\n";
7377   pr "\n";
7378   pr "#include <stdio.h>\n";
7379   pr "#include <stdlib.h>\n";
7380   pr "#include <string.h>\n";
7381   pr "#include <inttypes.h>\n";
7382   pr "\n";
7383   pr "#include <guestfs.h>\n";
7384   pr "#include \"c-ctype.h\"\n";
7385   pr "#include \"full-write.h\"\n";
7386   pr "#include \"xstrtol.h\"\n";
7387   pr "#include \"fish.h\"\n";
7388   pr "\n";
7389
7390   (* list_commands function, which implements guestfish -h *)
7391   pr "void list_commands (void)\n";
7392   pr "{\n";
7393   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7394   pr "  list_builtin_commands ();\n";
7395   List.iter (
7396     fun (name, _, _, flags, _, shortdesc, _) ->
7397       let name = replace_char name '_' '-' in
7398       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7399         name shortdesc
7400   ) all_functions_sorted;
7401   pr "  printf (\"    %%s\\n\",";
7402   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7403   pr "}\n";
7404   pr "\n";
7405
7406   (* display_command function, which implements guestfish -h cmd *)
7407   pr "void display_command (const char *cmd)\n";
7408   pr "{\n";
7409   List.iter (
7410     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7411       let name2 = replace_char name '_' '-' in
7412       let alias =
7413         try find_map (function FishAlias n -> Some n | _ -> None) flags
7414         with Not_found -> name in
7415       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7416       let synopsis =
7417         match snd style with
7418         | [] -> name2
7419         | args ->
7420             sprintf "%s %s"
7421               name2 (String.concat " " (List.map name_of_argt args)) in
7422
7423       let warnings =
7424         if List.mem ProtocolLimitWarning flags then
7425           ("\n\n" ^ protocol_limit_warning)
7426         else "" in
7427
7428       (* For DangerWillRobinson commands, we should probably have
7429        * guestfish prompt before allowing you to use them (especially
7430        * in interactive mode). XXX
7431        *)
7432       let warnings =
7433         warnings ^
7434           if List.mem DangerWillRobinson flags then
7435             ("\n\n" ^ danger_will_robinson)
7436           else "" in
7437
7438       let warnings =
7439         warnings ^
7440           match deprecation_notice flags with
7441           | None -> ""
7442           | Some txt -> "\n\n" ^ txt in
7443
7444       let describe_alias =
7445         if name <> alias then
7446           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7447         else "" in
7448
7449       pr "  if (";
7450       pr "STRCASEEQ (cmd, \"%s\")" name;
7451       if name <> name2 then
7452         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7453       if name <> alias then
7454         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7455       pr ")\n";
7456       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7457         name2 shortdesc
7458         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7459          "=head1 DESCRIPTION\n\n" ^
7460          longdesc ^ warnings ^ describe_alias);
7461       pr "  else\n"
7462   ) all_functions;
7463   pr "    display_builtin_command (cmd);\n";
7464   pr "}\n";
7465   pr "\n";
7466
7467   let emit_print_list_function typ =
7468     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7469       typ typ typ;
7470     pr "{\n";
7471     pr "  unsigned int i;\n";
7472     pr "\n";
7473     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7474     pr "    printf (\"[%%d] = {\\n\", i);\n";
7475     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7476     pr "    printf (\"}\\n\");\n";
7477     pr "  }\n";
7478     pr "}\n";
7479     pr "\n";
7480   in
7481
7482   (* print_* functions *)
7483   List.iter (
7484     fun (typ, cols) ->
7485       let needs_i =
7486         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7487
7488       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7489       pr "{\n";
7490       if needs_i then (
7491         pr "  unsigned int i;\n";
7492         pr "\n"
7493       );
7494       List.iter (
7495         function
7496         | name, FString ->
7497             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7498         | name, FUUID ->
7499             pr "  printf (\"%%s%s: \", indent);\n" name;
7500             pr "  for (i = 0; i < 32; ++i)\n";
7501             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7502             pr "  printf (\"\\n\");\n"
7503         | name, FBuffer ->
7504             pr "  printf (\"%%s%s: \", indent);\n" name;
7505             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7506             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7507             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7508             pr "    else\n";
7509             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7510             pr "  printf (\"\\n\");\n"
7511         | name, (FUInt64|FBytes) ->
7512             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7513               name typ name
7514         | name, FInt64 ->
7515             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7516               name typ name
7517         | name, FUInt32 ->
7518             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7519               name typ name
7520         | name, FInt32 ->
7521             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7522               name typ name
7523         | name, FChar ->
7524             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7525               name typ name
7526         | name, FOptPercent ->
7527             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7528               typ name name typ name;
7529             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7530       ) cols;
7531       pr "}\n";
7532       pr "\n";
7533   ) structs;
7534
7535   (* Emit a print_TYPE_list function definition only if that function is used. *)
7536   List.iter (
7537     function
7538     | typ, (RStructListOnly | RStructAndList) ->
7539         (* generate the function for typ *)
7540         emit_print_list_function typ
7541     | typ, _ -> () (* empty *)
7542   ) (rstructs_used_by all_functions);
7543
7544   (* Emit a print_TYPE function definition only if that function is used. *)
7545   List.iter (
7546     function
7547     | typ, (RStructOnly | RStructAndList) ->
7548         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7549         pr "{\n";
7550         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7551         pr "}\n";
7552         pr "\n";
7553     | typ, _ -> () (* empty *)
7554   ) (rstructs_used_by all_functions);
7555
7556   (* run_<action> actions *)
7557   List.iter (
7558     fun (name, style, _, flags, _, _, _) ->
7559       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7560       pr "{\n";
7561       (match fst style with
7562        | RErr
7563        | RInt _
7564        | RBool _ -> pr "  int r;\n"
7565        | RInt64 _ -> pr "  int64_t r;\n"
7566        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7567        | RString _ -> pr "  char *r;\n"
7568        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7569        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7570        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7571        | RBufferOut _ ->
7572            pr "  char *r;\n";
7573            pr "  size_t size;\n";
7574       );
7575       List.iter (
7576         function
7577         | Device n
7578         | String n
7579         | OptString n -> pr "  const char *%s;\n" n
7580         | Pathname n
7581         | Dev_or_Path n
7582         | FileIn n
7583         | FileOut n -> pr "  char *%s;\n" n
7584         | BufferIn n ->
7585             pr "  const char *%s;\n" n;
7586             pr "  size_t %s_size;\n" n
7587         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7588         | Bool n -> pr "  int %s;\n" n
7589         | Int n -> pr "  int %s;\n" n
7590         | Int64 n -> pr "  int64_t %s;\n" n
7591       ) (snd style);
7592
7593       (* Check and convert parameters. *)
7594       let argc_expected = List.length (snd style) in
7595       pr "  if (argc != %d) {\n" argc_expected;
7596       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7597         argc_expected;
7598       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7599       pr "    return -1;\n";
7600       pr "  }\n";
7601
7602       let parse_integer fn fntyp rtyp range name i =
7603         pr "  {\n";
7604         pr "    strtol_error xerr;\n";
7605         pr "    %s r;\n" fntyp;
7606         pr "\n";
7607         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7608         pr "    if (xerr != LONGINT_OK) {\n";
7609         pr "      fprintf (stderr,\n";
7610         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7611         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7612         pr "      return -1;\n";
7613         pr "    }\n";
7614         (match range with
7615          | None -> ()
7616          | Some (min, max, comment) ->
7617              pr "    /* %s */\n" comment;
7618              pr "    if (r < %s || r > %s) {\n" min max;
7619              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7620                name;
7621              pr "      return -1;\n";
7622              pr "    }\n";
7623              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7624         );
7625         pr "    %s = r;\n" name;
7626         pr "  }\n";
7627       in
7628
7629       iteri (
7630         fun i ->
7631           function
7632           | Device name
7633           | String name ->
7634               pr "  %s = argv[%d];\n" name i
7635           | Pathname name
7636           | Dev_or_Path name ->
7637               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7638               pr "  if (%s == NULL) return -1;\n" name
7639           | OptString name ->
7640               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7641                 name i i
7642           | BufferIn name ->
7643               pr "  %s = argv[%d];\n" name i;
7644               pr "  %s_size = strlen (argv[%d]);\n" name i
7645           | FileIn name ->
7646               pr "  %s = file_in (argv[%d]);\n" name i;
7647               pr "  if (%s == NULL) return -1;\n" name
7648           | FileOut name ->
7649               pr "  %s = file_out (argv[%d]);\n" name i;
7650               pr "  if (%s == NULL) return -1;\n" name
7651           | StringList name | DeviceList name ->
7652               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7653               pr "  if (%s == NULL) return -1;\n" name;
7654           | Bool name ->
7655               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7656           | Int name ->
7657               let range =
7658                 let min = "(-(2LL<<30))"
7659                 and max = "((2LL<<30)-1)"
7660                 and comment =
7661                   "The Int type in the generator is a signed 31 bit int." in
7662                 Some (min, max, comment) in
7663               parse_integer "xstrtoll" "long long" "int" range name i
7664           | Int64 name ->
7665               parse_integer "xstrtoll" "long long" "int64_t" None name i
7666       ) (snd style);
7667
7668       (* Call C API function. *)
7669       pr "  r = guestfs_%s " name;
7670       generate_c_call_args ~handle:"g" style;
7671       pr ";\n";
7672
7673       List.iter (
7674         function
7675         | Device name | String name
7676         | OptString name | Bool name
7677         | Int name | Int64 name
7678         | BufferIn name -> ()
7679         | Pathname name | Dev_or_Path name | FileOut name ->
7680             pr "  free (%s);\n" name
7681         | FileIn name ->
7682             pr "  free_file_in (%s);\n" name
7683         | StringList name | DeviceList name ->
7684             pr "  free_strings (%s);\n" name
7685       ) (snd style);
7686
7687       (* Any output flags? *)
7688       let fish_output =
7689         let flags = filter_map (
7690           function FishOutput flag -> Some flag | _ -> None
7691         ) flags in
7692         match flags with
7693         | [] -> None
7694         | [f] -> Some f
7695         | _ ->
7696             failwithf "%s: more than one FishOutput flag is not allowed" name in
7697
7698       (* Check return value for errors and display command results. *)
7699       (match fst style with
7700        | RErr -> pr "  return r;\n"
7701        | RInt _ ->
7702            pr "  if (r == -1) return -1;\n";
7703            (match fish_output with
7704             | None ->
7705                 pr "  printf (\"%%d\\n\", r);\n";
7706             | Some FishOutputOctal ->
7707                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7708             | Some FishOutputHexadecimal ->
7709                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7710            pr "  return 0;\n"
7711        | RInt64 _ ->
7712            pr "  if (r == -1) return -1;\n";
7713            (match fish_output with
7714             | None ->
7715                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7716             | Some FishOutputOctal ->
7717                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7718             | Some FishOutputHexadecimal ->
7719                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7720            pr "  return 0;\n"
7721        | RBool _ ->
7722            pr "  if (r == -1) return -1;\n";
7723            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7724            pr "  return 0;\n"
7725        | RConstString _ ->
7726            pr "  if (r == NULL) return -1;\n";
7727            pr "  printf (\"%%s\\n\", r);\n";
7728            pr "  return 0;\n"
7729        | RConstOptString _ ->
7730            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7731            pr "  return 0;\n"
7732        | RString _ ->
7733            pr "  if (r == NULL) return -1;\n";
7734            pr "  printf (\"%%s\\n\", r);\n";
7735            pr "  free (r);\n";
7736            pr "  return 0;\n"
7737        | RStringList _ ->
7738            pr "  if (r == NULL) return -1;\n";
7739            pr "  print_strings (r);\n";
7740            pr "  free_strings (r);\n";
7741            pr "  return 0;\n"
7742        | RStruct (_, typ) ->
7743            pr "  if (r == NULL) return -1;\n";
7744            pr "  print_%s (r);\n" typ;
7745            pr "  guestfs_free_%s (r);\n" typ;
7746            pr "  return 0;\n"
7747        | RStructList (_, typ) ->
7748            pr "  if (r == NULL) return -1;\n";
7749            pr "  print_%s_list (r);\n" typ;
7750            pr "  guestfs_free_%s_list (r);\n" typ;
7751            pr "  return 0;\n"
7752        | RHashtable _ ->
7753            pr "  if (r == NULL) return -1;\n";
7754            pr "  print_table (r);\n";
7755            pr "  free_strings (r);\n";
7756            pr "  return 0;\n"
7757        | RBufferOut _ ->
7758            pr "  if (r == NULL) return -1;\n";
7759            pr "  if (full_write (1, r, size) != size) {\n";
7760            pr "    perror (\"write\");\n";
7761            pr "    free (r);\n";
7762            pr "    return -1;\n";
7763            pr "  }\n";
7764            pr "  free (r);\n";
7765            pr "  return 0;\n"
7766       );
7767       pr "}\n";
7768       pr "\n"
7769   ) all_functions;
7770
7771   (* run_action function *)
7772   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7773   pr "{\n";
7774   List.iter (
7775     fun (name, _, _, flags, _, _, _) ->
7776       let name2 = replace_char name '_' '-' in
7777       let alias =
7778         try find_map (function FishAlias n -> Some n | _ -> None) flags
7779         with Not_found -> name in
7780       pr "  if (";
7781       pr "STRCASEEQ (cmd, \"%s\")" name;
7782       if name <> name2 then
7783         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7784       if name <> alias then
7785         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7786       pr ")\n";
7787       pr "    return run_%s (cmd, argc, argv);\n" name;
7788       pr "  else\n";
7789   ) all_functions;
7790   pr "    {\n";
7791   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7792   pr "      if (command_num == 1)\n";
7793   pr "        extended_help_message ();\n";
7794   pr "      return -1;\n";
7795   pr "    }\n";
7796   pr "  return 0;\n";
7797   pr "}\n";
7798   pr "\n"
7799
7800 (* Readline completion for guestfish. *)
7801 and generate_fish_completion () =
7802   generate_header CStyle GPLv2plus;
7803
7804   let all_functions =
7805     List.filter (
7806       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7807     ) all_functions in
7808
7809   pr "\
7810 #include <config.h>
7811
7812 #include <stdio.h>
7813 #include <stdlib.h>
7814 #include <string.h>
7815
7816 #ifdef HAVE_LIBREADLINE
7817 #include <readline/readline.h>
7818 #endif
7819
7820 #include \"fish.h\"
7821
7822 #ifdef HAVE_LIBREADLINE
7823
7824 static const char *const commands[] = {
7825   BUILTIN_COMMANDS_FOR_COMPLETION,
7826 ";
7827
7828   (* Get the commands, including the aliases.  They don't need to be
7829    * sorted - the generator() function just does a dumb linear search.
7830    *)
7831   let commands =
7832     List.map (
7833       fun (name, _, _, flags, _, _, _) ->
7834         let name2 = replace_char name '_' '-' in
7835         let alias =
7836           try find_map (function FishAlias n -> Some n | _ -> None) flags
7837           with Not_found -> name in
7838
7839         if name <> alias then [name2; alias] else [name2]
7840     ) all_functions in
7841   let commands = List.flatten commands in
7842
7843   List.iter (pr "  \"%s\",\n") commands;
7844
7845   pr "  NULL
7846 };
7847
7848 static char *
7849 generator (const char *text, int state)
7850 {
7851   static int index, len;
7852   const char *name;
7853
7854   if (!state) {
7855     index = 0;
7856     len = strlen (text);
7857   }
7858
7859   rl_attempted_completion_over = 1;
7860
7861   while ((name = commands[index]) != NULL) {
7862     index++;
7863     if (STRCASEEQLEN (name, text, len))
7864       return strdup (name);
7865   }
7866
7867   return NULL;
7868 }
7869
7870 #endif /* HAVE_LIBREADLINE */
7871
7872 #ifdef HAVE_RL_COMPLETION_MATCHES
7873 #define RL_COMPLETION_MATCHES rl_completion_matches
7874 #else
7875 #ifdef HAVE_COMPLETION_MATCHES
7876 #define RL_COMPLETION_MATCHES completion_matches
7877 #endif
7878 #endif /* else just fail if we don't have either symbol */
7879
7880 char **
7881 do_completion (const char *text, int start, int end)
7882 {
7883   char **matches = NULL;
7884
7885 #ifdef HAVE_LIBREADLINE
7886   rl_completion_append_character = ' ';
7887
7888   if (start == 0)
7889     matches = RL_COMPLETION_MATCHES (text, generator);
7890   else if (complete_dest_paths)
7891     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7892 #endif
7893
7894   return matches;
7895 }
7896 ";
7897
7898 (* Generate the POD documentation for guestfish. *)
7899 and generate_fish_actions_pod () =
7900   let all_functions_sorted =
7901     List.filter (
7902       fun (_, _, _, flags, _, _, _) ->
7903         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7904     ) all_functions_sorted in
7905
7906   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7907
7908   List.iter (
7909     fun (name, style, _, flags, _, _, longdesc) ->
7910       let longdesc =
7911         Str.global_substitute rex (
7912           fun s ->
7913             let sub =
7914               try Str.matched_group 1 s
7915               with Not_found ->
7916                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7917             "C<" ^ replace_char sub '_' '-' ^ ">"
7918         ) longdesc in
7919       let name = replace_char name '_' '-' in
7920       let alias =
7921         try find_map (function FishAlias n -> Some n | _ -> None) flags
7922         with Not_found -> name in
7923
7924       pr "=head2 %s" name;
7925       if name <> alias then
7926         pr " | %s" alias;
7927       pr "\n";
7928       pr "\n";
7929       pr " %s" name;
7930       List.iter (
7931         function
7932         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7933         | OptString n -> pr " %s" n
7934         | StringList n | DeviceList n -> pr " '%s ...'" n
7935         | Bool _ -> pr " true|false"
7936         | Int n -> pr " %s" n
7937         | Int64 n -> pr " %s" n
7938         | FileIn n | FileOut n -> pr " (%s|-)" n
7939         | BufferIn n -> pr " %s" n
7940       ) (snd style);
7941       pr "\n";
7942       pr "\n";
7943       pr "%s\n\n" longdesc;
7944
7945       if List.exists (function FileIn _ | FileOut _ -> true
7946                       | _ -> false) (snd style) then
7947         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7948
7949       if List.mem ProtocolLimitWarning flags then
7950         pr "%s\n\n" protocol_limit_warning;
7951
7952       if List.mem DangerWillRobinson flags then
7953         pr "%s\n\n" danger_will_robinson;
7954
7955       match deprecation_notice flags with
7956       | None -> ()
7957       | Some txt -> pr "%s\n\n" txt
7958   ) all_functions_sorted
7959
7960 (* Generate a C function prototype. *)
7961 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7962     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7963     ?(prefix = "")
7964     ?handle name style =
7965   if extern then pr "extern ";
7966   if static then pr "static ";
7967   (match fst style with
7968    | RErr -> pr "int "
7969    | RInt _ -> pr "int "
7970    | RInt64 _ -> pr "int64_t "
7971    | RBool _ -> pr "int "
7972    | RConstString _ | RConstOptString _ -> pr "const char *"
7973    | RString _ | RBufferOut _ -> pr "char *"
7974    | RStringList _ | RHashtable _ -> pr "char **"
7975    | RStruct (_, typ) ->
7976        if not in_daemon then pr "struct guestfs_%s *" typ
7977        else pr "guestfs_int_%s *" typ
7978    | RStructList (_, typ) ->
7979        if not in_daemon then pr "struct guestfs_%s_list *" typ
7980        else pr "guestfs_int_%s_list *" typ
7981   );
7982   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7983   pr "%s%s (" prefix name;
7984   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7985     pr "void"
7986   else (
7987     let comma = ref false in
7988     (match handle with
7989      | None -> ()
7990      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7991     );
7992     let next () =
7993       if !comma then (
7994         if single_line then pr ", " else pr ",\n\t\t"
7995       );
7996       comma := true
7997     in
7998     List.iter (
7999       function
8000       | Pathname n
8001       | Device n | Dev_or_Path n
8002       | String n
8003       | OptString n ->
8004           next ();
8005           pr "const char *%s" n
8006       | StringList n | DeviceList n ->
8007           next ();
8008           pr "char *const *%s" n
8009       | Bool n -> next (); pr "int %s" n
8010       | Int n -> next (); pr "int %s" n
8011       | Int64 n -> next (); pr "int64_t %s" n
8012       | FileIn n
8013       | FileOut n ->
8014           if not in_daemon then (next (); pr "const char *%s" n)
8015       | BufferIn n ->
8016           next ();
8017           pr "const char *%s" n;
8018           next ();
8019           pr "size_t %s_size" n
8020     ) (snd style);
8021     if is_RBufferOut then (next (); pr "size_t *size_r");
8022   );
8023   pr ")";
8024   if semicolon then pr ";";
8025   if newline then pr "\n"
8026
8027 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8028 and generate_c_call_args ?handle ?(decl = false) style =
8029   pr "(";
8030   let comma = ref false in
8031   let next () =
8032     if !comma then pr ", ";
8033     comma := true
8034   in
8035   (match handle with
8036    | None -> ()
8037    | Some handle -> pr "%s" handle; comma := true
8038   );
8039   List.iter (
8040     function
8041     | BufferIn n ->
8042         next ();
8043         pr "%s, %s_size" n n
8044     | arg ->
8045         next ();
8046         pr "%s" (name_of_argt arg)
8047   ) (snd style);
8048   (* For RBufferOut calls, add implicit &size parameter. *)
8049   if not decl then (
8050     match fst style with
8051     | RBufferOut _ ->
8052         next ();
8053         pr "&size"
8054     | _ -> ()
8055   );
8056   pr ")"
8057
8058 (* Generate the OCaml bindings interface. *)
8059 and generate_ocaml_mli () =
8060   generate_header OCamlStyle LGPLv2plus;
8061
8062   pr "\
8063 (** For API documentation you should refer to the C API
8064     in the guestfs(3) manual page.  The OCaml API uses almost
8065     exactly the same calls. *)
8066
8067 type t
8068 (** A [guestfs_h] handle. *)
8069
8070 exception Error of string
8071 (** This exception is raised when there is an error. *)
8072
8073 exception Handle_closed of string
8074 (** This exception is raised if you use a {!Guestfs.t} handle
8075     after calling {!close} on it.  The string is the name of
8076     the function. *)
8077
8078 val create : unit -> t
8079 (** Create a {!Guestfs.t} handle. *)
8080
8081 val close : t -> unit
8082 (** Close the {!Guestfs.t} handle and free up all resources used
8083     by it immediately.
8084
8085     Handles are closed by the garbage collector when they become
8086     unreferenced, but callers can call this in order to provide
8087     predictable cleanup. *)
8088
8089 ";
8090   generate_ocaml_structure_decls ();
8091
8092   (* The actions. *)
8093   List.iter (
8094     fun (name, style, _, _, _, shortdesc, _) ->
8095       generate_ocaml_prototype name style;
8096       pr "(** %s *)\n" shortdesc;
8097       pr "\n"
8098   ) all_functions_sorted
8099
8100 (* Generate the OCaml bindings implementation. *)
8101 and generate_ocaml_ml () =
8102   generate_header OCamlStyle LGPLv2plus;
8103
8104   pr "\
8105 type t
8106
8107 exception Error of string
8108 exception Handle_closed of string
8109
8110 external create : unit -> t = \"ocaml_guestfs_create\"
8111 external close : t -> unit = \"ocaml_guestfs_close\"
8112
8113 (* Give the exceptions names, so they can be raised from the C code. *)
8114 let () =
8115   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8116   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8117
8118 ";
8119
8120   generate_ocaml_structure_decls ();
8121
8122   (* The actions. *)
8123   List.iter (
8124     fun (name, style, _, _, _, shortdesc, _) ->
8125       generate_ocaml_prototype ~is_external:true name style;
8126   ) all_functions_sorted
8127
8128 (* Generate the OCaml bindings C implementation. *)
8129 and generate_ocaml_c () =
8130   generate_header CStyle LGPLv2plus;
8131
8132   pr "\
8133 #include <stdio.h>
8134 #include <stdlib.h>
8135 #include <string.h>
8136
8137 #include <caml/config.h>
8138 #include <caml/alloc.h>
8139 #include <caml/callback.h>
8140 #include <caml/fail.h>
8141 #include <caml/memory.h>
8142 #include <caml/mlvalues.h>
8143 #include <caml/signals.h>
8144
8145 #include <guestfs.h>
8146
8147 #include \"guestfs_c.h\"
8148
8149 /* Copy a hashtable of string pairs into an assoc-list.  We return
8150  * the list in reverse order, but hashtables aren't supposed to be
8151  * ordered anyway.
8152  */
8153 static CAMLprim value
8154 copy_table (char * const * argv)
8155 {
8156   CAMLparam0 ();
8157   CAMLlocal5 (rv, pairv, kv, vv, cons);
8158   int i;
8159
8160   rv = Val_int (0);
8161   for (i = 0; argv[i] != NULL; i += 2) {
8162     kv = caml_copy_string (argv[i]);
8163     vv = caml_copy_string (argv[i+1]);
8164     pairv = caml_alloc (2, 0);
8165     Store_field (pairv, 0, kv);
8166     Store_field (pairv, 1, vv);
8167     cons = caml_alloc (2, 0);
8168     Store_field (cons, 1, rv);
8169     rv = cons;
8170     Store_field (cons, 0, pairv);
8171   }
8172
8173   CAMLreturn (rv);
8174 }
8175
8176 ";
8177
8178   (* Struct copy functions. *)
8179
8180   let emit_ocaml_copy_list_function typ =
8181     pr "static CAMLprim value\n";
8182     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8183     pr "{\n";
8184     pr "  CAMLparam0 ();\n";
8185     pr "  CAMLlocal2 (rv, v);\n";
8186     pr "  unsigned int i;\n";
8187     pr "\n";
8188     pr "  if (%ss->len == 0)\n" typ;
8189     pr "    CAMLreturn (Atom (0));\n";
8190     pr "  else {\n";
8191     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8192     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8193     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8194     pr "      caml_modify (&Field (rv, i), v);\n";
8195     pr "    }\n";
8196     pr "    CAMLreturn (rv);\n";
8197     pr "  }\n";
8198     pr "}\n";
8199     pr "\n";
8200   in
8201
8202   List.iter (
8203     fun (typ, cols) ->
8204       let has_optpercent_col =
8205         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8206
8207       pr "static CAMLprim value\n";
8208       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8209       pr "{\n";
8210       pr "  CAMLparam0 ();\n";
8211       if has_optpercent_col then
8212         pr "  CAMLlocal3 (rv, v, v2);\n"
8213       else
8214         pr "  CAMLlocal2 (rv, v);\n";
8215       pr "\n";
8216       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8217       iteri (
8218         fun i col ->
8219           (match col with
8220            | name, FString ->
8221                pr "  v = caml_copy_string (%s->%s);\n" typ name
8222            | name, FBuffer ->
8223                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8224                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8225                  typ name typ name
8226            | name, FUUID ->
8227                pr "  v = caml_alloc_string (32);\n";
8228                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8229            | name, (FBytes|FInt64|FUInt64) ->
8230                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8231            | name, (FInt32|FUInt32) ->
8232                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8233            | name, FOptPercent ->
8234                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8235                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8236                pr "    v = caml_alloc (1, 0);\n";
8237                pr "    Store_field (v, 0, v2);\n";
8238                pr "  } else /* None */\n";
8239                pr "    v = Val_int (0);\n";
8240            | name, FChar ->
8241                pr "  v = Val_int (%s->%s);\n" typ name
8242           );
8243           pr "  Store_field (rv, %d, v);\n" i
8244       ) cols;
8245       pr "  CAMLreturn (rv);\n";
8246       pr "}\n";
8247       pr "\n";
8248   ) structs;
8249
8250   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8251   List.iter (
8252     function
8253     | typ, (RStructListOnly | RStructAndList) ->
8254         (* generate the function for typ *)
8255         emit_ocaml_copy_list_function typ
8256     | typ, _ -> () (* empty *)
8257   ) (rstructs_used_by all_functions);
8258
8259   (* The wrappers. *)
8260   List.iter (
8261     fun (name, style, _, _, _, _, _) ->
8262       pr "/* Automatically generated wrapper for function\n";
8263       pr " * ";
8264       generate_ocaml_prototype name style;
8265       pr " */\n";
8266       pr "\n";
8267
8268       let params =
8269         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8270
8271       let needs_extra_vs =
8272         match fst style with RConstOptString _ -> true | _ -> false in
8273
8274       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8275       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8276       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8277       pr "\n";
8278
8279       pr "CAMLprim value\n";
8280       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8281       List.iter (pr ", value %s") (List.tl params);
8282       pr ")\n";
8283       pr "{\n";
8284
8285       (match params with
8286        | [p1; p2; p3; p4; p5] ->
8287            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8288        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8289            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8290            pr "  CAMLxparam%d (%s);\n"
8291              (List.length rest) (String.concat ", " rest)
8292        | ps ->
8293            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8294       );
8295       if not needs_extra_vs then
8296         pr "  CAMLlocal1 (rv);\n"
8297       else
8298         pr "  CAMLlocal3 (rv, v, v2);\n";
8299       pr "\n";
8300
8301       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8302       pr "  if (g == NULL)\n";
8303       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8304       pr "\n";
8305
8306       List.iter (
8307         function
8308         | Pathname n
8309         | Device n | Dev_or_Path n
8310         | String n
8311         | FileIn n
8312         | FileOut n ->
8313             pr "  const char *%s = String_val (%sv);\n" n n
8314         | OptString n ->
8315             pr "  const char *%s =\n" n;
8316             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8317               n n
8318         | BufferIn n ->
8319             pr "  const char *%s = String_val (%sv);\n" n n;
8320             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8321         | StringList n | DeviceList n ->
8322             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8323         | Bool n ->
8324             pr "  int %s = Bool_val (%sv);\n" n n
8325         | Int n ->
8326             pr "  int %s = Int_val (%sv);\n" n n
8327         | Int64 n ->
8328             pr "  int64_t %s = Int64_val (%sv);\n" n n
8329       ) (snd style);
8330       let error_code =
8331         match fst style with
8332         | RErr -> pr "  int r;\n"; "-1"
8333         | RInt _ -> pr "  int r;\n"; "-1"
8334         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8335         | RBool _ -> pr "  int r;\n"; "-1"
8336         | RConstString _ | RConstOptString _ ->
8337             pr "  const char *r;\n"; "NULL"
8338         | RString _ -> pr "  char *r;\n"; "NULL"
8339         | RStringList _ ->
8340             pr "  int i;\n";
8341             pr "  char **r;\n";
8342             "NULL"
8343         | RStruct (_, typ) ->
8344             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8345         | RStructList (_, typ) ->
8346             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8347         | RHashtable _ ->
8348             pr "  int i;\n";
8349             pr "  char **r;\n";
8350             "NULL"
8351         | RBufferOut _ ->
8352             pr "  char *r;\n";
8353             pr "  size_t size;\n";
8354             "NULL" in
8355       pr "\n";
8356
8357       pr "  caml_enter_blocking_section ();\n";
8358       pr "  r = guestfs_%s " name;
8359       generate_c_call_args ~handle:"g" style;
8360       pr ";\n";
8361       pr "  caml_leave_blocking_section ();\n";
8362
8363       List.iter (
8364         function
8365         | StringList n | DeviceList n ->
8366             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8367         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8368         | Bool _ | Int _ | Int64 _
8369         | FileIn _ | FileOut _ | BufferIn _ -> ()
8370       ) (snd style);
8371
8372       pr "  if (r == %s)\n" error_code;
8373       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8374       pr "\n";
8375
8376       (match fst style with
8377        | RErr -> pr "  rv = Val_unit;\n"
8378        | RInt _ -> pr "  rv = Val_int (r);\n"
8379        | RInt64 _ ->
8380            pr "  rv = caml_copy_int64 (r);\n"
8381        | RBool _ -> pr "  rv = Val_bool (r);\n"
8382        | RConstString _ ->
8383            pr "  rv = caml_copy_string (r);\n"
8384        | RConstOptString _ ->
8385            pr "  if (r) { /* Some string */\n";
8386            pr "    v = caml_alloc (1, 0);\n";
8387            pr "    v2 = caml_copy_string (r);\n";
8388            pr "    Store_field (v, 0, v2);\n";
8389            pr "  } else /* None */\n";
8390            pr "    v = Val_int (0);\n";
8391        | RString _ ->
8392            pr "  rv = caml_copy_string (r);\n";
8393            pr "  free (r);\n"
8394        | RStringList _ ->
8395            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8396            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8397            pr "  free (r);\n"
8398        | RStruct (_, typ) ->
8399            pr "  rv = copy_%s (r);\n" typ;
8400            pr "  guestfs_free_%s (r);\n" typ;
8401        | RStructList (_, typ) ->
8402            pr "  rv = copy_%s_list (r);\n" typ;
8403            pr "  guestfs_free_%s_list (r);\n" typ;
8404        | RHashtable _ ->
8405            pr "  rv = copy_table (r);\n";
8406            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8407            pr "  free (r);\n";
8408        | RBufferOut _ ->
8409            pr "  rv = caml_alloc_string (size);\n";
8410            pr "  memcpy (String_val (rv), r, size);\n";
8411       );
8412
8413       pr "  CAMLreturn (rv);\n";
8414       pr "}\n";
8415       pr "\n";
8416
8417       if List.length params > 5 then (
8418         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8419         pr "CAMLprim value ";
8420         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8421         pr "CAMLprim value\n";
8422         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8423         pr "{\n";
8424         pr "  return ocaml_guestfs_%s (argv[0]" name;
8425         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8426         pr ");\n";
8427         pr "}\n";
8428         pr "\n"
8429       )
8430   ) all_functions_sorted
8431
8432 and generate_ocaml_structure_decls () =
8433   List.iter (
8434     fun (typ, cols) ->
8435       pr "type %s = {\n" typ;
8436       List.iter (
8437         function
8438         | name, FString -> pr "  %s : string;\n" name
8439         | name, FBuffer -> pr "  %s : string;\n" name
8440         | name, FUUID -> pr "  %s : string;\n" name
8441         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8442         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8443         | name, FChar -> pr "  %s : char;\n" name
8444         | name, FOptPercent -> pr "  %s : float option;\n" name
8445       ) cols;
8446       pr "}\n";
8447       pr "\n"
8448   ) structs
8449
8450 and generate_ocaml_prototype ?(is_external = false) name style =
8451   if is_external then pr "external " else pr "val ";
8452   pr "%s : t -> " name;
8453   List.iter (
8454     function
8455     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8456     | BufferIn _ -> pr "string -> "
8457     | OptString _ -> pr "string option -> "
8458     | StringList _ | DeviceList _ -> pr "string array -> "
8459     | Bool _ -> pr "bool -> "
8460     | Int _ -> pr "int -> "
8461     | Int64 _ -> pr "int64 -> "
8462   ) (snd style);
8463   (match fst style with
8464    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8465    | RInt _ -> pr "int"
8466    | RInt64 _ -> pr "int64"
8467    | RBool _ -> pr "bool"
8468    | RConstString _ -> pr "string"
8469    | RConstOptString _ -> pr "string option"
8470    | RString _ | RBufferOut _ -> pr "string"
8471    | RStringList _ -> pr "string array"
8472    | RStruct (_, typ) -> pr "%s" typ
8473    | RStructList (_, typ) -> pr "%s array" typ
8474    | RHashtable _ -> pr "(string * string) list"
8475   );
8476   if is_external then (
8477     pr " = ";
8478     if List.length (snd style) + 1 > 5 then
8479       pr "\"ocaml_guestfs_%s_byte\" " name;
8480     pr "\"ocaml_guestfs_%s\"" name
8481   );
8482   pr "\n"
8483
8484 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8485 and generate_perl_xs () =
8486   generate_header CStyle LGPLv2plus;
8487
8488   pr "\
8489 #include \"EXTERN.h\"
8490 #include \"perl.h\"
8491 #include \"XSUB.h\"
8492
8493 #include <guestfs.h>
8494
8495 #ifndef PRId64
8496 #define PRId64 \"lld\"
8497 #endif
8498
8499 static SV *
8500 my_newSVll(long long val) {
8501 #ifdef USE_64_BIT_ALL
8502   return newSViv(val);
8503 #else
8504   char buf[100];
8505   int len;
8506   len = snprintf(buf, 100, \"%%\" PRId64, val);
8507   return newSVpv(buf, len);
8508 #endif
8509 }
8510
8511 #ifndef PRIu64
8512 #define PRIu64 \"llu\"
8513 #endif
8514
8515 static SV *
8516 my_newSVull(unsigned long long val) {
8517 #ifdef USE_64_BIT_ALL
8518   return newSVuv(val);
8519 #else
8520   char buf[100];
8521   int len;
8522   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8523   return newSVpv(buf, len);
8524 #endif
8525 }
8526
8527 /* http://www.perlmonks.org/?node_id=680842 */
8528 static char **
8529 XS_unpack_charPtrPtr (SV *arg) {
8530   char **ret;
8531   AV *av;
8532   I32 i;
8533
8534   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8535     croak (\"array reference expected\");
8536
8537   av = (AV *)SvRV (arg);
8538   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8539   if (!ret)
8540     croak (\"malloc failed\");
8541
8542   for (i = 0; i <= av_len (av); i++) {
8543     SV **elem = av_fetch (av, i, 0);
8544
8545     if (!elem || !*elem)
8546       croak (\"missing element in list\");
8547
8548     ret[i] = SvPV_nolen (*elem);
8549   }
8550
8551   ret[i] = NULL;
8552
8553   return ret;
8554 }
8555
8556 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8557
8558 PROTOTYPES: ENABLE
8559
8560 guestfs_h *
8561 _create ()
8562    CODE:
8563       RETVAL = guestfs_create ();
8564       if (!RETVAL)
8565         croak (\"could not create guestfs handle\");
8566       guestfs_set_error_handler (RETVAL, NULL, NULL);
8567  OUTPUT:
8568       RETVAL
8569
8570 void
8571 DESTROY (g)
8572       guestfs_h *g;
8573  PPCODE:
8574       guestfs_close (g);
8575
8576 ";
8577
8578   List.iter (
8579     fun (name, style, _, _, _, _, _) ->
8580       (match fst style with
8581        | RErr -> pr "void\n"
8582        | RInt _ -> pr "SV *\n"
8583        | RInt64 _ -> pr "SV *\n"
8584        | RBool _ -> pr "SV *\n"
8585        | RConstString _ -> pr "SV *\n"
8586        | RConstOptString _ -> pr "SV *\n"
8587        | RString _ -> pr "SV *\n"
8588        | RBufferOut _ -> pr "SV *\n"
8589        | RStringList _
8590        | RStruct _ | RStructList _
8591        | RHashtable _ ->
8592            pr "void\n" (* all lists returned implictly on the stack *)
8593       );
8594       (* Call and arguments. *)
8595       pr "%s (g" name;
8596       List.iter (
8597         fun arg -> pr ", %s" (name_of_argt arg)
8598       ) (snd style);
8599       pr ")\n";
8600       pr "      guestfs_h *g;\n";
8601       iteri (
8602         fun i ->
8603           function
8604           | Pathname n | Device n | Dev_or_Path n | String n
8605           | FileIn n | FileOut n ->
8606               pr "      char *%s;\n" n
8607           | BufferIn n ->
8608               pr "      char *%s;\n" n;
8609               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8610           | OptString n ->
8611               (* http://www.perlmonks.org/?node_id=554277
8612                * Note that the implicit handle argument means we have
8613                * to add 1 to the ST(x) operator.
8614                *)
8615               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8616           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8617           | Bool n -> pr "      int %s;\n" n
8618           | Int n -> pr "      int %s;\n" n
8619           | Int64 n -> pr "      int64_t %s;\n" n
8620       ) (snd style);
8621
8622       let do_cleanups () =
8623         List.iter (
8624           function
8625           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8626           | Bool _ | Int _ | Int64 _
8627           | FileIn _ | FileOut _
8628           | BufferIn _ -> ()
8629           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8630         ) (snd style)
8631       in
8632
8633       (* Code. *)
8634       (match fst style with
8635        | RErr ->
8636            pr "PREINIT:\n";
8637            pr "      int r;\n";
8638            pr " PPCODE:\n";
8639            pr "      r = guestfs_%s " name;
8640            generate_c_call_args ~handle:"g" style;
8641            pr ";\n";
8642            do_cleanups ();
8643            pr "      if (r == -1)\n";
8644            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8645        | RInt n
8646        | RBool n ->
8647            pr "PREINIT:\n";
8648            pr "      int %s;\n" n;
8649            pr "   CODE:\n";
8650            pr "      %s = guestfs_%s " n name;
8651            generate_c_call_args ~handle:"g" style;
8652            pr ";\n";
8653            do_cleanups ();
8654            pr "      if (%s == -1)\n" n;
8655            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8656            pr "      RETVAL = newSViv (%s);\n" n;
8657            pr " OUTPUT:\n";
8658            pr "      RETVAL\n"
8659        | RInt64 n ->
8660            pr "PREINIT:\n";
8661            pr "      int64_t %s;\n" n;
8662            pr "   CODE:\n";
8663            pr "      %s = guestfs_%s " n name;
8664            generate_c_call_args ~handle:"g" style;
8665            pr ";\n";
8666            do_cleanups ();
8667            pr "      if (%s == -1)\n" n;
8668            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8669            pr "      RETVAL = my_newSVll (%s);\n" n;
8670            pr " OUTPUT:\n";
8671            pr "      RETVAL\n"
8672        | RConstString n ->
8673            pr "PREINIT:\n";
8674            pr "      const char *%s;\n" n;
8675            pr "   CODE:\n";
8676            pr "      %s = guestfs_%s " n name;
8677            generate_c_call_args ~handle:"g" style;
8678            pr ";\n";
8679            do_cleanups ();
8680            pr "      if (%s == NULL)\n" n;
8681            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8682            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8683            pr " OUTPUT:\n";
8684            pr "      RETVAL\n"
8685        | RConstOptString n ->
8686            pr "PREINIT:\n";
8687            pr "      const char *%s;\n" n;
8688            pr "   CODE:\n";
8689            pr "      %s = guestfs_%s " n name;
8690            generate_c_call_args ~handle:"g" style;
8691            pr ";\n";
8692            do_cleanups ();
8693            pr "      if (%s == NULL)\n" n;
8694            pr "        RETVAL = &PL_sv_undef;\n";
8695            pr "      else\n";
8696            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8697            pr " OUTPUT:\n";
8698            pr "      RETVAL\n"
8699        | RString n ->
8700            pr "PREINIT:\n";
8701            pr "      char *%s;\n" n;
8702            pr "   CODE:\n";
8703            pr "      %s = guestfs_%s " n name;
8704            generate_c_call_args ~handle:"g" style;
8705            pr ";\n";
8706            do_cleanups ();
8707            pr "      if (%s == NULL)\n" n;
8708            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8709            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8710            pr "      free (%s);\n" n;
8711            pr " OUTPUT:\n";
8712            pr "      RETVAL\n"
8713        | RStringList n | RHashtable n ->
8714            pr "PREINIT:\n";
8715            pr "      char **%s;\n" n;
8716            pr "      int i, n;\n";
8717            pr " PPCODE:\n";
8718            pr "      %s = guestfs_%s " n name;
8719            generate_c_call_args ~handle:"g" style;
8720            pr ";\n";
8721            do_cleanups ();
8722            pr "      if (%s == NULL)\n" n;
8723            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8724            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8725            pr "      EXTEND (SP, n);\n";
8726            pr "      for (i = 0; i < n; ++i) {\n";
8727            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8728            pr "        free (%s[i]);\n" n;
8729            pr "      }\n";
8730            pr "      free (%s);\n" n;
8731        | RStruct (n, typ) ->
8732            let cols = cols_of_struct typ in
8733            generate_perl_struct_code typ cols name style n do_cleanups
8734        | RStructList (n, typ) ->
8735            let cols = cols_of_struct typ in
8736            generate_perl_struct_list_code typ cols name style n do_cleanups
8737        | RBufferOut n ->
8738            pr "PREINIT:\n";
8739            pr "      char *%s;\n" n;
8740            pr "      size_t size;\n";
8741            pr "   CODE:\n";
8742            pr "      %s = guestfs_%s " n name;
8743            generate_c_call_args ~handle:"g" style;
8744            pr ";\n";
8745            do_cleanups ();
8746            pr "      if (%s == NULL)\n" n;
8747            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8748            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8749            pr "      free (%s);\n" n;
8750            pr " OUTPUT:\n";
8751            pr "      RETVAL\n"
8752       );
8753
8754       pr "\n"
8755   ) all_functions
8756
8757 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8758   pr "PREINIT:\n";
8759   pr "      struct guestfs_%s_list *%s;\n" typ n;
8760   pr "      int i;\n";
8761   pr "      HV *hv;\n";
8762   pr " PPCODE:\n";
8763   pr "      %s = guestfs_%s " n name;
8764   generate_c_call_args ~handle:"g" style;
8765   pr ";\n";
8766   do_cleanups ();
8767   pr "      if (%s == NULL)\n" n;
8768   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8769   pr "      EXTEND (SP, %s->len);\n" n;
8770   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8771   pr "        hv = newHV ();\n";
8772   List.iter (
8773     function
8774     | name, FString ->
8775         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8776           name (String.length name) n name
8777     | name, FUUID ->
8778         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8779           name (String.length name) n name
8780     | name, FBuffer ->
8781         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8782           name (String.length name) n name n name
8783     | name, (FBytes|FUInt64) ->
8784         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8785           name (String.length name) n name
8786     | name, FInt64 ->
8787         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8788           name (String.length name) n name
8789     | name, (FInt32|FUInt32) ->
8790         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8791           name (String.length name) n name
8792     | name, FChar ->
8793         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8794           name (String.length name) n name
8795     | name, FOptPercent ->
8796         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8797           name (String.length name) n name
8798   ) cols;
8799   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8800   pr "      }\n";
8801   pr "      guestfs_free_%s_list (%s);\n" typ n
8802
8803 and generate_perl_struct_code typ cols name style n do_cleanups =
8804   pr "PREINIT:\n";
8805   pr "      struct guestfs_%s *%s;\n" typ n;
8806   pr " PPCODE:\n";
8807   pr "      %s = guestfs_%s " n name;
8808   generate_c_call_args ~handle:"g" style;
8809   pr ";\n";
8810   do_cleanups ();
8811   pr "      if (%s == NULL)\n" n;
8812   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8813   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8814   List.iter (
8815     fun ((name, _) as col) ->
8816       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8817
8818       match col with
8819       | name, FString ->
8820           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8821             n name
8822       | name, FBuffer ->
8823           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8824             n name n name
8825       | name, FUUID ->
8826           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8827             n name
8828       | name, (FBytes|FUInt64) ->
8829           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8830             n name
8831       | name, FInt64 ->
8832           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8833             n name
8834       | name, (FInt32|FUInt32) ->
8835           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8836             n name
8837       | name, FChar ->
8838           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8839             n name
8840       | name, FOptPercent ->
8841           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8842             n name
8843   ) cols;
8844   pr "      free (%s);\n" n
8845
8846 (* Generate Sys/Guestfs.pm. *)
8847 and generate_perl_pm () =
8848   generate_header HashStyle LGPLv2plus;
8849
8850   pr "\
8851 =pod
8852
8853 =head1 NAME
8854
8855 Sys::Guestfs - Perl bindings for libguestfs
8856
8857 =head1 SYNOPSIS
8858
8859  use Sys::Guestfs;
8860
8861  my $h = Sys::Guestfs->new ();
8862  $h->add_drive ('guest.img');
8863  $h->launch ();
8864  $h->mount ('/dev/sda1', '/');
8865  $h->touch ('/hello');
8866  $h->sync ();
8867
8868 =head1 DESCRIPTION
8869
8870 The C<Sys::Guestfs> module provides a Perl XS binding to the
8871 libguestfs API for examining and modifying virtual machine
8872 disk images.
8873
8874 Amongst the things this is good for: making batch configuration
8875 changes to guests, getting disk used/free statistics (see also:
8876 virt-df), migrating between virtualization systems (see also:
8877 virt-p2v), performing partial backups, performing partial guest
8878 clones, cloning guests and changing registry/UUID/hostname info, and
8879 much else besides.
8880
8881 Libguestfs uses Linux kernel and qemu code, and can access any type of
8882 guest filesystem that Linux and qemu can, including but not limited
8883 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8884 schemes, qcow, qcow2, vmdk.
8885
8886 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8887 LVs, what filesystem is in each LV, etc.).  It can also run commands
8888 in the context of the guest.  Also you can access filesystems over
8889 FUSE.
8890
8891 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8892 functions for using libguestfs from Perl, including integration
8893 with libvirt.
8894
8895 =head1 ERRORS
8896
8897 All errors turn into calls to C<croak> (see L<Carp(3)>).
8898
8899 =head1 METHODS
8900
8901 =over 4
8902
8903 =cut
8904
8905 package Sys::Guestfs;
8906
8907 use strict;
8908 use warnings;
8909
8910 # This version number changes whenever a new function
8911 # is added to the libguestfs API.  It is not directly
8912 # related to the libguestfs version number.
8913 use vars qw($VERSION);
8914 $VERSION = '0.%d';
8915
8916 require XSLoader;
8917 XSLoader::load ('Sys::Guestfs');
8918
8919 =item $h = Sys::Guestfs->new ();
8920
8921 Create a new guestfs handle.
8922
8923 =cut
8924
8925 sub new {
8926   my $proto = shift;
8927   my $class = ref ($proto) || $proto;
8928
8929   my $self = Sys::Guestfs::_create ();
8930   bless $self, $class;
8931   return $self;
8932 }
8933
8934 " max_proc_nr;
8935
8936   (* Actions.  We only need to print documentation for these as
8937    * they are pulled in from the XS code automatically.
8938    *)
8939   List.iter (
8940     fun (name, style, _, flags, _, _, longdesc) ->
8941       if not (List.mem NotInDocs flags) then (
8942         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8943         pr "=item ";
8944         generate_perl_prototype name style;
8945         pr "\n\n";
8946         pr "%s\n\n" longdesc;
8947         if List.mem ProtocolLimitWarning flags then
8948           pr "%s\n\n" protocol_limit_warning;
8949         if List.mem DangerWillRobinson flags then
8950           pr "%s\n\n" danger_will_robinson;
8951         match deprecation_notice flags with
8952         | None -> ()
8953         | Some txt -> pr "%s\n\n" txt
8954       )
8955   ) all_functions_sorted;
8956
8957   (* End of file. *)
8958   pr "\
8959 =cut
8960
8961 1;
8962
8963 =back
8964
8965 =head1 COPYRIGHT
8966
8967 Copyright (C) %s Red Hat Inc.
8968
8969 =head1 LICENSE
8970
8971 Please see the file COPYING.LIB for the full license.
8972
8973 =head1 SEE ALSO
8974
8975 L<guestfs(3)>,
8976 L<guestfish(1)>,
8977 L<http://libguestfs.org>,
8978 L<Sys::Guestfs::Lib(3)>.
8979
8980 =cut
8981 " copyright_years
8982
8983 and generate_perl_prototype name style =
8984   (match fst style with
8985    | RErr -> ()
8986    | RBool n
8987    | RInt n
8988    | RInt64 n
8989    | RConstString n
8990    | RConstOptString n
8991    | RString n
8992    | RBufferOut n -> pr "$%s = " n
8993    | RStruct (n,_)
8994    | RHashtable n -> pr "%%%s = " n
8995    | RStringList n
8996    | RStructList (n,_) -> pr "@%s = " n
8997   );
8998   pr "$h->%s (" name;
8999   let comma = ref false in
9000   List.iter (
9001     fun arg ->
9002       if !comma then pr ", ";
9003       comma := true;
9004       match arg with
9005       | Pathname n | Device n | Dev_or_Path n | String n
9006       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9007       | BufferIn n ->
9008           pr "$%s" n
9009       | StringList n | DeviceList n ->
9010           pr "\\@%s" n
9011   ) (snd style);
9012   pr ");"
9013
9014 (* Generate Python C module. *)
9015 and generate_python_c () =
9016   generate_header CStyle LGPLv2plus;
9017
9018   pr "\
9019 #define PY_SSIZE_T_CLEAN 1
9020 #include <Python.h>
9021
9022 #include <stdio.h>
9023 #include <stdlib.h>
9024 #include <assert.h>
9025
9026 #include \"guestfs.h\"
9027
9028 typedef struct {
9029   PyObject_HEAD
9030   guestfs_h *g;
9031 } Pyguestfs_Object;
9032
9033 static guestfs_h *
9034 get_handle (PyObject *obj)
9035 {
9036   assert (obj);
9037   assert (obj != Py_None);
9038   return ((Pyguestfs_Object *) obj)->g;
9039 }
9040
9041 static PyObject *
9042 put_handle (guestfs_h *g)
9043 {
9044   assert (g);
9045   return
9046     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9047 }
9048
9049 /* This list should be freed (but not the strings) after use. */
9050 static char **
9051 get_string_list (PyObject *obj)
9052 {
9053   int i, len;
9054   char **r;
9055
9056   assert (obj);
9057
9058   if (!PyList_Check (obj)) {
9059     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9060     return NULL;
9061   }
9062
9063   len = PyList_Size (obj);
9064   r = malloc (sizeof (char *) * (len+1));
9065   if (r == NULL) {
9066     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9067     return NULL;
9068   }
9069
9070   for (i = 0; i < len; ++i)
9071     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9072   r[len] = NULL;
9073
9074   return r;
9075 }
9076
9077 static PyObject *
9078 put_string_list (char * const * const argv)
9079 {
9080   PyObject *list;
9081   int argc, i;
9082
9083   for (argc = 0; argv[argc] != NULL; ++argc)
9084     ;
9085
9086   list = PyList_New (argc);
9087   for (i = 0; i < argc; ++i)
9088     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9089
9090   return list;
9091 }
9092
9093 static PyObject *
9094 put_table (char * const * const argv)
9095 {
9096   PyObject *list, *item;
9097   int argc, i;
9098
9099   for (argc = 0; argv[argc] != NULL; ++argc)
9100     ;
9101
9102   list = PyList_New (argc >> 1);
9103   for (i = 0; i < argc; i += 2) {
9104     item = PyTuple_New (2);
9105     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9106     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9107     PyList_SetItem (list, i >> 1, item);
9108   }
9109
9110   return list;
9111 }
9112
9113 static void
9114 free_strings (char **argv)
9115 {
9116   int argc;
9117
9118   for (argc = 0; argv[argc] != NULL; ++argc)
9119     free (argv[argc]);
9120   free (argv);
9121 }
9122
9123 static PyObject *
9124 py_guestfs_create (PyObject *self, PyObject *args)
9125 {
9126   guestfs_h *g;
9127
9128   g = guestfs_create ();
9129   if (g == NULL) {
9130     PyErr_SetString (PyExc_RuntimeError,
9131                      \"guestfs.create: failed to allocate handle\");
9132     return NULL;
9133   }
9134   guestfs_set_error_handler (g, NULL, NULL);
9135   return put_handle (g);
9136 }
9137
9138 static PyObject *
9139 py_guestfs_close (PyObject *self, PyObject *args)
9140 {
9141   PyObject *py_g;
9142   guestfs_h *g;
9143
9144   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9145     return NULL;
9146   g = get_handle (py_g);
9147
9148   guestfs_close (g);
9149
9150   Py_INCREF (Py_None);
9151   return Py_None;
9152 }
9153
9154 ";
9155
9156   let emit_put_list_function typ =
9157     pr "static PyObject *\n";
9158     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9159     pr "{\n";
9160     pr "  PyObject *list;\n";
9161     pr "  int i;\n";
9162     pr "\n";
9163     pr "  list = PyList_New (%ss->len);\n" typ;
9164     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9165     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9166     pr "  return list;\n";
9167     pr "};\n";
9168     pr "\n"
9169   in
9170
9171   (* Structures, turned into Python dictionaries. *)
9172   List.iter (
9173     fun (typ, cols) ->
9174       pr "static PyObject *\n";
9175       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9176       pr "{\n";
9177       pr "  PyObject *dict;\n";
9178       pr "\n";
9179       pr "  dict = PyDict_New ();\n";
9180       List.iter (
9181         function
9182         | name, FString ->
9183             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9184             pr "                        PyString_FromString (%s->%s));\n"
9185               typ name
9186         | name, FBuffer ->
9187             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9188             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9189               typ name typ name
9190         | name, FUUID ->
9191             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9192             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9193               typ name
9194         | name, (FBytes|FUInt64) ->
9195             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9196             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9197               typ name
9198         | name, FInt64 ->
9199             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9200             pr "                        PyLong_FromLongLong (%s->%s));\n"
9201               typ name
9202         | name, FUInt32 ->
9203             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9204             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9205               typ name
9206         | name, FInt32 ->
9207             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9208             pr "                        PyLong_FromLong (%s->%s));\n"
9209               typ name
9210         | name, FOptPercent ->
9211             pr "  if (%s->%s >= 0)\n" typ name;
9212             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9213             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9214               typ name;
9215             pr "  else {\n";
9216             pr "    Py_INCREF (Py_None);\n";
9217             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9218             pr "  }\n"
9219         | name, FChar ->
9220             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9221             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9222       ) cols;
9223       pr "  return dict;\n";
9224       pr "};\n";
9225       pr "\n";
9226
9227   ) structs;
9228
9229   (* Emit a put_TYPE_list function definition only if that function is used. *)
9230   List.iter (
9231     function
9232     | typ, (RStructListOnly | RStructAndList) ->
9233         (* generate the function for typ *)
9234         emit_put_list_function typ
9235     | typ, _ -> () (* empty *)
9236   ) (rstructs_used_by all_functions);
9237
9238   (* Python wrapper functions. *)
9239   List.iter (
9240     fun (name, style, _, _, _, _, _) ->
9241       pr "static PyObject *\n";
9242       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9243       pr "{\n";
9244
9245       pr "  PyObject *py_g;\n";
9246       pr "  guestfs_h *g;\n";
9247       pr "  PyObject *py_r;\n";
9248
9249       let error_code =
9250         match fst style with
9251         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9252         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9253         | RConstString _ | RConstOptString _ ->
9254             pr "  const char *r;\n"; "NULL"
9255         | RString _ -> pr "  char *r;\n"; "NULL"
9256         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9257         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9258         | RStructList (_, typ) ->
9259             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9260         | RBufferOut _ ->
9261             pr "  char *r;\n";
9262             pr "  size_t size;\n";
9263             "NULL" in
9264
9265       List.iter (
9266         function
9267         | Pathname n | Device n | Dev_or_Path n | String n
9268         | FileIn n | FileOut n ->
9269             pr "  const char *%s;\n" n
9270         | OptString n -> pr "  const char *%s;\n" n
9271         | BufferIn n ->
9272             pr "  const char *%s;\n" n;
9273             pr "  Py_ssize_t %s_size;\n" n
9274         | StringList n | DeviceList n ->
9275             pr "  PyObject *py_%s;\n" n;
9276             pr "  char **%s;\n" n
9277         | Bool n -> pr "  int %s;\n" n
9278         | Int n -> pr "  int %s;\n" n
9279         | Int64 n -> pr "  long long %s;\n" n
9280       ) (snd style);
9281
9282       pr "\n";
9283
9284       (* Convert the parameters. *)
9285       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9286       List.iter (
9287         function
9288         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9289         | OptString _ -> pr "z"
9290         | StringList _ | DeviceList _ -> pr "O"
9291         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9292         | Int _ -> pr "i"
9293         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9294                              * emulate C's int/long/long long in Python?
9295                              *)
9296         | BufferIn _ -> pr "s#"
9297       ) (snd style);
9298       pr ":guestfs_%s\",\n" name;
9299       pr "                         &py_g";
9300       List.iter (
9301         function
9302         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9303         | OptString n -> pr ", &%s" n
9304         | StringList n | DeviceList n -> pr ", &py_%s" n
9305         | Bool n -> pr ", &%s" n
9306         | Int n -> pr ", &%s" n
9307         | Int64 n -> pr ", &%s" n
9308         | BufferIn n -> pr ", &%s, &%s_size" n n
9309       ) (snd style);
9310
9311       pr "))\n";
9312       pr "    return NULL;\n";
9313
9314       pr "  g = get_handle (py_g);\n";
9315       List.iter (
9316         function
9317         | Pathname _ | Device _ | Dev_or_Path _ | String _
9318         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9319         | BufferIn _ -> ()
9320         | StringList n | DeviceList n ->
9321             pr "  %s = get_string_list (py_%s);\n" n n;
9322             pr "  if (!%s) return NULL;\n" n
9323       ) (snd style);
9324
9325       pr "\n";
9326
9327       pr "  r = guestfs_%s " name;
9328       generate_c_call_args ~handle:"g" style;
9329       pr ";\n";
9330
9331       List.iter (
9332         function
9333         | Pathname _ | Device _ | Dev_or_Path _ | String _
9334         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9335         | BufferIn _ -> ()
9336         | StringList n | DeviceList n ->
9337             pr "  free (%s);\n" n
9338       ) (snd style);
9339
9340       pr "  if (r == %s) {\n" error_code;
9341       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9342       pr "    return NULL;\n";
9343       pr "  }\n";
9344       pr "\n";
9345
9346       (match fst style with
9347        | RErr ->
9348            pr "  Py_INCREF (Py_None);\n";
9349            pr "  py_r = Py_None;\n"
9350        | RInt _
9351        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9352        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9353        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9354        | RConstOptString _ ->
9355            pr "  if (r)\n";
9356            pr "    py_r = PyString_FromString (r);\n";
9357            pr "  else {\n";
9358            pr "    Py_INCREF (Py_None);\n";
9359            pr "    py_r = Py_None;\n";
9360            pr "  }\n"
9361        | RString _ ->
9362            pr "  py_r = PyString_FromString (r);\n";
9363            pr "  free (r);\n"
9364        | RStringList _ ->
9365            pr "  py_r = put_string_list (r);\n";
9366            pr "  free_strings (r);\n"
9367        | RStruct (_, typ) ->
9368            pr "  py_r = put_%s (r);\n" typ;
9369            pr "  guestfs_free_%s (r);\n" typ
9370        | RStructList (_, typ) ->
9371            pr "  py_r = put_%s_list (r);\n" typ;
9372            pr "  guestfs_free_%s_list (r);\n" typ
9373        | RHashtable n ->
9374            pr "  py_r = put_table (r);\n";
9375            pr "  free_strings (r);\n"
9376        | RBufferOut _ ->
9377            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9378            pr "  free (r);\n"
9379       );
9380
9381       pr "  return py_r;\n";
9382       pr "}\n";
9383       pr "\n"
9384   ) all_functions;
9385
9386   (* Table of functions. *)
9387   pr "static PyMethodDef methods[] = {\n";
9388   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9389   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9390   List.iter (
9391     fun (name, _, _, _, _, _, _) ->
9392       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9393         name name
9394   ) all_functions;
9395   pr "  { NULL, NULL, 0, NULL }\n";
9396   pr "};\n";
9397   pr "\n";
9398
9399   (* Init function. *)
9400   pr "\
9401 void
9402 initlibguestfsmod (void)
9403 {
9404   static int initialized = 0;
9405
9406   if (initialized) return;
9407   Py_InitModule ((char *) \"libguestfsmod\", methods);
9408   initialized = 1;
9409 }
9410 "
9411
9412 (* Generate Python module. *)
9413 and generate_python_py () =
9414   generate_header HashStyle LGPLv2plus;
9415
9416   pr "\
9417 u\"\"\"Python bindings for libguestfs
9418
9419 import guestfs
9420 g = guestfs.GuestFS ()
9421 g.add_drive (\"guest.img\")
9422 g.launch ()
9423 parts = g.list_partitions ()
9424
9425 The guestfs module provides a Python binding to the libguestfs API
9426 for examining and modifying virtual machine disk images.
9427
9428 Amongst the things this is good for: making batch configuration
9429 changes to guests, getting disk used/free statistics (see also:
9430 virt-df), migrating between virtualization systems (see also:
9431 virt-p2v), performing partial backups, performing partial guest
9432 clones, cloning guests and changing registry/UUID/hostname info, and
9433 much else besides.
9434
9435 Libguestfs uses Linux kernel and qemu code, and can access any type of
9436 guest filesystem that Linux and qemu can, including but not limited
9437 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9438 schemes, qcow, qcow2, vmdk.
9439
9440 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9441 LVs, what filesystem is in each LV, etc.).  It can also run commands
9442 in the context of the guest.  Also you can access filesystems over
9443 FUSE.
9444
9445 Errors which happen while using the API are turned into Python
9446 RuntimeError exceptions.
9447
9448 To create a guestfs handle you usually have to perform the following
9449 sequence of calls:
9450
9451 # Create the handle, call add_drive at least once, and possibly
9452 # several times if the guest has multiple block devices:
9453 g = guestfs.GuestFS ()
9454 g.add_drive (\"guest.img\")
9455
9456 # Launch the qemu subprocess and wait for it to become ready:
9457 g.launch ()
9458
9459 # Now you can issue commands, for example:
9460 logvols = g.lvs ()
9461
9462 \"\"\"
9463
9464 import libguestfsmod
9465
9466 class GuestFS:
9467     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9468
9469     def __init__ (self):
9470         \"\"\"Create a new libguestfs handle.\"\"\"
9471         self._o = libguestfsmod.create ()
9472
9473     def __del__ (self):
9474         libguestfsmod.close (self._o)
9475
9476 ";
9477
9478   List.iter (
9479     fun (name, style, _, flags, _, _, longdesc) ->
9480       pr "    def %s " name;
9481       generate_py_call_args ~handle:"self" (snd style);
9482       pr ":\n";
9483
9484       if not (List.mem NotInDocs flags) then (
9485         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9486         let doc =
9487           match fst style with
9488           | RErr | RInt _ | RInt64 _ | RBool _
9489           | RConstOptString _ | RConstString _
9490           | RString _ | RBufferOut _ -> doc
9491           | RStringList _ ->
9492               doc ^ "\n\nThis function returns a list of strings."
9493           | RStruct (_, typ) ->
9494               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9495           | RStructList (_, typ) ->
9496               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9497           | RHashtable _ ->
9498               doc ^ "\n\nThis function returns a dictionary." in
9499         let doc =
9500           if List.mem ProtocolLimitWarning flags then
9501             doc ^ "\n\n" ^ protocol_limit_warning
9502           else doc in
9503         let doc =
9504           if List.mem DangerWillRobinson flags then
9505             doc ^ "\n\n" ^ danger_will_robinson
9506           else doc in
9507         let doc =
9508           match deprecation_notice flags with
9509           | None -> doc
9510           | Some txt -> doc ^ "\n\n" ^ txt in
9511         let doc = pod2text ~width:60 name doc in
9512         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9513         let doc = String.concat "\n        " doc in
9514         pr "        u\"\"\"%s\"\"\"\n" doc;
9515       );
9516       pr "        return libguestfsmod.%s " name;
9517       generate_py_call_args ~handle:"self._o" (snd style);
9518       pr "\n";
9519       pr "\n";
9520   ) all_functions
9521
9522 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9523 and generate_py_call_args ~handle args =
9524   pr "(%s" handle;
9525   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9526   pr ")"
9527
9528 (* Useful if you need the longdesc POD text as plain text.  Returns a
9529  * list of lines.
9530  *
9531  * Because this is very slow (the slowest part of autogeneration),
9532  * we memoize the results.
9533  *)
9534 and pod2text ~width name longdesc =
9535   let key = width, name, longdesc in
9536   try Hashtbl.find pod2text_memo key
9537   with Not_found ->
9538     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9539     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9540     close_out chan;
9541     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9542     let chan = open_process_in cmd in
9543     let lines = ref [] in
9544     let rec loop i =
9545       let line = input_line chan in
9546       if i = 1 then             (* discard the first line of output *)
9547         loop (i+1)
9548       else (
9549         let line = triml line in
9550         lines := line :: !lines;
9551         loop (i+1)
9552       ) in
9553     let lines = try loop 1 with End_of_file -> List.rev !lines in
9554     unlink filename;
9555     (match close_process_in chan with
9556      | WEXITED 0 -> ()
9557      | WEXITED i ->
9558          failwithf "pod2text: process exited with non-zero status (%d)" i
9559      | WSIGNALED i | WSTOPPED i ->
9560          failwithf "pod2text: process signalled or stopped by signal %d" i
9561     );
9562     Hashtbl.add pod2text_memo key lines;
9563     pod2text_memo_updated ();
9564     lines
9565
9566 (* Generate ruby bindings. *)
9567 and generate_ruby_c () =
9568   generate_header CStyle LGPLv2plus;
9569
9570   pr "\
9571 #include <stdio.h>
9572 #include <stdlib.h>
9573
9574 #include <ruby.h>
9575
9576 #include \"guestfs.h\"
9577
9578 #include \"extconf.h\"
9579
9580 /* For Ruby < 1.9 */
9581 #ifndef RARRAY_LEN
9582 #define RARRAY_LEN(r) (RARRAY((r))->len)
9583 #endif
9584
9585 static VALUE m_guestfs;                 /* guestfs module */
9586 static VALUE c_guestfs;                 /* guestfs_h handle */
9587 static VALUE e_Error;                   /* used for all errors */
9588
9589 static void ruby_guestfs_free (void *p)
9590 {
9591   if (!p) return;
9592   guestfs_close ((guestfs_h *) p);
9593 }
9594
9595 static VALUE ruby_guestfs_create (VALUE m)
9596 {
9597   guestfs_h *g;
9598
9599   g = guestfs_create ();
9600   if (!g)
9601     rb_raise (e_Error, \"failed to create guestfs handle\");
9602
9603   /* Don't print error messages to stderr by default. */
9604   guestfs_set_error_handler (g, NULL, NULL);
9605
9606   /* Wrap it, and make sure the close function is called when the
9607    * handle goes away.
9608    */
9609   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9610 }
9611
9612 static VALUE ruby_guestfs_close (VALUE gv)
9613 {
9614   guestfs_h *g;
9615   Data_Get_Struct (gv, guestfs_h, g);
9616
9617   ruby_guestfs_free (g);
9618   DATA_PTR (gv) = NULL;
9619
9620   return Qnil;
9621 }
9622
9623 ";
9624
9625   List.iter (
9626     fun (name, style, _, _, _, _, _) ->
9627       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9628       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9629       pr ")\n";
9630       pr "{\n";
9631       pr "  guestfs_h *g;\n";
9632       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9633       pr "  if (!g)\n";
9634       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9635         name;
9636       pr "\n";
9637
9638       List.iter (
9639         function
9640         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9641             pr "  Check_Type (%sv, T_STRING);\n" n;
9642             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9643             pr "  if (!%s)\n" n;
9644             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9645             pr "              \"%s\", \"%s\");\n" n name
9646         | BufferIn n ->
9647             pr "  Check_Type (%sv, T_STRING);\n" n;
9648             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9649             pr "  if (!%s)\n" n;
9650             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9651             pr "              \"%s\", \"%s\");\n" n name;
9652             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9653         | OptString n ->
9654             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9655         | StringList n | DeviceList n ->
9656             pr "  char **%s;\n" n;
9657             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9658             pr "  {\n";
9659             pr "    int i, len;\n";
9660             pr "    len = RARRAY_LEN (%sv);\n" n;
9661             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9662               n;
9663             pr "    for (i = 0; i < len; ++i) {\n";
9664             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9665             pr "      %s[i] = StringValueCStr (v);\n" n;
9666             pr "    }\n";
9667             pr "    %s[len] = NULL;\n" n;
9668             pr "  }\n";
9669         | Bool n ->
9670             pr "  int %s = RTEST (%sv);\n" n n
9671         | Int n ->
9672             pr "  int %s = NUM2INT (%sv);\n" n n
9673         | Int64 n ->
9674             pr "  long long %s = NUM2LL (%sv);\n" n n
9675       ) (snd style);
9676       pr "\n";
9677
9678       let error_code =
9679         match fst style with
9680         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9681         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9682         | RConstString _ | RConstOptString _ ->
9683             pr "  const char *r;\n"; "NULL"
9684         | RString _ -> pr "  char *r;\n"; "NULL"
9685         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9686         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9687         | RStructList (_, typ) ->
9688             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9689         | RBufferOut _ ->
9690             pr "  char *r;\n";
9691             pr "  size_t size;\n";
9692             "NULL" in
9693       pr "\n";
9694
9695       pr "  r = guestfs_%s " name;
9696       generate_c_call_args ~handle:"g" style;
9697       pr ";\n";
9698
9699       List.iter (
9700         function
9701         | Pathname _ | Device _ | Dev_or_Path _ | String _
9702         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9703         | BufferIn _ -> ()
9704         | StringList n | DeviceList n ->
9705             pr "  free (%s);\n" n
9706       ) (snd style);
9707
9708       pr "  if (r == %s)\n" error_code;
9709       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9710       pr "\n";
9711
9712       (match fst style with
9713        | RErr ->
9714            pr "  return Qnil;\n"
9715        | RInt _ | RBool _ ->
9716            pr "  return INT2NUM (r);\n"
9717        | RInt64 _ ->
9718            pr "  return ULL2NUM (r);\n"
9719        | RConstString _ ->
9720            pr "  return rb_str_new2 (r);\n";
9721        | RConstOptString _ ->
9722            pr "  if (r)\n";
9723            pr "    return rb_str_new2 (r);\n";
9724            pr "  else\n";
9725            pr "    return Qnil;\n";
9726        | RString _ ->
9727            pr "  VALUE rv = rb_str_new2 (r);\n";
9728            pr "  free (r);\n";
9729            pr "  return rv;\n";
9730        | RStringList _ ->
9731            pr "  int i, len = 0;\n";
9732            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9733            pr "  VALUE rv = rb_ary_new2 (len);\n";
9734            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9735            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9736            pr "    free (r[i]);\n";
9737            pr "  }\n";
9738            pr "  free (r);\n";
9739            pr "  return rv;\n"
9740        | RStruct (_, typ) ->
9741            let cols = cols_of_struct typ in
9742            generate_ruby_struct_code typ cols
9743        | RStructList (_, typ) ->
9744            let cols = cols_of_struct typ in
9745            generate_ruby_struct_list_code typ cols
9746        | RHashtable _ ->
9747            pr "  VALUE rv = rb_hash_new ();\n";
9748            pr "  int i;\n";
9749            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9750            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9751            pr "    free (r[i]);\n";
9752            pr "    free (r[i+1]);\n";
9753            pr "  }\n";
9754            pr "  free (r);\n";
9755            pr "  return rv;\n"
9756        | RBufferOut _ ->
9757            pr "  VALUE rv = rb_str_new (r, size);\n";
9758            pr "  free (r);\n";
9759            pr "  return rv;\n";
9760       );
9761
9762       pr "}\n";
9763       pr "\n"
9764   ) all_functions;
9765
9766   pr "\
9767 /* Initialize the module. */
9768 void Init__guestfs ()
9769 {
9770   m_guestfs = rb_define_module (\"Guestfs\");
9771   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9772   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9773
9774   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9775   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9776
9777 ";
9778   (* Define the rest of the methods. *)
9779   List.iter (
9780     fun (name, style, _, _, _, _, _) ->
9781       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9782       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9783   ) all_functions;
9784
9785   pr "}\n"
9786
9787 (* Ruby code to return a struct. *)
9788 and generate_ruby_struct_code typ cols =
9789   pr "  VALUE rv = rb_hash_new ();\n";
9790   List.iter (
9791     function
9792     | name, FString ->
9793         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9794     | name, FBuffer ->
9795         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9796     | name, FUUID ->
9797         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9798     | name, (FBytes|FUInt64) ->
9799         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9800     | name, FInt64 ->
9801         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9802     | name, FUInt32 ->
9803         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9804     | name, FInt32 ->
9805         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9806     | name, FOptPercent ->
9807         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9808     | name, FChar -> (* XXX wrong? *)
9809         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9810   ) cols;
9811   pr "  guestfs_free_%s (r);\n" typ;
9812   pr "  return rv;\n"
9813
9814 (* Ruby code to return a struct list. *)
9815 and generate_ruby_struct_list_code typ cols =
9816   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9817   pr "  int i;\n";
9818   pr "  for (i = 0; i < r->len; ++i) {\n";
9819   pr "    VALUE hv = rb_hash_new ();\n";
9820   List.iter (
9821     function
9822     | name, FString ->
9823         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9824     | name, FBuffer ->
9825         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
9826     | name, FUUID ->
9827         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9828     | name, (FBytes|FUInt64) ->
9829         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9830     | name, FInt64 ->
9831         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9832     | name, FUInt32 ->
9833         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9834     | name, FInt32 ->
9835         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9836     | name, FOptPercent ->
9837         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9838     | name, FChar -> (* XXX wrong? *)
9839         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9840   ) cols;
9841   pr "    rb_ary_push (rv, hv);\n";
9842   pr "  }\n";
9843   pr "  guestfs_free_%s_list (r);\n" typ;
9844   pr "  return rv;\n"
9845
9846 (* Generate Java bindings GuestFS.java file. *)
9847 and generate_java_java () =
9848   generate_header CStyle LGPLv2plus;
9849
9850   pr "\
9851 package com.redhat.et.libguestfs;
9852
9853 import java.util.HashMap;
9854 import com.redhat.et.libguestfs.LibGuestFSException;
9855 import com.redhat.et.libguestfs.PV;
9856 import com.redhat.et.libguestfs.VG;
9857 import com.redhat.et.libguestfs.LV;
9858 import com.redhat.et.libguestfs.Stat;
9859 import com.redhat.et.libguestfs.StatVFS;
9860 import com.redhat.et.libguestfs.IntBool;
9861 import com.redhat.et.libguestfs.Dirent;
9862
9863 /**
9864  * The GuestFS object is a libguestfs handle.
9865  *
9866  * @author rjones
9867  */
9868 public class GuestFS {
9869   // Load the native code.
9870   static {
9871     System.loadLibrary (\"guestfs_jni\");
9872   }
9873
9874   /**
9875    * The native guestfs_h pointer.
9876    */
9877   long g;
9878
9879   /**
9880    * Create a libguestfs handle.
9881    *
9882    * @throws LibGuestFSException
9883    */
9884   public GuestFS () throws LibGuestFSException
9885   {
9886     g = _create ();
9887   }
9888   private native long _create () throws LibGuestFSException;
9889
9890   /**
9891    * Close a libguestfs handle.
9892    *
9893    * You can also leave handles to be collected by the garbage
9894    * collector, but this method ensures that the resources used
9895    * by the handle are freed up immediately.  If you call any
9896    * other methods after closing the handle, you will get an
9897    * exception.
9898    *
9899    * @throws LibGuestFSException
9900    */
9901   public void close () throws LibGuestFSException
9902   {
9903     if (g != 0)
9904       _close (g);
9905     g = 0;
9906   }
9907   private native void _close (long g) throws LibGuestFSException;
9908
9909   public void finalize () throws LibGuestFSException
9910   {
9911     close ();
9912   }
9913
9914 ";
9915
9916   List.iter (
9917     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9918       if not (List.mem NotInDocs flags); then (
9919         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9920         let doc =
9921           if List.mem ProtocolLimitWarning flags then
9922             doc ^ "\n\n" ^ protocol_limit_warning
9923           else doc in
9924         let doc =
9925           if List.mem DangerWillRobinson flags then
9926             doc ^ "\n\n" ^ danger_will_robinson
9927           else doc in
9928         let doc =
9929           match deprecation_notice flags with
9930           | None -> doc
9931           | Some txt -> doc ^ "\n\n" ^ txt in
9932         let doc = pod2text ~width:60 name doc in
9933         let doc = List.map (            (* RHBZ#501883 *)
9934           function
9935           | "" -> "<p>"
9936           | nonempty -> nonempty
9937         ) doc in
9938         let doc = String.concat "\n   * " doc in
9939
9940         pr "  /**\n";
9941         pr "   * %s\n" shortdesc;
9942         pr "   * <p>\n";
9943         pr "   * %s\n" doc;
9944         pr "   * @throws LibGuestFSException\n";
9945         pr "   */\n";
9946         pr "  ";
9947       );
9948       generate_java_prototype ~public:true ~semicolon:false name style;
9949       pr "\n";
9950       pr "  {\n";
9951       pr "    if (g == 0)\n";
9952       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9953         name;
9954       pr "    ";
9955       if fst style <> RErr then pr "return ";
9956       pr "_%s " name;
9957       generate_java_call_args ~handle:"g" (snd style);
9958       pr ";\n";
9959       pr "  }\n";
9960       pr "  ";
9961       generate_java_prototype ~privat:true ~native:true name style;
9962       pr "\n";
9963       pr "\n";
9964   ) all_functions;
9965
9966   pr "}\n"
9967
9968 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9969 and generate_java_call_args ~handle args =
9970   pr "(%s" handle;
9971   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9972   pr ")"
9973
9974 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9975     ?(semicolon=true) name style =
9976   if privat then pr "private ";
9977   if public then pr "public ";
9978   if native then pr "native ";
9979
9980   (* return type *)
9981   (match fst style with
9982    | RErr -> pr "void ";
9983    | RInt _ -> pr "int ";
9984    | RInt64 _ -> pr "long ";
9985    | RBool _ -> pr "boolean ";
9986    | RConstString _ | RConstOptString _ | RString _
9987    | RBufferOut _ -> pr "String ";
9988    | RStringList _ -> pr "String[] ";
9989    | RStruct (_, typ) ->
9990        let name = java_name_of_struct typ in
9991        pr "%s " name;
9992    | RStructList (_, typ) ->
9993        let name = java_name_of_struct typ in
9994        pr "%s[] " name;
9995    | RHashtable _ -> pr "HashMap<String,String> ";
9996   );
9997
9998   if native then pr "_%s " name else pr "%s " name;
9999   pr "(";
10000   let needs_comma = ref false in
10001   if native then (
10002     pr "long g";
10003     needs_comma := true
10004   );
10005
10006   (* args *)
10007   List.iter (
10008     fun arg ->
10009       if !needs_comma then pr ", ";
10010       needs_comma := true;
10011
10012       match arg with
10013       | Pathname n
10014       | Device n | Dev_or_Path n
10015       | String n
10016       | OptString n
10017       | FileIn n
10018       | FileOut n ->
10019           pr "String %s" n
10020       | BufferIn n ->
10021           pr "byte[] %s" n
10022       | StringList n | DeviceList n ->
10023           pr "String[] %s" n
10024       | Bool n ->
10025           pr "boolean %s" n
10026       | Int n ->
10027           pr "int %s" n
10028       | Int64 n ->
10029           pr "long %s" n
10030   ) (snd style);
10031
10032   pr ")\n";
10033   pr "    throws LibGuestFSException";
10034   if semicolon then pr ";"
10035
10036 and generate_java_struct jtyp cols () =
10037   generate_header CStyle LGPLv2plus;
10038
10039   pr "\
10040 package com.redhat.et.libguestfs;
10041
10042 /**
10043  * Libguestfs %s structure.
10044  *
10045  * @author rjones
10046  * @see GuestFS
10047  */
10048 public class %s {
10049 " jtyp jtyp;
10050
10051   List.iter (
10052     function
10053     | name, FString
10054     | name, FUUID
10055     | name, FBuffer -> pr "  public String %s;\n" name
10056     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10057     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10058     | name, FChar -> pr "  public char %s;\n" name
10059     | name, FOptPercent ->
10060         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10061         pr "  public float %s;\n" name
10062   ) cols;
10063
10064   pr "}\n"
10065
10066 and generate_java_c () =
10067   generate_header CStyle LGPLv2plus;
10068
10069   pr "\
10070 #include <stdio.h>
10071 #include <stdlib.h>
10072 #include <string.h>
10073
10074 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10075 #include \"guestfs.h\"
10076
10077 /* Note that this function returns.  The exception is not thrown
10078  * until after the wrapper function returns.
10079  */
10080 static void
10081 throw_exception (JNIEnv *env, const char *msg)
10082 {
10083   jclass cl;
10084   cl = (*env)->FindClass (env,
10085                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10086   (*env)->ThrowNew (env, cl, msg);
10087 }
10088
10089 JNIEXPORT jlong JNICALL
10090 Java_com_redhat_et_libguestfs_GuestFS__1create
10091   (JNIEnv *env, jobject obj)
10092 {
10093   guestfs_h *g;
10094
10095   g = guestfs_create ();
10096   if (g == NULL) {
10097     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10098     return 0;
10099   }
10100   guestfs_set_error_handler (g, NULL, NULL);
10101   return (jlong) (long) g;
10102 }
10103
10104 JNIEXPORT void JNICALL
10105 Java_com_redhat_et_libguestfs_GuestFS__1close
10106   (JNIEnv *env, jobject obj, jlong jg)
10107 {
10108   guestfs_h *g = (guestfs_h *) (long) jg;
10109   guestfs_close (g);
10110 }
10111
10112 ";
10113
10114   List.iter (
10115     fun (name, style, _, _, _, _, _) ->
10116       pr "JNIEXPORT ";
10117       (match fst style with
10118        | RErr -> pr "void ";
10119        | RInt _ -> pr "jint ";
10120        | RInt64 _ -> pr "jlong ";
10121        | RBool _ -> pr "jboolean ";
10122        | RConstString _ | RConstOptString _ | RString _
10123        | RBufferOut _ -> pr "jstring ";
10124        | RStruct _ | RHashtable _ ->
10125            pr "jobject ";
10126        | RStringList _ | RStructList _ ->
10127            pr "jobjectArray ";
10128       );
10129       pr "JNICALL\n";
10130       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10131       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10132       pr "\n";
10133       pr "  (JNIEnv *env, jobject obj, jlong jg";
10134       List.iter (
10135         function
10136         | Pathname n
10137         | Device n | Dev_or_Path n
10138         | String n
10139         | OptString n
10140         | FileIn n
10141         | FileOut n ->
10142             pr ", jstring j%s" n
10143         | BufferIn n ->
10144             pr ", jbyteArray j%s" n
10145         | StringList n | DeviceList n ->
10146             pr ", jobjectArray j%s" n
10147         | Bool n ->
10148             pr ", jboolean j%s" n
10149         | Int n ->
10150             pr ", jint j%s" n
10151         | Int64 n ->
10152             pr ", jlong j%s" n
10153       ) (snd style);
10154       pr ")\n";
10155       pr "{\n";
10156       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10157       let error_code, no_ret =
10158         match fst style with
10159         | RErr -> pr "  int r;\n"; "-1", ""
10160         | RBool _
10161         | RInt _ -> pr "  int r;\n"; "-1", "0"
10162         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10163         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10164         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10165         | RString _ ->
10166             pr "  jstring jr;\n";
10167             pr "  char *r;\n"; "NULL", "NULL"
10168         | RStringList _ ->
10169             pr "  jobjectArray jr;\n";
10170             pr "  int r_len;\n";
10171             pr "  jclass cl;\n";
10172             pr "  jstring jstr;\n";
10173             pr "  char **r;\n"; "NULL", "NULL"
10174         | RStruct (_, typ) ->
10175             pr "  jobject jr;\n";
10176             pr "  jclass cl;\n";
10177             pr "  jfieldID fl;\n";
10178             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10179         | RStructList (_, typ) ->
10180             pr "  jobjectArray jr;\n";
10181             pr "  jclass cl;\n";
10182             pr "  jfieldID fl;\n";
10183             pr "  jobject jfl;\n";
10184             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10185         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10186         | RBufferOut _ ->
10187             pr "  jstring jr;\n";
10188             pr "  char *r;\n";
10189             pr "  size_t size;\n";
10190             "NULL", "NULL" in
10191       List.iter (
10192         function
10193         | Pathname n
10194         | Device n | Dev_or_Path n
10195         | String n
10196         | OptString n
10197         | FileIn n
10198         | FileOut n ->
10199             pr "  const char *%s;\n" n
10200         | BufferIn n ->
10201             pr "  jbyte *%s;\n" n;
10202             pr "  size_t %s_size;\n" n
10203         | StringList n | DeviceList n ->
10204             pr "  int %s_len;\n" n;
10205             pr "  const char **%s;\n" n
10206         | Bool n
10207         | Int n ->
10208             pr "  int %s;\n" n
10209         | Int64 n ->
10210             pr "  int64_t %s;\n" n
10211       ) (snd style);
10212
10213       let needs_i =
10214         (match fst style with
10215          | RStringList _ | RStructList _ -> true
10216          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10217          | RConstOptString _
10218          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10219           List.exists (function
10220                        | StringList _ -> true
10221                        | DeviceList _ -> true
10222                        | _ -> false) (snd style) in
10223       if needs_i then
10224         pr "  int i;\n";
10225
10226       pr "\n";
10227
10228       (* Get the parameters. *)
10229       List.iter (
10230         function
10231         | Pathname n
10232         | Device n | Dev_or_Path n
10233         | String n
10234         | FileIn n
10235         | FileOut n ->
10236             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10237         | OptString n ->
10238             (* This is completely undocumented, but Java null becomes
10239              * a NULL parameter.
10240              *)
10241             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10242         | BufferIn n ->
10243             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10244             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10245         | StringList n | DeviceList n ->
10246             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10247             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10248             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10249             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10250               n;
10251             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10252             pr "  }\n";
10253             pr "  %s[%s_len] = NULL;\n" n n;
10254         | Bool n
10255         | Int n
10256         | Int64 n ->
10257             pr "  %s = j%s;\n" n n
10258       ) (snd style);
10259
10260       (* Make the call. *)
10261       pr "  r = guestfs_%s " name;
10262       generate_c_call_args ~handle:"g" style;
10263       pr ";\n";
10264
10265       (* Release the parameters. *)
10266       List.iter (
10267         function
10268         | Pathname n
10269         | Device n | Dev_or_Path n
10270         | String n
10271         | FileIn n
10272         | FileOut n ->
10273             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10274         | OptString n ->
10275             pr "  if (j%s)\n" n;
10276             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10277         | BufferIn n ->
10278             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10279         | StringList n | DeviceList n ->
10280             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10281             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10282               n;
10283             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10284             pr "  }\n";
10285             pr "  free (%s);\n" n
10286         | Bool n
10287         | Int n
10288         | Int64 n -> ()
10289       ) (snd style);
10290
10291       (* Check for errors. *)
10292       pr "  if (r == %s) {\n" error_code;
10293       pr "    throw_exception (env, guestfs_last_error (g));\n";
10294       pr "    return %s;\n" no_ret;
10295       pr "  }\n";
10296
10297       (* Return value. *)
10298       (match fst style with
10299        | RErr -> ()
10300        | RInt _ -> pr "  return (jint) r;\n"
10301        | RBool _ -> pr "  return (jboolean) r;\n"
10302        | RInt64 _ -> pr "  return (jlong) r;\n"
10303        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10304        | RConstOptString _ ->
10305            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10306        | RString _ ->
10307            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10308            pr "  free (r);\n";
10309            pr "  return jr;\n"
10310        | RStringList _ ->
10311            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10312            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10313            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10314            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10315            pr "  for (i = 0; i < r_len; ++i) {\n";
10316            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10317            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10318            pr "    free (r[i]);\n";
10319            pr "  }\n";
10320            pr "  free (r);\n";
10321            pr "  return jr;\n"
10322        | RStruct (_, typ) ->
10323            let jtyp = java_name_of_struct typ in
10324            let cols = cols_of_struct typ in
10325            generate_java_struct_return typ jtyp cols
10326        | RStructList (_, typ) ->
10327            let jtyp = java_name_of_struct typ in
10328            let cols = cols_of_struct typ in
10329            generate_java_struct_list_return typ jtyp cols
10330        | RHashtable _ ->
10331            (* XXX *)
10332            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10333            pr "  return NULL;\n"
10334        | RBufferOut _ ->
10335            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10336            pr "  free (r);\n";
10337            pr "  return jr;\n"
10338       );
10339
10340       pr "}\n";
10341       pr "\n"
10342   ) all_functions
10343
10344 and generate_java_struct_return typ jtyp cols =
10345   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10346   pr "  jr = (*env)->AllocObject (env, cl);\n";
10347   List.iter (
10348     function
10349     | name, FString ->
10350         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10351         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10352     | name, FUUID ->
10353         pr "  {\n";
10354         pr "    char s[33];\n";
10355         pr "    memcpy (s, r->%s, 32);\n" name;
10356         pr "    s[32] = 0;\n";
10357         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10358         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10359         pr "  }\n";
10360     | name, FBuffer ->
10361         pr "  {\n";
10362         pr "    int len = r->%s_len;\n" name;
10363         pr "    char s[len+1];\n";
10364         pr "    memcpy (s, r->%s, len);\n" name;
10365         pr "    s[len] = 0;\n";
10366         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10367         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10368         pr "  }\n";
10369     | name, (FBytes|FUInt64|FInt64) ->
10370         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10371         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10372     | name, (FUInt32|FInt32) ->
10373         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10374         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10375     | name, FOptPercent ->
10376         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10377         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10378     | name, FChar ->
10379         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10380         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10381   ) cols;
10382   pr "  free (r);\n";
10383   pr "  return jr;\n"
10384
10385 and generate_java_struct_list_return typ jtyp cols =
10386   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10387   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10388   pr "  for (i = 0; i < r->len; ++i) {\n";
10389   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10390   List.iter (
10391     function
10392     | name, FString ->
10393         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10394         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10395     | name, FUUID ->
10396         pr "    {\n";
10397         pr "      char s[33];\n";
10398         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10399         pr "      s[32] = 0;\n";
10400         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10401         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10402         pr "    }\n";
10403     | name, FBuffer ->
10404         pr "    {\n";
10405         pr "      int len = r->val[i].%s_len;\n" name;
10406         pr "      char s[len+1];\n";
10407         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10408         pr "      s[len] = 0;\n";
10409         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10410         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10411         pr "    }\n";
10412     | name, (FBytes|FUInt64|FInt64) ->
10413         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10414         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10415     | name, (FUInt32|FInt32) ->
10416         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10417         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10418     | name, FOptPercent ->
10419         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10420         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10421     | name, FChar ->
10422         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10423         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10424   ) cols;
10425   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10426   pr "  }\n";
10427   pr "  guestfs_free_%s_list (r);\n" typ;
10428   pr "  return jr;\n"
10429
10430 and generate_java_makefile_inc () =
10431   generate_header HashStyle GPLv2plus;
10432
10433   pr "java_built_sources = \\\n";
10434   List.iter (
10435     fun (typ, jtyp) ->
10436         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10437   ) java_structs;
10438   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10439
10440 and generate_haskell_hs () =
10441   generate_header HaskellStyle LGPLv2plus;
10442
10443   (* XXX We only know how to generate partial FFI for Haskell
10444    * at the moment.  Please help out!
10445    *)
10446   let can_generate style =
10447     match style with
10448     | RErr, _
10449     | RInt _, _
10450     | RInt64 _, _ -> true
10451     | RBool _, _
10452     | RConstString _, _
10453     | RConstOptString _, _
10454     | RString _, _
10455     | RStringList _, _
10456     | RStruct _, _
10457     | RStructList _, _
10458     | RHashtable _, _
10459     | RBufferOut _, _ -> false in
10460
10461   pr "\
10462 {-# INCLUDE <guestfs.h> #-}
10463 {-# LANGUAGE ForeignFunctionInterface #-}
10464
10465 module Guestfs (
10466   create";
10467
10468   (* List out the names of the actions we want to export. *)
10469   List.iter (
10470     fun (name, style, _, _, _, _, _) ->
10471       if can_generate style then pr ",\n  %s" name
10472   ) all_functions;
10473
10474   pr "
10475   ) where
10476
10477 -- Unfortunately some symbols duplicate ones already present
10478 -- in Prelude.  We don't know which, so we hard-code a list
10479 -- here.
10480 import Prelude hiding (truncate)
10481
10482 import Foreign
10483 import Foreign.C
10484 import Foreign.C.Types
10485 import IO
10486 import Control.Exception
10487 import Data.Typeable
10488
10489 data GuestfsS = GuestfsS            -- represents the opaque C struct
10490 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10491 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10492
10493 -- XXX define properly later XXX
10494 data PV = PV
10495 data VG = VG
10496 data LV = LV
10497 data IntBool = IntBool
10498 data Stat = Stat
10499 data StatVFS = StatVFS
10500 data Hashtable = Hashtable
10501
10502 foreign import ccall unsafe \"guestfs_create\" c_create
10503   :: IO GuestfsP
10504 foreign import ccall unsafe \"&guestfs_close\" c_close
10505   :: FunPtr (GuestfsP -> IO ())
10506 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10507   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10508
10509 create :: IO GuestfsH
10510 create = do
10511   p <- c_create
10512   c_set_error_handler p nullPtr nullPtr
10513   h <- newForeignPtr c_close p
10514   return h
10515
10516 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10517   :: GuestfsP -> IO CString
10518
10519 -- last_error :: GuestfsH -> IO (Maybe String)
10520 -- last_error h = do
10521 --   str <- withForeignPtr h (\\p -> c_last_error p)
10522 --   maybePeek peekCString str
10523
10524 last_error :: GuestfsH -> IO (String)
10525 last_error h = do
10526   str <- withForeignPtr h (\\p -> c_last_error p)
10527   if (str == nullPtr)
10528     then return \"no error\"
10529     else peekCString str
10530
10531 ";
10532
10533   (* Generate wrappers for each foreign function. *)
10534   List.iter (
10535     fun (name, style, _, _, _, _, _) ->
10536       if can_generate style then (
10537         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10538         pr "  :: ";
10539         generate_haskell_prototype ~handle:"GuestfsP" style;
10540         pr "\n";
10541         pr "\n";
10542         pr "%s :: " name;
10543         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10544         pr "\n";
10545         pr "%s %s = do\n" name
10546           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10547         pr "  r <- ";
10548         (* Convert pointer arguments using with* functions. *)
10549         List.iter (
10550           function
10551           | FileIn n
10552           | FileOut n
10553           | Pathname n | Device n | Dev_or_Path n | String n ->
10554               pr "withCString %s $ \\%s -> " n n
10555           | BufferIn n ->
10556               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10557           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10558           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10559           | Bool _ | Int _ | Int64 _ -> ()
10560         ) (snd style);
10561         (* Convert integer arguments. *)
10562         let args =
10563           List.map (
10564             function
10565             | Bool n -> sprintf "(fromBool %s)" n
10566             | Int n -> sprintf "(fromIntegral %s)" n
10567             | Int64 n -> sprintf "(fromIntegral %s)" n
10568             | FileIn n | FileOut n
10569             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10570             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10571           ) (snd style) in
10572         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10573           (String.concat " " ("p" :: args));
10574         (match fst style with
10575          | RErr | RInt _ | RInt64 _ | RBool _ ->
10576              pr "  if (r == -1)\n";
10577              pr "    then do\n";
10578              pr "      err <- last_error h\n";
10579              pr "      fail err\n";
10580          | RConstString _ | RConstOptString _ | RString _
10581          | RStringList _ | RStruct _
10582          | RStructList _ | RHashtable _ | RBufferOut _ ->
10583              pr "  if (r == nullPtr)\n";
10584              pr "    then do\n";
10585              pr "      err <- last_error h\n";
10586              pr "      fail err\n";
10587         );
10588         (match fst style with
10589          | RErr ->
10590              pr "    else return ()\n"
10591          | RInt _ ->
10592              pr "    else return (fromIntegral r)\n"
10593          | RInt64 _ ->
10594              pr "    else return (fromIntegral r)\n"
10595          | RBool _ ->
10596              pr "    else return (toBool r)\n"
10597          | RConstString _
10598          | RConstOptString _
10599          | RString _
10600          | RStringList _
10601          | RStruct _
10602          | RStructList _
10603          | RHashtable _
10604          | RBufferOut _ ->
10605              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10606         );
10607         pr "\n";
10608       )
10609   ) all_functions
10610
10611 and generate_haskell_prototype ~handle ?(hs = false) style =
10612   pr "%s -> " handle;
10613   let string = if hs then "String" else "CString" in
10614   let int = if hs then "Int" else "CInt" in
10615   let bool = if hs then "Bool" else "CInt" in
10616   let int64 = if hs then "Integer" else "Int64" in
10617   List.iter (
10618     fun arg ->
10619       (match arg with
10620        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10621        | BufferIn _ ->
10622            if hs then pr "String"
10623            else pr "CString -> CInt"
10624        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10625        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10626        | Bool _ -> pr "%s" bool
10627        | Int _ -> pr "%s" int
10628        | Int64 _ -> pr "%s" int
10629        | FileIn _ -> pr "%s" string
10630        | FileOut _ -> pr "%s" string
10631       );
10632       pr " -> ";
10633   ) (snd style);
10634   pr "IO (";
10635   (match fst style with
10636    | RErr -> if not hs then pr "CInt"
10637    | RInt _ -> pr "%s" int
10638    | RInt64 _ -> pr "%s" int64
10639    | RBool _ -> pr "%s" bool
10640    | RConstString _ -> pr "%s" string
10641    | RConstOptString _ -> pr "Maybe %s" string
10642    | RString _ -> pr "%s" string
10643    | RStringList _ -> pr "[%s]" string
10644    | RStruct (_, typ) ->
10645        let name = java_name_of_struct typ in
10646        pr "%s" name
10647    | RStructList (_, typ) ->
10648        let name = java_name_of_struct typ in
10649        pr "[%s]" name
10650    | RHashtable _ -> pr "Hashtable"
10651    | RBufferOut _ -> pr "%s" string
10652   );
10653   pr ")"
10654
10655 and generate_csharp () =
10656   generate_header CPlusPlusStyle LGPLv2plus;
10657
10658   (* XXX Make this configurable by the C# assembly users. *)
10659   let library = "libguestfs.so.0" in
10660
10661   pr "\
10662 // These C# bindings are highly experimental at present.
10663 //
10664 // Firstly they only work on Linux (ie. Mono).  In order to get them
10665 // to work on Windows (ie. .Net) you would need to port the library
10666 // itself to Windows first.
10667 //
10668 // The second issue is that some calls are known to be incorrect and
10669 // can cause Mono to segfault.  Particularly: calls which pass or
10670 // return string[], or return any structure value.  This is because
10671 // we haven't worked out the correct way to do this from C#.
10672 //
10673 // The third issue is that when compiling you get a lot of warnings.
10674 // We are not sure whether the warnings are important or not.
10675 //
10676 // Fourthly we do not routinely build or test these bindings as part
10677 // of the make && make check cycle, which means that regressions might
10678 // go unnoticed.
10679 //
10680 // Suggestions and patches are welcome.
10681
10682 // To compile:
10683 //
10684 // gmcs Libguestfs.cs
10685 // mono Libguestfs.exe
10686 //
10687 // (You'll probably want to add a Test class / static main function
10688 // otherwise this won't do anything useful).
10689
10690 using System;
10691 using System.IO;
10692 using System.Runtime.InteropServices;
10693 using System.Runtime.Serialization;
10694 using System.Collections;
10695
10696 namespace Guestfs
10697 {
10698   class Error : System.ApplicationException
10699   {
10700     public Error (string message) : base (message) {}
10701     protected Error (SerializationInfo info, StreamingContext context) {}
10702   }
10703
10704   class Guestfs
10705   {
10706     IntPtr _handle;
10707
10708     [DllImport (\"%s\")]
10709     static extern IntPtr guestfs_create ();
10710
10711     public Guestfs ()
10712     {
10713       _handle = guestfs_create ();
10714       if (_handle == IntPtr.Zero)
10715         throw new Error (\"could not create guestfs handle\");
10716     }
10717
10718     [DllImport (\"%s\")]
10719     static extern void guestfs_close (IntPtr h);
10720
10721     ~Guestfs ()
10722     {
10723       guestfs_close (_handle);
10724     }
10725
10726     [DllImport (\"%s\")]
10727     static extern string guestfs_last_error (IntPtr h);
10728
10729 " library library library;
10730
10731   (* Generate C# structure bindings.  We prefix struct names with
10732    * underscore because C# cannot have conflicting struct names and
10733    * method names (eg. "class stat" and "stat").
10734    *)
10735   List.iter (
10736     fun (typ, cols) ->
10737       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10738       pr "    public class _%s {\n" typ;
10739       List.iter (
10740         function
10741         | name, FChar -> pr "      char %s;\n" name
10742         | name, FString -> pr "      string %s;\n" name
10743         | name, FBuffer ->
10744             pr "      uint %s_len;\n" name;
10745             pr "      string %s;\n" name
10746         | name, FUUID ->
10747             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10748             pr "      string %s;\n" name
10749         | name, FUInt32 -> pr "      uint %s;\n" name
10750         | name, FInt32 -> pr "      int %s;\n" name
10751         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10752         | name, FInt64 -> pr "      long %s;\n" name
10753         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10754       ) cols;
10755       pr "    }\n";
10756       pr "\n"
10757   ) structs;
10758
10759   (* Generate C# function bindings. *)
10760   List.iter (
10761     fun (name, style, _, _, _, shortdesc, _) ->
10762       let rec csharp_return_type () =
10763         match fst style with
10764         | RErr -> "void"
10765         | RBool n -> "bool"
10766         | RInt n -> "int"
10767         | RInt64 n -> "long"
10768         | RConstString n
10769         | RConstOptString n
10770         | RString n
10771         | RBufferOut n -> "string"
10772         | RStruct (_,n) -> "_" ^ n
10773         | RHashtable n -> "Hashtable"
10774         | RStringList n -> "string[]"
10775         | RStructList (_,n) -> sprintf "_%s[]" n
10776
10777       and c_return_type () =
10778         match fst style with
10779         | RErr
10780         | RBool _
10781         | RInt _ -> "int"
10782         | RInt64 _ -> "long"
10783         | RConstString _
10784         | RConstOptString _
10785         | RString _
10786         | RBufferOut _ -> "string"
10787         | RStruct (_,n) -> "_" ^ n
10788         | RHashtable _
10789         | RStringList _ -> "string[]"
10790         | RStructList (_,n) -> sprintf "_%s[]" n
10791
10792       and c_error_comparison () =
10793         match fst style with
10794         | RErr
10795         | RBool _
10796         | RInt _
10797         | RInt64 _ -> "== -1"
10798         | RConstString _
10799         | RConstOptString _
10800         | RString _
10801         | RBufferOut _
10802         | RStruct (_,_)
10803         | RHashtable _
10804         | RStringList _
10805         | RStructList (_,_) -> "== null"
10806
10807       and generate_extern_prototype () =
10808         pr "    static extern %s guestfs_%s (IntPtr h"
10809           (c_return_type ()) name;
10810         List.iter (
10811           function
10812           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10813           | FileIn n | FileOut n
10814           | BufferIn n ->
10815               pr ", [In] string %s" n
10816           | StringList n | DeviceList n ->
10817               pr ", [In] string[] %s" n
10818           | Bool n ->
10819               pr ", bool %s" n
10820           | Int n ->
10821               pr ", int %s" n
10822           | Int64 n ->
10823               pr ", long %s" n
10824         ) (snd style);
10825         pr ");\n"
10826
10827       and generate_public_prototype () =
10828         pr "    public %s %s (" (csharp_return_type ()) name;
10829         let comma = ref false in
10830         let next () =
10831           if !comma then pr ", ";
10832           comma := true
10833         in
10834         List.iter (
10835           function
10836           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10837           | FileIn n | FileOut n
10838           | BufferIn n ->
10839               next (); pr "string %s" n
10840           | StringList n | DeviceList n ->
10841               next (); pr "string[] %s" n
10842           | Bool n ->
10843               next (); pr "bool %s" n
10844           | Int n ->
10845               next (); pr "int %s" n
10846           | Int64 n ->
10847               next (); pr "long %s" n
10848         ) (snd style);
10849         pr ")\n"
10850
10851       and generate_call () =
10852         pr "guestfs_%s (_handle" name;
10853         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10854         pr ");\n";
10855       in
10856
10857       pr "    [DllImport (\"%s\")]\n" library;
10858       generate_extern_prototype ();
10859       pr "\n";
10860       pr "    /// <summary>\n";
10861       pr "    /// %s\n" shortdesc;
10862       pr "    /// </summary>\n";
10863       generate_public_prototype ();
10864       pr "    {\n";
10865       pr "      %s r;\n" (c_return_type ());
10866       pr "      r = ";
10867       generate_call ();
10868       pr "      if (r %s)\n" (c_error_comparison ());
10869       pr "        throw new Error (guestfs_last_error (_handle));\n";
10870       (match fst style with
10871        | RErr -> ()
10872        | RBool _ ->
10873            pr "      return r != 0 ? true : false;\n"
10874        | RHashtable _ ->
10875            pr "      Hashtable rr = new Hashtable ();\n";
10876            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10877            pr "        rr.Add (r[i], r[i+1]);\n";
10878            pr "      return rr;\n"
10879        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10880        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10881        | RStructList _ ->
10882            pr "      return r;\n"
10883       );
10884       pr "    }\n";
10885       pr "\n";
10886   ) all_functions_sorted;
10887
10888   pr "  }
10889 }
10890 "
10891
10892 and generate_bindtests () =
10893   generate_header CStyle LGPLv2plus;
10894
10895   pr "\
10896 #include <stdio.h>
10897 #include <stdlib.h>
10898 #include <inttypes.h>
10899 #include <string.h>
10900
10901 #include \"guestfs.h\"
10902 #include \"guestfs-internal.h\"
10903 #include \"guestfs-internal-actions.h\"
10904 #include \"guestfs_protocol.h\"
10905
10906 #define error guestfs_error
10907 #define safe_calloc guestfs_safe_calloc
10908 #define safe_malloc guestfs_safe_malloc
10909
10910 static void
10911 print_strings (char *const *argv)
10912 {
10913   int argc;
10914
10915   printf (\"[\");
10916   for (argc = 0; argv[argc] != NULL; ++argc) {
10917     if (argc > 0) printf (\", \");
10918     printf (\"\\\"%%s\\\"\", argv[argc]);
10919   }
10920   printf (\"]\\n\");
10921 }
10922
10923 /* The test0 function prints its parameters to stdout. */
10924 ";
10925
10926   let test0, tests =
10927     match test_functions with
10928     | [] -> assert false
10929     | test0 :: tests -> test0, tests in
10930
10931   let () =
10932     let (name, style, _, _, _, _, _) = test0 in
10933     generate_prototype ~extern:false ~semicolon:false ~newline:true
10934       ~handle:"g" ~prefix:"guestfs__" name style;
10935     pr "{\n";
10936     List.iter (
10937       function
10938       | Pathname n
10939       | Device n | Dev_or_Path n
10940       | String n
10941       | FileIn n
10942       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10943       | BufferIn n ->
10944           pr "  for (size_t i = 0; i < %s_size; ++i)\n" n;
10945           pr "    printf (\"<%%02x>\", %s[i]);\n" n;
10946           pr "  printf (\"\\n\");\n"
10947       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10948       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10949       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10950       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10951       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10952     ) (snd style);
10953     pr "  /* Java changes stdout line buffering so we need this: */\n";
10954     pr "  fflush (stdout);\n";
10955     pr "  return 0;\n";
10956     pr "}\n";
10957     pr "\n" in
10958
10959   List.iter (
10960     fun (name, style, _, _, _, _, _) ->
10961       if String.sub name (String.length name - 3) 3 <> "err" then (
10962         pr "/* Test normal return. */\n";
10963         generate_prototype ~extern:false ~semicolon:false ~newline:true
10964           ~handle:"g" ~prefix:"guestfs__" name style;
10965         pr "{\n";
10966         (match fst style with
10967          | RErr ->
10968              pr "  return 0;\n"
10969          | RInt _ ->
10970              pr "  int r;\n";
10971              pr "  sscanf (val, \"%%d\", &r);\n";
10972              pr "  return r;\n"
10973          | RInt64 _ ->
10974              pr "  int64_t r;\n";
10975              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10976              pr "  return r;\n"
10977          | RBool _ ->
10978              pr "  return STREQ (val, \"true\");\n"
10979          | RConstString _
10980          | RConstOptString _ ->
10981              (* Can't return the input string here.  Return a static
10982               * string so we ensure we get a segfault if the caller
10983               * tries to free it.
10984               *)
10985              pr "  return \"static string\";\n"
10986          | RString _ ->
10987              pr "  return strdup (val);\n"
10988          | RStringList _ ->
10989              pr "  char **strs;\n";
10990              pr "  int n, i;\n";
10991              pr "  sscanf (val, \"%%d\", &n);\n";
10992              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10993              pr "  for (i = 0; i < n; ++i) {\n";
10994              pr "    strs[i] = safe_malloc (g, 16);\n";
10995              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10996              pr "  }\n";
10997              pr "  strs[n] = NULL;\n";
10998              pr "  return strs;\n"
10999          | RStruct (_, typ) ->
11000              pr "  struct guestfs_%s *r;\n" typ;
11001              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11002              pr "  return r;\n"
11003          | RStructList (_, typ) ->
11004              pr "  struct guestfs_%s_list *r;\n" typ;
11005              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11006              pr "  sscanf (val, \"%%d\", &r->len);\n";
11007              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11008              pr "  return r;\n"
11009          | RHashtable _ ->
11010              pr "  char **strs;\n";
11011              pr "  int n, i;\n";
11012              pr "  sscanf (val, \"%%d\", &n);\n";
11013              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11014              pr "  for (i = 0; i < n; ++i) {\n";
11015              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11016              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11017              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11018              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11019              pr "  }\n";
11020              pr "  strs[n*2] = NULL;\n";
11021              pr "  return strs;\n"
11022          | RBufferOut _ ->
11023              pr "  return strdup (val);\n"
11024         );
11025         pr "}\n";
11026         pr "\n"
11027       ) else (
11028         pr "/* Test error return. */\n";
11029         generate_prototype ~extern:false ~semicolon:false ~newline:true
11030           ~handle:"g" ~prefix:"guestfs__" name style;
11031         pr "{\n";
11032         pr "  error (g, \"error\");\n";
11033         (match fst style with
11034          | RErr | RInt _ | RInt64 _ | RBool _ ->
11035              pr "  return -1;\n"
11036          | RConstString _ | RConstOptString _
11037          | RString _ | RStringList _ | RStruct _
11038          | RStructList _
11039          | RHashtable _
11040          | RBufferOut _ ->
11041              pr "  return NULL;\n"
11042         );
11043         pr "}\n";
11044         pr "\n"
11045       )
11046   ) tests
11047
11048 and generate_ocaml_bindtests () =
11049   generate_header OCamlStyle GPLv2plus;
11050
11051   pr "\
11052 let () =
11053   let g = Guestfs.create () in
11054 ";
11055
11056   let mkargs args =
11057     String.concat " " (
11058       List.map (
11059         function
11060         | CallString s -> "\"" ^ s ^ "\""
11061         | CallOptString None -> "None"
11062         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11063         | CallStringList xs ->
11064             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11065         | CallInt i when i >= 0 -> string_of_int i
11066         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11067         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11068         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11069         | CallBool b -> string_of_bool b
11070         | CallBuffer s -> sprintf "%S" s
11071       ) args
11072     )
11073   in
11074
11075   generate_lang_bindtests (
11076     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11077   );
11078
11079   pr "print_endline \"EOF\"\n"
11080
11081 and generate_perl_bindtests () =
11082   pr "#!/usr/bin/perl -w\n";
11083   generate_header HashStyle GPLv2plus;
11084
11085   pr "\
11086 use strict;
11087
11088 use Sys::Guestfs;
11089
11090 my $g = Sys::Guestfs->new ();
11091 ";
11092
11093   let mkargs args =
11094     String.concat ", " (
11095       List.map (
11096         function
11097         | CallString s -> "\"" ^ s ^ "\""
11098         | CallOptString None -> "undef"
11099         | CallOptString (Some s) -> sprintf "\"%s\"" s
11100         | CallStringList xs ->
11101             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11102         | CallInt i -> string_of_int i
11103         | CallInt64 i -> Int64.to_string i
11104         | CallBool b -> if b then "1" else "0"
11105         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11106       ) args
11107     )
11108   in
11109
11110   generate_lang_bindtests (
11111     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11112   );
11113
11114   pr "print \"EOF\\n\"\n"
11115
11116 and generate_python_bindtests () =
11117   generate_header HashStyle GPLv2plus;
11118
11119   pr "\
11120 import guestfs
11121
11122 g = guestfs.GuestFS ()
11123 ";
11124
11125   let mkargs args =
11126     String.concat ", " (
11127       List.map (
11128         function
11129         | CallString s -> "\"" ^ s ^ "\""
11130         | CallOptString None -> "None"
11131         | CallOptString (Some s) -> sprintf "\"%s\"" s
11132         | CallStringList xs ->
11133             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11134         | CallInt i -> string_of_int i
11135         | CallInt64 i -> Int64.to_string i
11136         | CallBool b -> if b then "1" else "0"
11137         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11138       ) args
11139     )
11140   in
11141
11142   generate_lang_bindtests (
11143     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11144   );
11145
11146   pr "print \"EOF\"\n"
11147
11148 and generate_ruby_bindtests () =
11149   generate_header HashStyle GPLv2plus;
11150
11151   pr "\
11152 require 'guestfs'
11153
11154 g = Guestfs::create()
11155 ";
11156
11157   let mkargs args =
11158     String.concat ", " (
11159       List.map (
11160         function
11161         | CallString s -> "\"" ^ s ^ "\""
11162         | CallOptString None -> "nil"
11163         | CallOptString (Some s) -> sprintf "\"%s\"" s
11164         | CallStringList xs ->
11165             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11166         | CallInt i -> string_of_int i
11167         | CallInt64 i -> Int64.to_string i
11168         | CallBool b -> string_of_bool b
11169         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11170       ) args
11171     )
11172   in
11173
11174   generate_lang_bindtests (
11175     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11176   );
11177
11178   pr "print \"EOF\\n\"\n"
11179
11180 and generate_java_bindtests () =
11181   generate_header CStyle GPLv2plus;
11182
11183   pr "\
11184 import com.redhat.et.libguestfs.*;
11185
11186 public class Bindtests {
11187     public static void main (String[] argv)
11188     {
11189         try {
11190             GuestFS g = new GuestFS ();
11191 ";
11192
11193   let mkargs args =
11194     String.concat ", " (
11195       List.map (
11196         function
11197         | CallString s -> "\"" ^ s ^ "\""
11198         | CallOptString None -> "null"
11199         | CallOptString (Some s) -> sprintf "\"%s\"" s
11200         | CallStringList xs ->
11201             "new String[]{" ^
11202               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11203         | CallInt i -> string_of_int i
11204         | CallInt64 i -> Int64.to_string i
11205         | CallBool b -> string_of_bool b
11206         | CallBuffer s ->
11207             "new byte[] { " ^ String.concat "," (
11208               map_chars (fun c -> string_of_int (Char.code c)) s
11209             ) ^ " }"
11210       ) args
11211     )
11212   in
11213
11214   generate_lang_bindtests (
11215     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11216   );
11217
11218   pr "
11219             System.out.println (\"EOF\");
11220         }
11221         catch (Exception exn) {
11222             System.err.println (exn);
11223             System.exit (1);
11224         }
11225     }
11226 }
11227 "
11228
11229 and generate_haskell_bindtests () =
11230   generate_header HaskellStyle GPLv2plus;
11231
11232   pr "\
11233 module Bindtests where
11234 import qualified Guestfs
11235
11236 main = do
11237   g <- Guestfs.create
11238 ";
11239
11240   let mkargs args =
11241     String.concat " " (
11242       List.map (
11243         function
11244         | CallString s -> "\"" ^ s ^ "\""
11245         | CallOptString None -> "Nothing"
11246         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11247         | CallStringList xs ->
11248             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11249         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11250         | CallInt i -> string_of_int i
11251         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11252         | CallInt64 i -> Int64.to_string i
11253         | CallBool true -> "True"
11254         | CallBool false -> "False"
11255         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11256       ) args
11257     )
11258   in
11259
11260   generate_lang_bindtests (
11261     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11262   );
11263
11264   pr "  putStrLn \"EOF\"\n"
11265
11266 (* Language-independent bindings tests - we do it this way to
11267  * ensure there is parity in testing bindings across all languages.
11268  *)
11269 and generate_lang_bindtests call =
11270   call "test0" [CallString "abc"; CallOptString (Some "def");
11271                 CallStringList []; CallBool false;
11272                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11273                 CallBuffer "abc\000abc"];
11274   call "test0" [CallString "abc"; CallOptString None;
11275                 CallStringList []; CallBool false;
11276                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11277                 CallBuffer "abc\000abc"];
11278   call "test0" [CallString ""; CallOptString (Some "def");
11279                 CallStringList []; CallBool false;
11280                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11281                 CallBuffer "abc\000abc"];
11282   call "test0" [CallString ""; CallOptString (Some "");
11283                 CallStringList []; CallBool false;
11284                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11285                 CallBuffer "abc\000abc"];
11286   call "test0" [CallString "abc"; CallOptString (Some "def");
11287                 CallStringList ["1"]; CallBool false;
11288                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11289                 CallBuffer "abc\000abc"];
11290   call "test0" [CallString "abc"; CallOptString (Some "def");
11291                 CallStringList ["1"; "2"]; CallBool false;
11292                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11293                 CallBuffer "abc\000abc"];
11294   call "test0" [CallString "abc"; CallOptString (Some "def");
11295                 CallStringList ["1"]; CallBool true;
11296                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11297                 CallBuffer "abc\000abc"];
11298   call "test0" [CallString "abc"; CallOptString (Some "def");
11299                 CallStringList ["1"]; CallBool false;
11300                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11301                 CallBuffer "abc\000abc"];
11302   call "test0" [CallString "abc"; CallOptString (Some "def");
11303                 CallStringList ["1"]; CallBool false;
11304                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11305                 CallBuffer "abc\000abc"];
11306   call "test0" [CallString "abc"; CallOptString (Some "def");
11307                 CallStringList ["1"]; CallBool false;
11308                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11309                 CallBuffer "abc\000abc"];
11310   call "test0" [CallString "abc"; CallOptString (Some "def");
11311                 CallStringList ["1"]; CallBool false;
11312                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11313                 CallBuffer "abc\000abc"];
11314   call "test0" [CallString "abc"; CallOptString (Some "def");
11315                 CallStringList ["1"]; CallBool false;
11316                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11317                 CallBuffer "abc\000abc"];
11318   call "test0" [CallString "abc"; CallOptString (Some "def");
11319                 CallStringList ["1"]; CallBool false;
11320                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11321                 CallBuffer "abc\000abc"]
11322
11323 (* XXX Add here tests of the return and error functions. *)
11324
11325 (* Code to generator bindings for virt-inspector.  Currently only
11326  * implemented for OCaml code (for virt-p2v 2.0).
11327  *)
11328 let rng_input = "inspector/virt-inspector.rng"
11329
11330 (* Read the input file and parse it into internal structures.  This is
11331  * by no means a complete RELAX NG parser, but is just enough to be
11332  * able to parse the specific input file.
11333  *)
11334 type rng =
11335   | Element of string * rng list        (* <element name=name/> *)
11336   | Attribute of string * rng list        (* <attribute name=name/> *)
11337   | Interleave of rng list                (* <interleave/> *)
11338   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11339   | OneOrMore of rng                        (* <oneOrMore/> *)
11340   | Optional of rng                        (* <optional/> *)
11341   | Choice of string list                (* <choice><value/>*</choice> *)
11342   | Value of string                        (* <value>str</value> *)
11343   | Text                                (* <text/> *)
11344
11345 let rec string_of_rng = function
11346   | Element (name, xs) ->
11347       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11348   | Attribute (name, xs) ->
11349       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11350   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11351   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11352   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11353   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11354   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11355   | Value value -> "Value \"" ^ value ^ "\""
11356   | Text -> "Text"
11357
11358 and string_of_rng_list xs =
11359   String.concat ", " (List.map string_of_rng xs)
11360
11361 let rec parse_rng ?defines context = function
11362   | [] -> []
11363   | Xml.Element ("element", ["name", name], children) :: rest ->
11364       Element (name, parse_rng ?defines context children)
11365       :: parse_rng ?defines context rest
11366   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11367       Attribute (name, parse_rng ?defines context children)
11368       :: parse_rng ?defines context rest
11369   | Xml.Element ("interleave", [], children) :: rest ->
11370       Interleave (parse_rng ?defines context children)
11371       :: parse_rng ?defines context rest
11372   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11373       let rng = parse_rng ?defines context [child] in
11374       (match rng with
11375        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11376        | _ ->
11377            failwithf "%s: <zeroOrMore> contains more than one child element"
11378              context
11379       )
11380   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11381       let rng = parse_rng ?defines context [child] in
11382       (match rng with
11383        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11384        | _ ->
11385            failwithf "%s: <oneOrMore> contains more than one child element"
11386              context
11387       )
11388   | Xml.Element ("optional", [], [child]) :: rest ->
11389       let rng = parse_rng ?defines context [child] in
11390       (match rng with
11391        | [child] -> Optional child :: parse_rng ?defines context rest
11392        | _ ->
11393            failwithf "%s: <optional> contains more than one child element"
11394              context
11395       )
11396   | Xml.Element ("choice", [], children) :: rest ->
11397       let values = List.map (
11398         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11399         | _ ->
11400             failwithf "%s: can't handle anything except <value> in <choice>"
11401               context
11402       ) children in
11403       Choice values
11404       :: parse_rng ?defines context rest
11405   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11406       Value value :: parse_rng ?defines context rest
11407   | Xml.Element ("text", [], []) :: rest ->
11408       Text :: parse_rng ?defines context rest
11409   | Xml.Element ("ref", ["name", name], []) :: rest ->
11410       (* Look up the reference.  Because of limitations in this parser,
11411        * we can't handle arbitrarily nested <ref> yet.  You can only
11412        * use <ref> from inside <start>.
11413        *)
11414       (match defines with
11415        | None ->
11416            failwithf "%s: contains <ref>, but no refs are defined yet" context
11417        | Some map ->
11418            let rng = StringMap.find name map in
11419            rng @ parse_rng ?defines context rest
11420       )
11421   | x :: _ ->
11422       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11423
11424 let grammar =
11425   let xml = Xml.parse_file rng_input in
11426   match xml with
11427   | Xml.Element ("grammar", _,
11428                  Xml.Element ("start", _, gram) :: defines) ->
11429       (* The <define/> elements are referenced in the <start> section,
11430        * so build a map of those first.
11431        *)
11432       let defines = List.fold_left (
11433         fun map ->
11434           function Xml.Element ("define", ["name", name], defn) ->
11435             StringMap.add name defn map
11436           | _ ->
11437               failwithf "%s: expected <define name=name/>" rng_input
11438       ) StringMap.empty defines in
11439       let defines = StringMap.mapi parse_rng defines in
11440
11441       (* Parse the <start> clause, passing the defines. *)
11442       parse_rng ~defines "<start>" gram
11443   | _ ->
11444       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11445         rng_input
11446
11447 let name_of_field = function
11448   | Element (name, _) | Attribute (name, _)
11449   | ZeroOrMore (Element (name, _))
11450   | OneOrMore (Element (name, _))
11451   | Optional (Element (name, _)) -> name
11452   | Optional (Attribute (name, _)) -> name
11453   | Text -> (* an unnamed field in an element *)
11454       "data"
11455   | rng ->
11456       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11457
11458 (* At the moment this function only generates OCaml types.  However we
11459  * should parameterize it later so it can generate types/structs in a
11460  * variety of languages.
11461  *)
11462 let generate_types xs =
11463   (* A simple type is one that can be printed out directly, eg.
11464    * "string option".  A complex type is one which has a name and has
11465    * to be defined via another toplevel definition, eg. a struct.
11466    *
11467    * generate_type generates code for either simple or complex types.
11468    * In the simple case, it returns the string ("string option").  In
11469    * the complex case, it returns the name ("mountpoint").  In the
11470    * complex case it has to print out the definition before returning,
11471    * so it should only be called when we are at the beginning of a
11472    * new line (BOL context).
11473    *)
11474   let rec generate_type = function
11475     | Text ->                                (* string *)
11476         "string", true
11477     | Choice values ->                        (* [`val1|`val2|...] *)
11478         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11479     | ZeroOrMore rng ->                        (* <rng> list *)
11480         let t, is_simple = generate_type rng in
11481         t ^ " list (* 0 or more *)", is_simple
11482     | OneOrMore rng ->                        (* <rng> list *)
11483         let t, is_simple = generate_type rng in
11484         t ^ " list (* 1 or more *)", is_simple
11485                                         (* virt-inspector hack: bool *)
11486     | Optional (Attribute (name, [Value "1"])) ->
11487         "bool", true
11488     | Optional rng ->                        (* <rng> list *)
11489         let t, is_simple = generate_type rng in
11490         t ^ " option", is_simple
11491                                         (* type name = { fields ... } *)
11492     | Element (name, fields) when is_attrs_interleave fields ->
11493         generate_type_struct name (get_attrs_interleave fields)
11494     | Element (name, [field])                (* type name = field *)
11495     | Attribute (name, [field]) ->
11496         let t, is_simple = generate_type field in
11497         if is_simple then (t, true)
11498         else (
11499           pr "type %s = %s\n" name t;
11500           name, false
11501         )
11502     | Element (name, fields) ->              (* type name = { fields ... } *)
11503         generate_type_struct name fields
11504     | rng ->
11505         failwithf "generate_type failed at: %s" (string_of_rng rng)
11506
11507   and is_attrs_interleave = function
11508     | [Interleave _] -> true
11509     | Attribute _ :: fields -> is_attrs_interleave fields
11510     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11511     | _ -> false
11512
11513   and get_attrs_interleave = function
11514     | [Interleave fields] -> fields
11515     | ((Attribute _) as field) :: fields
11516     | ((Optional (Attribute _)) as field) :: fields ->
11517         field :: get_attrs_interleave fields
11518     | _ -> assert false
11519
11520   and generate_types xs =
11521     List.iter (fun x -> ignore (generate_type x)) xs
11522
11523   and generate_type_struct name fields =
11524     (* Calculate the types of the fields first.  We have to do this
11525      * before printing anything so we are still in BOL context.
11526      *)
11527     let types = List.map fst (List.map generate_type fields) in
11528
11529     (* Special case of a struct containing just a string and another
11530      * field.  Turn it into an assoc list.
11531      *)
11532     match types with
11533     | ["string"; other] ->
11534         let fname1, fname2 =
11535           match fields with
11536           | [f1; f2] -> name_of_field f1, name_of_field f2
11537           | _ -> assert false in
11538         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11539         name, false
11540
11541     | types ->
11542         pr "type %s = {\n" name;
11543         List.iter (
11544           fun (field, ftype) ->
11545             let fname = name_of_field field in
11546             pr "  %s_%s : %s;\n" name fname ftype
11547         ) (List.combine fields types);
11548         pr "}\n";
11549         (* Return the name of this type, and
11550          * false because it's not a simple type.
11551          *)
11552         name, false
11553   in
11554
11555   generate_types xs
11556
11557 let generate_parsers xs =
11558   (* As for generate_type above, generate_parser makes a parser for
11559    * some type, and returns the name of the parser it has generated.
11560    * Because it (may) need to print something, it should always be
11561    * called in BOL context.
11562    *)
11563   let rec generate_parser = function
11564     | Text ->                                (* string *)
11565         "string_child_or_empty"
11566     | Choice values ->                        (* [`val1|`val2|...] *)
11567         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11568           (String.concat "|"
11569              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11570     | ZeroOrMore rng ->                        (* <rng> list *)
11571         let pa = generate_parser rng in
11572         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11573     | OneOrMore rng ->                        (* <rng> list *)
11574         let pa = generate_parser rng in
11575         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11576                                         (* virt-inspector hack: bool *)
11577     | Optional (Attribute (name, [Value "1"])) ->
11578         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11579     | Optional rng ->                        (* <rng> list *)
11580         let pa = generate_parser rng in
11581         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11582                                         (* type name = { fields ... } *)
11583     | Element (name, fields) when is_attrs_interleave fields ->
11584         generate_parser_struct name (get_attrs_interleave fields)
11585     | Element (name, [field]) ->        (* type name = field *)
11586         let pa = generate_parser field in
11587         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11588         pr "let %s =\n" parser_name;
11589         pr "  %s\n" pa;
11590         pr "let parse_%s = %s\n" name parser_name;
11591         parser_name
11592     | Attribute (name, [field]) ->
11593         let pa = generate_parser field in
11594         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11595         pr "let %s =\n" parser_name;
11596         pr "  %s\n" pa;
11597         pr "let parse_%s = %s\n" name parser_name;
11598         parser_name
11599     | Element (name, fields) ->              (* type name = { fields ... } *)
11600         generate_parser_struct name ([], fields)
11601     | rng ->
11602         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11603
11604   and is_attrs_interleave = function
11605     | [Interleave _] -> true
11606     | Attribute _ :: fields -> is_attrs_interleave fields
11607     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11608     | _ -> false
11609
11610   and get_attrs_interleave = function
11611     | [Interleave fields] -> [], fields
11612     | ((Attribute _) as field) :: fields
11613     | ((Optional (Attribute _)) as field) :: fields ->
11614         let attrs, interleaves = get_attrs_interleave fields in
11615         (field :: attrs), interleaves
11616     | _ -> assert false
11617
11618   and generate_parsers xs =
11619     List.iter (fun x -> ignore (generate_parser x)) xs
11620
11621   and generate_parser_struct name (attrs, interleaves) =
11622     (* Generate parsers for the fields first.  We have to do this
11623      * before printing anything so we are still in BOL context.
11624      *)
11625     let fields = attrs @ interleaves in
11626     let pas = List.map generate_parser fields in
11627
11628     (* Generate an intermediate tuple from all the fields first.
11629      * If the type is just a string + another field, then we will
11630      * return this directly, otherwise it is turned into a record.
11631      *
11632      * RELAX NG note: This code treats <interleave> and plain lists of
11633      * fields the same.  In other words, it doesn't bother enforcing
11634      * any ordering of fields in the XML.
11635      *)
11636     pr "let parse_%s x =\n" name;
11637     pr "  let t = (\n    ";
11638     let comma = ref false in
11639     List.iter (
11640       fun x ->
11641         if !comma then pr ",\n    ";
11642         comma := true;
11643         match x with
11644         | Optional (Attribute (fname, [field])), pa ->
11645             pr "%s x" pa
11646         | Optional (Element (fname, [field])), pa ->
11647             pr "%s (optional_child %S x)" pa fname
11648         | Attribute (fname, [Text]), _ ->
11649             pr "attribute %S x" fname
11650         | (ZeroOrMore _ | OneOrMore _), pa ->
11651             pr "%s x" pa
11652         | Text, pa ->
11653             pr "%s x" pa
11654         | (field, pa) ->
11655             let fname = name_of_field field in
11656             pr "%s (child %S x)" pa fname
11657     ) (List.combine fields pas);
11658     pr "\n  ) in\n";
11659
11660     (match fields with
11661      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11662          pr "  t\n"
11663
11664      | _ ->
11665          pr "  (Obj.magic t : %s)\n" name
11666 (*
11667          List.iter (
11668            function
11669            | (Optional (Attribute (fname, [field])), pa) ->
11670                pr "  %s_%s =\n" name fname;
11671                pr "    %s x;\n" pa
11672            | (Optional (Element (fname, [field])), pa) ->
11673                pr "  %s_%s =\n" name fname;
11674                pr "    (let x = optional_child %S x in\n" fname;
11675                pr "     %s x);\n" pa
11676            | (field, pa) ->
11677                let fname = name_of_field field in
11678                pr "  %s_%s =\n" name fname;
11679                pr "    (let x = child %S x in\n" fname;
11680                pr "     %s x);\n" pa
11681          ) (List.combine fields pas);
11682          pr "}\n"
11683 *)
11684     );
11685     sprintf "parse_%s" name
11686   in
11687
11688   generate_parsers xs
11689
11690 (* Generate ocaml/guestfs_inspector.mli. *)
11691 let generate_ocaml_inspector_mli () =
11692   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11693
11694   pr "\
11695 (** This is an OCaml language binding to the external [virt-inspector]
11696     program.
11697
11698     For more information, please read the man page [virt-inspector(1)].
11699 *)
11700
11701 ";
11702
11703   generate_types grammar;
11704   pr "(** The nested information returned from the {!inspect} function. *)\n";
11705   pr "\n";
11706
11707   pr "\
11708 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11709 (** To inspect a libvirt domain called [name], pass a singleton
11710     list: [inspect [name]].  When using libvirt only, you may
11711     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11712
11713     To inspect a disk image or images, pass a list of the filenames
11714     of the disk images: [inspect filenames]
11715
11716     This function inspects the given guest or disk images and
11717     returns a list of operating system(s) found and a large amount
11718     of information about them.  In the vast majority of cases,
11719     a virtual machine only contains a single operating system.
11720
11721     If the optional [~xml] parameter is given, then this function
11722     skips running the external virt-inspector program and just
11723     parses the given XML directly (which is expected to be XML
11724     produced from a previous run of virt-inspector).  The list of
11725     names and connect URI are ignored in this case.
11726
11727     This function can throw a wide variety of exceptions, for example
11728     if the external virt-inspector program cannot be found, or if
11729     it doesn't generate valid XML.
11730 *)
11731 "
11732
11733 (* Generate ocaml/guestfs_inspector.ml. *)
11734 let generate_ocaml_inspector_ml () =
11735   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11736
11737   pr "open Unix\n";
11738   pr "\n";
11739
11740   generate_types grammar;
11741   pr "\n";
11742
11743   pr "\
11744 (* Misc functions which are used by the parser code below. *)
11745 let first_child = function
11746   | Xml.Element (_, _, c::_) -> c
11747   | Xml.Element (name, _, []) ->
11748       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11749   | Xml.PCData str ->
11750       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11751
11752 let string_child_or_empty = function
11753   | Xml.Element (_, _, [Xml.PCData s]) -> s
11754   | Xml.Element (_, _, []) -> \"\"
11755   | Xml.Element (x, _, _) ->
11756       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11757                 x ^ \" instead\")
11758   | Xml.PCData str ->
11759       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11760
11761 let optional_child name xml =
11762   let children = Xml.children xml in
11763   try
11764     Some (List.find (function
11765                      | Xml.Element (n, _, _) when n = name -> true
11766                      | _ -> false) children)
11767   with
11768     Not_found -> None
11769
11770 let child name xml =
11771   match optional_child name xml with
11772   | Some c -> c
11773   | None ->
11774       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11775
11776 let attribute name xml =
11777   try Xml.attrib xml name
11778   with Xml.No_attribute _ ->
11779     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11780
11781 ";
11782
11783   generate_parsers grammar;
11784   pr "\n";
11785
11786   pr "\
11787 (* Run external virt-inspector, then use parser to parse the XML. *)
11788 let inspect ?connect ?xml names =
11789   let xml =
11790     match xml with
11791     | None ->
11792         if names = [] then invalid_arg \"inspect: no names given\";
11793         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11794           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11795           names in
11796         let cmd = List.map Filename.quote cmd in
11797         let cmd = String.concat \" \" cmd in
11798         let chan = open_process_in cmd in
11799         let xml = Xml.parse_in chan in
11800         (match close_process_in chan with
11801          | WEXITED 0 -> ()
11802          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11803          | WSIGNALED i | WSTOPPED i ->
11804              failwith (\"external virt-inspector command died or stopped on sig \" ^
11805                        string_of_int i)
11806         );
11807         xml
11808     | Some doc ->
11809         Xml.parse_string doc in
11810   parse_operatingsystems xml
11811 "
11812
11813 and generate_max_proc_nr () =
11814   pr "%d\n" max_proc_nr
11815
11816 let output_to filename k =
11817   let filename_new = filename ^ ".new" in
11818   chan := open_out filename_new;
11819   k ();
11820   close_out !chan;
11821   chan := Pervasives.stdout;
11822
11823   (* Is the new file different from the current file? *)
11824   if Sys.file_exists filename && files_equal filename filename_new then
11825     unlink filename_new                 (* same, so skip it *)
11826   else (
11827     (* different, overwrite old one *)
11828     (try chmod filename 0o644 with Unix_error _ -> ());
11829     rename filename_new filename;
11830     chmod filename 0o444;
11831     printf "written %s\n%!" filename;
11832   )
11833
11834 let perror msg = function
11835   | Unix_error (err, _, _) ->
11836       eprintf "%s: %s\n" msg (error_message err)
11837   | exn ->
11838       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11839
11840 (* Main program. *)
11841 let () =
11842   let lock_fd =
11843     try openfile "HACKING" [O_RDWR] 0
11844     with
11845     | Unix_error (ENOENT, _, _) ->
11846         eprintf "\
11847 You are probably running this from the wrong directory.
11848 Run it from the top source directory using the command
11849   src/generator.ml
11850 ";
11851         exit 1
11852     | exn ->
11853         perror "open: HACKING" exn;
11854         exit 1 in
11855
11856   (* Acquire a lock so parallel builds won't try to run the generator
11857    * twice at the same time.  Subsequent builds will wait for the first
11858    * one to finish.  Note the lock is released implicitly when the
11859    * program exits.
11860    *)
11861   (try lockf lock_fd F_LOCK 1
11862    with exn ->
11863      perror "lock: HACKING" exn;
11864      exit 1);
11865
11866   check_functions ();
11867
11868   output_to "src/guestfs_protocol.x" generate_xdr;
11869   output_to "src/guestfs-structs.h" generate_structs_h;
11870   output_to "src/guestfs-actions.h" generate_actions_h;
11871   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11872   output_to "src/guestfs-actions.c" generate_client_actions;
11873   output_to "src/guestfs-bindtests.c" generate_bindtests;
11874   output_to "src/guestfs-structs.pod" generate_structs_pod;
11875   output_to "src/guestfs-actions.pod" generate_actions_pod;
11876   output_to "src/guestfs-availability.pod" generate_availability_pod;
11877   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11878   output_to "src/libguestfs.syms" generate_linker_script;
11879   output_to "daemon/actions.h" generate_daemon_actions_h;
11880   output_to "daemon/stubs.c" generate_daemon_actions;
11881   output_to "daemon/names.c" generate_daemon_names;
11882   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11883   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11884   output_to "capitests/tests.c" generate_tests;
11885   output_to "fish/cmds.c" generate_fish_cmds;
11886   output_to "fish/completion.c" generate_fish_completion;
11887   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11888   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11889   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11890   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11891   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11892   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11893   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11894   output_to "perl/Guestfs.xs" generate_perl_xs;
11895   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11896   output_to "perl/bindtests.pl" generate_perl_bindtests;
11897   output_to "python/guestfs-py.c" generate_python_c;
11898   output_to "python/guestfs.py" generate_python_py;
11899   output_to "python/bindtests.py" generate_python_bindtests;
11900   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11901   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11902   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11903
11904   List.iter (
11905     fun (typ, jtyp) ->
11906       let cols = cols_of_struct typ in
11907       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11908       output_to filename (generate_java_struct jtyp cols);
11909   ) java_structs;
11910
11911   output_to "java/Makefile.inc" generate_java_makefile_inc;
11912   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11913   output_to "java/Bindtests.java" generate_java_bindtests;
11914   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11915   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11916   output_to "csharp/Libguestfs.cs" generate_csharp;
11917
11918   (* Always generate this file last, and unconditionally.  It's used
11919    * by the Makefile to know when we must re-run the generator.
11920    *)
11921   let chan = open_out "src/stamp-generator" in
11922   fprintf chan "1\n";
11923   close_out chan;
11924
11925   printf "generated %d lines of code\n" !lines