Clarify sparse behaviour of truncate-size command.
[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, [OptString "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, [OptString "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 dynamic linker functions
798 to find out if this symbol exists (if it doesn't, then
799 it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 I<Note:> Don't use this call to test for availability
811 of features.  Distro backports makes this unreliable.  Use
812 C<guestfs_available> instead.");
813
814   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
815    [InitNone, Always, TestOutputTrue (
816       [["set_selinux"; "true"];
817        ["get_selinux"]])],
818    "set SELinux enabled or disabled at appliance boot",
819    "\
820 This sets the selinux flag that is passed to the appliance
821 at boot time.  The default is C<selinux=0> (disabled).
822
823 Note that if SELinux is enabled, it is always in
824 Permissive mode (C<enforcing=0>).
825
826 For more information on the architecture of libguestfs,
827 see L<guestfs(3)>.");
828
829   ("get_selinux", (RBool "selinux", []), -1, [],
830    [],
831    "get SELinux enabled flag",
832    "\
833 This returns the current setting of the selinux flag which
834 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
835
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
838
839   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
840    [InitNone, Always, TestOutputFalse (
841       [["set_trace"; "false"];
842        ["get_trace"]])],
843    "enable or disable command traces",
844    "\
845 If the command trace flag is set to 1, then commands are
846 printed on stdout before they are executed in a format
847 which is very similar to the one used by guestfish.  In
848 other words, you can run a program with this enabled, and
849 you will get out a script which you can feed to guestfish
850 to perform the same set of actions.
851
852 If you want to trace C API calls into libguestfs (and
853 other libraries) then possibly a better way is to use
854 the external ltrace(1) command.
855
856 Command traces are disabled unless the environment variable
857 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858
859   ("get_trace", (RBool "trace", []), -1, [],
860    [],
861    "get command trace enabled flag",
862    "\
863 Return the command trace flag.");
864
865   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
866    [InitNone, Always, TestOutputFalse (
867       [["set_direct"; "false"];
868        ["get_direct"]])],
869    "enable or disable direct appliance mode",
870    "\
871 If the direct appliance mode flag is enabled, then stdin and
872 stdout are passed directly through to the appliance once it
873 is launched.
874
875 One consequence of this is that log messages aren't caught
876 by the library and handled by C<guestfs_set_log_message_callback>,
877 but go straight to stdout.
878
879 You probably don't want to use this unless you know what you
880 are doing.
881
882 The default is disabled.");
883
884   ("get_direct", (RBool "direct", []), -1, [],
885    [],
886    "get direct appliance mode flag",
887    "\
888 Return the direct appliance mode flag.");
889
890   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
891    [InitNone, Always, TestOutputTrue (
892       [["set_recovery_proc"; "true"];
893        ["get_recovery_proc"]])],
894    "enable or disable the recovery process",
895    "\
896 If this is called with the parameter C<false> then
897 C<guestfs_launch> does not create a recovery process.  The
898 purpose of the recovery process is to stop runaway qemu
899 processes in the case where the main program aborts abruptly.
900
901 This only has any effect if called before C<guestfs_launch>,
902 and the default is true.
903
904 About the only time when you would want to disable this is
905 if the main process will fork itself into the background
906 (\"daemonize\" itself).  In this case the recovery process
907 thinks that the main program has disappeared and so kills
908 qemu, which is not very helpful.");
909
910   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911    [],
912    "get recovery process enabled flag",
913    "\
914 Return the recovery process enabled flag.");
915
916   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917    [],
918    "add a drive specifying the QEMU block emulation to use",
919    "\
920 This is the same as C<guestfs_add_drive> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
922
923   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive read-only specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive_ro> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930 ]
931
932 (* daemon_functions are any functions which cause some action
933  * to take place in the daemon.
934  *)
935
936 let daemon_functions = [
937   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
938    [InitEmpty, Always, TestOutput (
939       [["part_disk"; "/dev/sda"; "mbr"];
940        ["mkfs"; "ext2"; "/dev/sda1"];
941        ["mount"; "/dev/sda1"; "/"];
942        ["write"; "/new"; "new file contents"];
943        ["cat"; "/new"]], "new file contents")],
944    "mount a guest disk at a position in the filesystem",
945    "\
946 Mount a guest disk at a position in the filesystem.  Block devices
947 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
948 the guest.  If those block devices contain partitions, they will have
949 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
950 names can be used.
951
952 The rules are the same as for L<mount(2)>:  A filesystem must
953 first be mounted on C</> before others can be mounted.  Other
954 filesystems can only be mounted on directories which already
955 exist.
956
957 The mounted filesystem is writable, if we have sufficient permissions
958 on the underlying device.
959
960 B<Important note:>
961 When you use this call, the filesystem options C<sync> and C<noatime>
962 are set implicitly.  This was originally done because we thought it
963 would improve reliability, but it turns out that I<-o sync> has a
964 very large negative performance impact and negligible effect on
965 reliability.  Therefore we recommend that you avoid using
966 C<guestfs_mount> in any code that needs performance, and instead
967 use C<guestfs_mount_options> (use an empty string for the first
968 parameter if you don't want any options).");
969
970   ("sync", (RErr, []), 2, [],
971    [ InitEmpty, Always, TestRun [["sync"]]],
972    "sync disks, writes are flushed through to the disk image",
973    "\
974 This syncs the disk, so that any writes are flushed through to the
975 underlying disk image.
976
977 You should always call this if you have modified a disk image, before
978 closing the handle.");
979
980   ("touch", (RErr, [Pathname "path"]), 3, [],
981    [InitBasicFS, Always, TestOutputTrue (
982       [["touch"; "/new"];
983        ["exists"; "/new"]])],
984    "update file timestamps or create a new file",
985    "\
986 Touch acts like the L<touch(1)> command.  It can be used to
987 update the timestamps on a file, or, if the file does not exist,
988 to create a new zero-length file.");
989
990   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
991    [InitISOFS, Always, TestOutput (
992       [["cat"; "/known-2"]], "abcdef\n")],
993    "list the contents of a file",
994    "\
995 Return the contents of the file named C<path>.
996
997 Note that this function cannot correctly handle binary files
998 (specifically, files containing C<\\0> character which is treated
999 as end of string).  For those you need to use the C<guestfs_read_file>
1000 or C<guestfs_download> functions which have a more complex interface.");
1001
1002   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1003    [], (* XXX Tricky to test because it depends on the exact format
1004         * of the 'ls -l' command, which changes between F10 and F11.
1005         *)
1006    "list the files in a directory (long format)",
1007    "\
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd) in the format of 'ls -la'.
1010
1011 This command is mostly useful for interactive sessions.  It
1012 is I<not> intended that you try to parse the output string.");
1013
1014   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1015    [InitBasicFS, Always, TestOutputList (
1016       [["touch"; "/new"];
1017        ["touch"; "/newer"];
1018        ["touch"; "/newest"];
1019        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1020    "list the files in a directory",
1021    "\
1022 List the files in C<directory> (relative to the root directory,
1023 there is no cwd).  The '.' and '..' entries are not returned, but
1024 hidden files are shown.
1025
1026 This command is mostly useful for interactive sessions.  Programs
1027 should probably use C<guestfs_readdir> instead.");
1028
1029   ("list_devices", (RStringList "devices", []), 7, [],
1030    [InitEmpty, Always, TestOutputListOfDevices (
1031       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1032    "list the block devices",
1033    "\
1034 List all the block devices.
1035
1036 The full block device names are returned, eg. C</dev/sda>");
1037
1038   ("list_partitions", (RStringList "partitions", []), 8, [],
1039    [InitBasicFS, Always, TestOutputListOfDevices (
1040       [["list_partitions"]], ["/dev/sda1"]);
1041     InitEmpty, Always, TestOutputListOfDevices (
1042       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1043        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1044    "list the partitions",
1045    "\
1046 List all the partitions detected on all block devices.
1047
1048 The full partition device names are returned, eg. C</dev/sda1>
1049
1050 This does not return logical volumes.  For that you will need to
1051 call C<guestfs_lvs>.");
1052
1053   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1054    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1055       [["pvs"]], ["/dev/sda1"]);
1056     InitEmpty, Always, TestOutputListOfDevices (
1057       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1058        ["pvcreate"; "/dev/sda1"];
1059        ["pvcreate"; "/dev/sda2"];
1060        ["pvcreate"; "/dev/sda3"];
1061        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1062    "list the LVM physical volumes (PVs)",
1063    "\
1064 List all the physical volumes detected.  This is the equivalent
1065 of the L<pvs(8)> command.
1066
1067 This returns a list of just the device names that contain
1068 PVs (eg. C</dev/sda2>).
1069
1070 See also C<guestfs_pvs_full>.");
1071
1072   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1073    [InitBasicFSonLVM, Always, TestOutputList (
1074       [["vgs"]], ["VG"]);
1075     InitEmpty, Always, TestOutputList (
1076       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1077        ["pvcreate"; "/dev/sda1"];
1078        ["pvcreate"; "/dev/sda2"];
1079        ["pvcreate"; "/dev/sda3"];
1080        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1081        ["vgcreate"; "VG2"; "/dev/sda3"];
1082        ["vgs"]], ["VG1"; "VG2"])],
1083    "list the LVM volume groups (VGs)",
1084    "\
1085 List all the volumes groups detected.  This is the equivalent
1086 of the L<vgs(8)> command.
1087
1088 This returns a list of just the volume group names that were
1089 detected (eg. C<VolGroup00>).
1090
1091 See also C<guestfs_vgs_full>.");
1092
1093   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1094    [InitBasicFSonLVM, Always, TestOutputList (
1095       [["lvs"]], ["/dev/VG/LV"]);
1096     InitEmpty, Always, TestOutputList (
1097       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1098        ["pvcreate"; "/dev/sda1"];
1099        ["pvcreate"; "/dev/sda2"];
1100        ["pvcreate"; "/dev/sda3"];
1101        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1102        ["vgcreate"; "VG2"; "/dev/sda3"];
1103        ["lvcreate"; "LV1"; "VG1"; "50"];
1104        ["lvcreate"; "LV2"; "VG1"; "50"];
1105        ["lvcreate"; "LV3"; "VG2"; "50"];
1106        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1107    "list the LVM logical volumes (LVs)",
1108    "\
1109 List all the logical volumes detected.  This is the equivalent
1110 of the L<lvs(8)> command.
1111
1112 This returns a list of the logical volume device names
1113 (eg. C</dev/VolGroup00/LogVol00>).
1114
1115 See also C<guestfs_lvs_full>.");
1116
1117   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1118    [], (* XXX how to test? *)
1119    "list the LVM physical volumes (PVs)",
1120    "\
1121 List all the physical volumes detected.  This is the equivalent
1122 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1123
1124   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1125    [], (* XXX how to test? *)
1126    "list the LVM volume groups (VGs)",
1127    "\
1128 List all the volumes groups detected.  This is the equivalent
1129 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1130
1131   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1132    [], (* XXX how to test? *)
1133    "list the LVM logical volumes (LVs)",
1134    "\
1135 List all the logical volumes detected.  This is the equivalent
1136 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1137
1138   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1139    [InitISOFS, Always, TestOutputList (
1140       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1141     InitISOFS, Always, TestOutputList (
1142       [["read_lines"; "/empty"]], [])],
1143    "read file as lines",
1144    "\
1145 Return the contents of the file named C<path>.
1146
1147 The file contents are returned as a list of lines.  Trailing
1148 C<LF> and C<CRLF> character sequences are I<not> returned.
1149
1150 Note that this function cannot correctly handle binary files
1151 (specifically, files containing C<\\0> character which is treated
1152 as end of line).  For those you need to use the C<guestfs_read_file>
1153 function which has a more complex interface.");
1154
1155   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1156    [], (* XXX Augeas code needs tests. *)
1157    "create a new Augeas handle",
1158    "\
1159 Create a new Augeas handle for editing configuration files.
1160 If there was any previous Augeas handle associated with this
1161 guestfs session, then it is closed.
1162
1163 You must call this before using any other C<guestfs_aug_*>
1164 commands.
1165
1166 C<root> is the filesystem root.  C<root> must not be NULL,
1167 use C</> instead.
1168
1169 The flags are the same as the flags defined in
1170 E<lt>augeas.hE<gt>, the logical I<or> of the following
1171 integers:
1172
1173 =over 4
1174
1175 =item C<AUG_SAVE_BACKUP> = 1
1176
1177 Keep the original file with a C<.augsave> extension.
1178
1179 =item C<AUG_SAVE_NEWFILE> = 2
1180
1181 Save changes into a file with extension C<.augnew>, and
1182 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1183
1184 =item C<AUG_TYPE_CHECK> = 4
1185
1186 Typecheck lenses (can be expensive).
1187
1188 =item C<AUG_NO_STDINC> = 8
1189
1190 Do not use standard load path for modules.
1191
1192 =item C<AUG_SAVE_NOOP> = 16
1193
1194 Make save a no-op, just record what would have been changed.
1195
1196 =item C<AUG_NO_LOAD> = 32
1197
1198 Do not load the tree in C<guestfs_aug_init>.
1199
1200 =back
1201
1202 To close the handle, you can call C<guestfs_aug_close>.
1203
1204 To find out more about Augeas, see L<http://augeas.net/>.");
1205
1206   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1207    [], (* XXX Augeas code needs tests. *)
1208    "close the current Augeas handle",
1209    "\
1210 Close the current Augeas handle and free up any resources
1211 used by it.  After calling this, you have to call
1212 C<guestfs_aug_init> again before you can use any other
1213 Augeas functions.");
1214
1215   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas variable",
1218    "\
1219 Defines an Augeas variable C<name> whose value is the result
1220 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1221 undefined.
1222
1223 On success this returns the number of nodes in C<expr>, or
1224 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225
1226   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "define an Augeas node",
1229    "\
1230 Defines a variable C<name> whose value is the result of
1231 evaluating C<expr>.
1232
1233 If C<expr> evaluates to an empty nodeset, a node is created,
1234 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1235 C<name> will be the nodeset containing that single node.
1236
1237 On success this returns a pair containing the
1238 number of nodes in the nodeset, and a boolean flag
1239 if a node was created.");
1240
1241   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1242    [], (* XXX Augeas code needs tests. *)
1243    "look up the value of an Augeas path",
1244    "\
1245 Look up the value associated with C<path>.  If C<path>
1246 matches exactly one node, the C<value> is returned.");
1247
1248   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "set Augeas path to value",
1251    "\
1252 Set the value associated with C<path> to C<val>.
1253
1254 In the Augeas API, it is possible to clear a node by setting
1255 the value to NULL.  Due to an oversight in the libguestfs API
1256 you cannot do that with this call.  Instead you must use the
1257 C<guestfs_aug_clear> call.");
1258
1259   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1260    [], (* XXX Augeas code needs tests. *)
1261    "insert a sibling Augeas node",
1262    "\
1263 Create a new sibling C<label> for C<path>, inserting it into
1264 the tree before or after C<path> (depending on the boolean
1265 flag C<before>).
1266
1267 C<path> must match exactly one existing node in the tree, and
1268 C<label> must be a label, ie. not contain C</>, C<*> or end
1269 with a bracketed index C<[N]>.");
1270
1271   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "remove an Augeas path",
1274    "\
1275 Remove C<path> and all of its children.
1276
1277 On success this returns the number of entries which were removed.");
1278
1279   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "move Augeas node",
1282    "\
1283 Move the node C<src> to C<dest>.  C<src> must match exactly
1284 one node.  C<dest> is overwritten if it exists.");
1285
1286   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "return Augeas nodes which match augpath",
1289    "\
1290 Returns a list of paths which match the path expression C<path>.
1291 The returned paths are sufficiently qualified so that they match
1292 exactly one node in the current tree.");
1293
1294   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "write all pending Augeas changes to disk",
1297    "\
1298 This writes all pending changes to disk.
1299
1300 The flags which were passed to C<guestfs_aug_init> affect exactly
1301 how files are saved.");
1302
1303   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1304    [], (* XXX Augeas code needs tests. *)
1305    "load files into the tree",
1306    "\
1307 Load files into the tree.
1308
1309 See C<aug_load> in the Augeas documentation for the full gory
1310 details.");
1311
1312   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1313    [], (* XXX Augeas code needs tests. *)
1314    "list Augeas nodes under augpath",
1315    "\
1316 This is just a shortcut for listing C<guestfs_aug_match>
1317 C<path/*> and sorting the resulting nodes into alphabetical order.");
1318
1319   ("rm", (RErr, [Pathname "path"]), 29, [],
1320    [InitBasicFS, Always, TestRun
1321       [["touch"; "/new"];
1322        ["rm"; "/new"]];
1323     InitBasicFS, Always, TestLastFail
1324       [["rm"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["mkdir"; "/new"];
1327        ["rm"; "/new"]]],
1328    "remove a file",
1329    "\
1330 Remove the single file C<path>.");
1331
1332   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1333    [InitBasicFS, Always, TestRun
1334       [["mkdir"; "/new"];
1335        ["rmdir"; "/new"]];
1336     InitBasicFS, Always, TestLastFail
1337       [["rmdir"; "/new"]];
1338     InitBasicFS, Always, TestLastFail
1339       [["touch"; "/new"];
1340        ["rmdir"; "/new"]]],
1341    "remove a directory",
1342    "\
1343 Remove the single directory C<path>.");
1344
1345   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1346    [InitBasicFS, Always, TestOutputFalse
1347       [["mkdir"; "/new"];
1348        ["mkdir"; "/new/foo"];
1349        ["touch"; "/new/foo/bar"];
1350        ["rm_rf"; "/new"];
1351        ["exists"; "/new"]]],
1352    "remove a file or directory recursively",
1353    "\
1354 Remove the file or directory C<path>, recursively removing the
1355 contents if its a directory.  This is like the C<rm -rf> shell
1356 command.");
1357
1358   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1359    [InitBasicFS, Always, TestOutputTrue
1360       [["mkdir"; "/new"];
1361        ["is_dir"; "/new"]];
1362     InitBasicFS, Always, TestLastFail
1363       [["mkdir"; "/new/foo/bar"]]],
1364    "create a directory",
1365    "\
1366 Create a directory named C<path>.");
1367
1368   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new/foo/bar"]];
1372     InitBasicFS, Always, TestOutputTrue
1373       [["mkdir_p"; "/new/foo/bar"];
1374        ["is_dir"; "/new/foo"]];
1375     InitBasicFS, Always, TestOutputTrue
1376       [["mkdir_p"; "/new/foo/bar"];
1377        ["is_dir"; "/new"]];
1378     (* Regression tests for RHBZ#503133: *)
1379     InitBasicFS, Always, TestRun
1380       [["mkdir"; "/new"];
1381        ["mkdir_p"; "/new"]];
1382     InitBasicFS, Always, TestLastFail
1383       [["touch"; "/new"];
1384        ["mkdir_p"; "/new"]]],
1385    "create a directory and parents",
1386    "\
1387 Create a directory named C<path>, creating any parent directories
1388 as necessary.  This is like the C<mkdir -p> shell command.");
1389
1390   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1391    [], (* XXX Need stat command to test *)
1392    "change file mode",
1393    "\
1394 Change the mode (permissions) of C<path> to C<mode>.  Only
1395 numeric modes are supported.
1396
1397 I<Note>: When using this command from guestfish, C<mode>
1398 by default would be decimal, unless you prefix it with
1399 C<0> to get octal, ie. use C<0700> not C<700>.
1400
1401 The mode actually set is affected by the umask.");
1402
1403   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1404    [], (* XXX Need stat command to test *)
1405    "change file owner and group",
1406    "\
1407 Change the file owner to C<owner> and group to C<group>.
1408
1409 Only numeric uid and gid are supported.  If you want to use
1410 names, you will need to locate and parse the password file
1411 yourself (Augeas support makes this relatively easy).");
1412
1413   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1414    [InitISOFS, Always, TestOutputTrue (
1415       [["exists"; "/empty"]]);
1416     InitISOFS, Always, TestOutputTrue (
1417       [["exists"; "/directory"]])],
1418    "test if file or directory exists",
1419    "\
1420 This returns C<true> if and only if there is a file, directory
1421 (or anything) with the given C<path> name.
1422
1423 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1424
1425   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1426    [InitISOFS, Always, TestOutputTrue (
1427       [["is_file"; "/known-1"]]);
1428     InitISOFS, Always, TestOutputFalse (
1429       [["is_file"; "/directory"]])],
1430    "test if file exists",
1431    "\
1432 This returns C<true> if and only if there is a file
1433 with the given C<path> name.  Note that it returns false for
1434 other objects like directories.
1435
1436 See also C<guestfs_stat>.");
1437
1438   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1439    [InitISOFS, Always, TestOutputFalse (
1440       [["is_dir"; "/known-3"]]);
1441     InitISOFS, Always, TestOutputTrue (
1442       [["is_dir"; "/directory"]])],
1443    "test if file exists",
1444    "\
1445 This returns C<true> if and only if there is a directory
1446 with the given C<path> name.  Note that it returns false for
1447 other objects like files.
1448
1449 See also C<guestfs_stat>.");
1450
1451   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1452    [InitEmpty, Always, TestOutputListOfDevices (
1453       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454        ["pvcreate"; "/dev/sda1"];
1455        ["pvcreate"; "/dev/sda2"];
1456        ["pvcreate"; "/dev/sda3"];
1457        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1458    "create an LVM physical volume",
1459    "\
1460 This creates an LVM physical volume on the named C<device>,
1461 where C<device> should usually be a partition name such
1462 as C</dev/sda1>.");
1463
1464   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1465    [InitEmpty, Always, TestOutputList (
1466       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467        ["pvcreate"; "/dev/sda1"];
1468        ["pvcreate"; "/dev/sda2"];
1469        ["pvcreate"; "/dev/sda3"];
1470        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1471        ["vgcreate"; "VG2"; "/dev/sda3"];
1472        ["vgs"]], ["VG1"; "VG2"])],
1473    "create an LVM volume group",
1474    "\
1475 This creates an LVM volume group called C<volgroup>
1476 from the non-empty list of physical volumes C<physvols>.");
1477
1478   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1479    [InitEmpty, Always, TestOutputList (
1480       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1481        ["pvcreate"; "/dev/sda1"];
1482        ["pvcreate"; "/dev/sda2"];
1483        ["pvcreate"; "/dev/sda3"];
1484        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1485        ["vgcreate"; "VG2"; "/dev/sda3"];
1486        ["lvcreate"; "LV1"; "VG1"; "50"];
1487        ["lvcreate"; "LV2"; "VG1"; "50"];
1488        ["lvcreate"; "LV3"; "VG2"; "50"];
1489        ["lvcreate"; "LV4"; "VG2"; "50"];
1490        ["lvcreate"; "LV5"; "VG2"; "50"];
1491        ["lvs"]],
1492       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1493        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1494    "create an LVM logical volume",
1495    "\
1496 This creates an LVM logical volume called C<logvol>
1497 on the volume group C<volgroup>, with C<size> megabytes.");
1498
1499   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1500    [InitEmpty, Always, TestOutput (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount_options"; ""; "/dev/sda1"; "/"];
1504        ["write"; "/new"; "new file contents"];
1505        ["cat"; "/new"]], "new file contents")],
1506    "make a filesystem",
1507    "\
1508 This creates a filesystem on C<device> (usually a partition
1509 or LVM logical volume).  The filesystem type is C<fstype>, for
1510 example C<ext3>.");
1511
1512   ("sfdisk", (RErr, [Device "device";
1513                      Int "cyls"; Int "heads"; Int "sectors";
1514                      StringList "lines"]), 43, [DangerWillRobinson],
1515    [],
1516    "create partitions on a block device",
1517    "\
1518 This is a direct interface to the L<sfdisk(8)> program for creating
1519 partitions on block devices.
1520
1521 C<device> should be a block device, for example C</dev/sda>.
1522
1523 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1524 and sectors on the device, which are passed directly to sfdisk as
1525 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1526 of these, then the corresponding parameter is omitted.  Usually for
1527 'large' disks, you can just pass C<0> for these, but for small
1528 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1529 out the right geometry and you will need to tell it.
1530
1531 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1532 information refer to the L<sfdisk(8)> manpage.
1533
1534 To create a single partition occupying the whole disk, you would
1535 pass C<lines> as a single element list, when the single element being
1536 the string C<,> (comma).
1537
1538 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1539 C<guestfs_part_init>");
1540
1541   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1542    [],
1543    "create a file",
1544    "\
1545 This call creates a file called C<path>.  The contents of the
1546 file is the string C<content> (which can contain any 8 bit data),
1547 with length C<size>.
1548
1549 As a special case, if C<size> is C<0>
1550 then the length is calculated using C<strlen> (so in this case
1551 the content cannot contain embedded ASCII NULs).
1552
1553 I<NB.> Owing to a bug, writing content containing ASCII NUL
1554 characters does I<not> work, even if the length is specified.");
1555
1556   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557    [InitEmpty, Always, TestOutputListOfDevices (
1558       [["part_disk"; "/dev/sda"; "mbr"];
1559        ["mkfs"; "ext2"; "/dev/sda1"];
1560        ["mount_options"; ""; "/dev/sda1"; "/"];
1561        ["mounts"]], ["/dev/sda1"]);
1562     InitEmpty, Always, TestOutputList (
1563       [["part_disk"; "/dev/sda"; "mbr"];
1564        ["mkfs"; "ext2"; "/dev/sda1"];
1565        ["mount_options"; ""; "/dev/sda1"; "/"];
1566        ["umount"; "/"];
1567        ["mounts"]], [])],
1568    "unmount a filesystem",
1569    "\
1570 This unmounts the given filesystem.  The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1573
1574   ("mounts", (RStringList "devices", []), 46, [],
1575    [InitBasicFS, Always, TestOutputListOfDevices (
1576       [["mounts"]], ["/dev/sda1"])],
1577    "show mounted filesystems",
1578    "\
1579 This returns the list of currently mounted filesystems.  It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1581
1582 Some internal mounts are not shown.
1583
1584 See also: C<guestfs_mountpoints>");
1585
1586   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587    [InitBasicFS, Always, TestOutputList (
1588       [["umount_all"];
1589        ["mounts"]], []);
1590     (* check that umount_all can unmount nested mounts correctly: *)
1591     InitEmpty, Always, TestOutputList (
1592       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593        ["mkfs"; "ext2"; "/dev/sda1"];
1594        ["mkfs"; "ext2"; "/dev/sda2"];
1595        ["mkfs"; "ext2"; "/dev/sda3"];
1596        ["mount_options"; ""; "/dev/sda1"; "/"];
1597        ["mkdir"; "/mp1"];
1598        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599        ["mkdir"; "/mp1/mp2"];
1600        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601        ["mkdir"; "/mp1/mp2/mp3"];
1602        ["umount_all"];
1603        ["mounts"]], [])],
1604    "unmount all filesystems",
1605    "\
1606 This unmounts all mounted filesystems.
1607
1608 Some internal mounts are not unmounted by this call.");
1609
1610   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1611    [],
1612    "remove all LVM LVs, VGs and PVs",
1613    "\
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1616
1617   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618    [InitISOFS, Always, TestOutput (
1619       [["file"; "/empty"]], "empty");
1620     InitISOFS, Always, TestOutput (
1621       [["file"; "/known-1"]], "ASCII text");
1622     InitISOFS, Always, TestLastFail (
1623       [["file"; "/notexists"]])],
1624    "determine file type",
1625    "\
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file.  This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1629
1630 This call will also transparently look inside various types
1631 of compressed file.
1632
1633 The exact command which runs is C<file -zbsL path>.  Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1636
1637   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638    [InitBasicFS, Always, TestOutput (
1639       [["upload"; "test-command"; "/test-command"];
1640        ["chmod"; "0o755"; "/test-command"];
1641        ["command"; "/test-command 1"]], "Result1");
1642     InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 2"]], "Result2\n");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 3"]], "\nResult3");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 4"]], "\nResult4\n");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 5"]], "\nResult5\n\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 7"]], "");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 8"]], "\n");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 9"]], "\n\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682     InitBasicFS, Always, TestLastFail (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command"]])],
1686    "run a command from the guest filesystem",
1687    "\
1688 This call runs a command from the guest filesystem.  The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1692
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters.  The list must be
1696 non-empty (ie. must contain a program name).  Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1699
1700 The return value is anything printed to I<stdout> by
1701 the command.
1702
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message.  The error message
1705 string is the content of I<stderr> from the command.
1706
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>.  If you require a program from
1709 another location, you should provide the full path in the
1710 first parameter.
1711
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places.  It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1716 locations.");
1717
1718   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719    [InitBasicFS, Always, TestOutputList (
1720       [["upload"; "test-command"; "/test-command"];
1721        ["chmod"; "0o755"; "/test-command"];
1722        ["command_lines"; "/test-command 1"]], ["Result1"]);
1723     InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 2"]], ["Result2"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 7"]], []);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 8"]], [""]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 9"]], ["";""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763    "run a command, returning lines",
1764    "\
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1767
1768 See also: C<guestfs_sh_lines>");
1769
1770   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771    [InitISOFS, Always, TestOutputStruct (
1772       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773    "get file information",
1774    "\
1775 Returns file information for the given C<path>.
1776
1777 This is the same as the C<stat(2)> system call.");
1778
1779   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780    [InitISOFS, Always, TestOutputStruct (
1781       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782    "get file information for a symbolic link",
1783    "\
1784 Returns file information for the given C<path>.
1785
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1788 refers to.
1789
1790 This is the same as the C<lstat(2)> system call.");
1791
1792   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795    "get file system statistics",
1796    "\
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1800
1801 This is the same as the C<statvfs(2)> system call.");
1802
1803   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1804    [], (* XXX test *)
1805    "get ext2/ext3/ext4 superblock details",
1806    "\
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1809
1810 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1811 manpage for more details.  The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1814
1815   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816    [InitEmpty, Always, TestOutputTrue (
1817       [["blockdev_setro"; "/dev/sda"];
1818        ["blockdev_getro"; "/dev/sda"]])],
1819    "set block device to read-only",
1820    "\
1821 Sets the block device named C<device> to read-only.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826    [InitEmpty, Always, TestOutputFalse (
1827       [["blockdev_setrw"; "/dev/sda"];
1828        ["blockdev_getro"; "/dev/sda"]])],
1829    "set block device to read-write",
1830    "\
1831 Sets the block device named C<device> to read-write.
1832
1833 This uses the L<blockdev(8)> command.");
1834
1835   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "is block device set to read-only",
1840    "\
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847    [InitEmpty, Always, TestOutputInt (
1848       [["blockdev_getss"; "/dev/sda"]], 512)],
1849    "get sectorsize of block device",
1850    "\
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1853
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1855 for that).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862    "get blocksize of block device",
1863    "\
1864 This returns the block size of a device.
1865
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1872    [], (* XXX test *)
1873    "set blocksize of block device",
1874    "\
1875 This sets the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885    "get total size of device in 512-byte sectors",
1886    "\
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1889
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1893
1894 This uses the L<blockdev(8)> command.");
1895
1896   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897    [InitEmpty, Always, TestOutputInt (
1898       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899    "get total size of device in bytes",
1900    "\
1901 This returns the size of the device in bytes.
1902
1903 See also C<guestfs_blockdev_getsz>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908    [InitEmpty, Always, TestRun
1909       [["blockdev_flushbufs"; "/dev/sda"]]],
1910    "flush device buffers",
1911    "\
1912 This tells the kernel to flush internal buffers associated
1913 with C<device>.
1914
1915 This uses the L<blockdev(8)> command.");
1916
1917   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918    [InitEmpty, Always, TestRun
1919       [["blockdev_rereadpt"; "/dev/sda"]]],
1920    "reread partition table",
1921    "\
1922 Reread the partition table on C<device>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927    [InitBasicFS, Always, TestOutput (
1928       (* Pick a file from cwd which isn't likely to change. *)
1929       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930        ["checksum"; "md5"; "/COPYING.LIB"]],
1931       Digest.to_hex (Digest.file "COPYING.LIB"))],
1932    "upload a file from the local machine",
1933    "\
1934 Upload local file C<filename> to C<remotefilename> on the
1935 filesystem.
1936
1937 C<filename> can also be a named pipe.
1938
1939 See also C<guestfs_download>.");
1940
1941   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942    [InitBasicFS, Always, TestOutput (
1943       (* Pick a file from cwd which isn't likely to change. *)
1944       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946        ["upload"; "testdownload.tmp"; "/upload"];
1947        ["checksum"; "md5"; "/upload"]],
1948       Digest.to_hex (Digest.file "COPYING.LIB"))],
1949    "download a file to the local machine",
1950    "\
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1953
1954 C<filename> can also be a named pipe.
1955
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1957
1958   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959    [InitISOFS, Always, TestOutput (
1960       [["checksum"; "crc"; "/known-3"]], "2891671662");
1961     InitISOFS, Always, TestLastFail (
1962       [["checksum"; "crc"; "/notexists"]]);
1963     InitISOFS, Always, TestOutput (
1964       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965     InitISOFS, Always, TestOutput (
1966       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1975     (* Test for RHBZ#579608, absolute symbolic links. *)
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1978    "compute MD5, SHAx or CRC checksum of file",
1979    "\
1980 This call computes the MD5, SHAx or CRC checksum of the
1981 file named C<path>.
1982
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1985
1986 =over 4
1987
1988 =item C<crc>
1989
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1992
1993 =item C<md5>
1994
1995 Compute the MD5 hash (using the C<md5sum> program).
1996
1997 =item C<sha1>
1998
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2000
2001 =item C<sha224>
2002
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2004
2005 =item C<sha256>
2006
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2008
2009 =item C<sha384>
2010
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2012
2013 =item C<sha512>
2014
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2016
2017 =back
2018
2019 The checksum is returned as a printable string.
2020
2021 To get the checksum for a device, use C<guestfs_checksum_device>.
2022
2023 To get the checksums for many files, use C<guestfs_checksums_out>.");
2024
2025   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2026    [InitBasicFS, Always, TestOutput (
2027       [["tar_in"; "../images/helloworld.tar"; "/"];
2028        ["cat"; "/hello"]], "hello\n")],
2029    "unpack tarfile to directory",
2030    "\
2031 This command uploads and unpacks local file C<tarfile> (an
2032 I<uncompressed> tar file) into C<directory>.
2033
2034 To upload a compressed tarball, use C<guestfs_tgz_in>
2035 or C<guestfs_txz_in>.");
2036
2037   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2038    [],
2039    "pack directory into tarfile",
2040    "\
2041 This command packs the contents of C<directory> and downloads
2042 it to local file C<tarfile>.
2043
2044 To download a compressed tarball, use C<guestfs_tgz_out>
2045 or C<guestfs_txz_out>.");
2046
2047   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2048    [InitBasicFS, Always, TestOutput (
2049       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2050        ["cat"; "/hello"]], "hello\n")],
2051    "unpack compressed tarball to directory",
2052    "\
2053 This command uploads and unpacks local file C<tarball> (a
2054 I<gzip compressed> tar file) into C<directory>.
2055
2056 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2057
2058   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2059    [],
2060    "pack directory into compressed tarball",
2061    "\
2062 This command packs the contents of C<directory> and downloads
2063 it to local file C<tarball>.
2064
2065 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2066
2067   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2068    [InitBasicFS, Always, TestLastFail (
2069       [["umount"; "/"];
2070        ["mount_ro"; "/dev/sda1"; "/"];
2071        ["touch"; "/new"]]);
2072     InitBasicFS, Always, TestOutput (
2073       [["write"; "/new"; "data"];
2074        ["umount"; "/"];
2075        ["mount_ro"; "/dev/sda1"; "/"];
2076        ["cat"; "/new"]], "data")],
2077    "mount a guest disk, read-only",
2078    "\
2079 This is the same as the C<guestfs_mount> command, but it
2080 mounts the filesystem with the read-only (I<-o ro>) flag.");
2081
2082   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2083    [],
2084    "mount a guest disk with mount options",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set the mount options as for the
2088 L<mount(8)> I<-o> flag.
2089
2090 If the C<options> parameter is an empty string, then
2091 no options are passed (all options default to whatever
2092 the filesystem uses).");
2093
2094   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2095    [],
2096    "mount a guest disk with mount options and vfstype",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2101
2102   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2103    [],
2104    "debugging and internals",
2105    "\
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2108 qemu subprocess.
2109
2110 There is no comprehensive help for this command.  You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2113
2114   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115    [InitEmpty, Always, TestOutputList (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["lvremove"; "/dev/VG/LV1"];
2122        ["lvs"]], ["/dev/VG/LV2"]);
2123     InitEmpty, Always, TestOutputList (
2124       [["part_disk"; "/dev/sda"; "mbr"];
2125        ["pvcreate"; "/dev/sda1"];
2126        ["vgcreate"; "VG"; "/dev/sda1"];
2127        ["lvcreate"; "LV1"; "VG"; "50"];
2128        ["lvcreate"; "LV2"; "VG"; "50"];
2129        ["lvremove"; "/dev/VG"];
2130        ["lvs"]], []);
2131     InitEmpty, Always, TestOutputList (
2132       [["part_disk"; "/dev/sda"; "mbr"];
2133        ["pvcreate"; "/dev/sda1"];
2134        ["vgcreate"; "VG"; "/dev/sda1"];
2135        ["lvcreate"; "LV1"; "VG"; "50"];
2136        ["lvcreate"; "LV2"; "VG"; "50"];
2137        ["lvremove"; "/dev/VG"];
2138        ["vgs"]], ["VG"])],
2139    "remove an LVM logical volume",
2140    "\
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2143
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2146
2147   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148    [InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["vgremove"; "VG"];
2155        ["lvs"]], []);
2156     InitEmpty, Always, TestOutputList (
2157       [["part_disk"; "/dev/sda"; "mbr"];
2158        ["pvcreate"; "/dev/sda1"];
2159        ["vgcreate"; "VG"; "/dev/sda1"];
2160        ["lvcreate"; "LV1"; "VG"; "50"];
2161        ["lvcreate"; "LV2"; "VG"; "50"];
2162        ["vgremove"; "VG"];
2163        ["vgs"]], [])],
2164    "remove an LVM volume group",
2165    "\
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2167
2168 This also forcibly removes all logical volumes in the volume
2169 group (if any).");
2170
2171   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172    [InitEmpty, Always, TestOutputListOfDevices (
2173       [["part_disk"; "/dev/sda"; "mbr"];
2174        ["pvcreate"; "/dev/sda1"];
2175        ["vgcreate"; "VG"; "/dev/sda1"];
2176        ["lvcreate"; "LV1"; "VG"; "50"];
2177        ["lvcreate"; "LV2"; "VG"; "50"];
2178        ["vgremove"; "VG"];
2179        ["pvremove"; "/dev/sda1"];
2180        ["lvs"]], []);
2181     InitEmpty, Always, TestOutputListOfDevices (
2182       [["part_disk"; "/dev/sda"; "mbr"];
2183        ["pvcreate"; "/dev/sda1"];
2184        ["vgcreate"; "VG"; "/dev/sda1"];
2185        ["lvcreate"; "LV1"; "VG"; "50"];
2186        ["lvcreate"; "LV2"; "VG"; "50"];
2187        ["vgremove"; "VG"];
2188        ["pvremove"; "/dev/sda1"];
2189        ["vgs"]], []);
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        ["pvs"]], [])],
2199    "remove an LVM physical volume",
2200    "\
2201 This wipes a physical volume C<device> so that LVM will no longer
2202 recognise it.
2203
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2207
2208   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209    [InitBasicFS, Always, TestOutput (
2210       [["set_e2label"; "/dev/sda1"; "testlabel"];
2211        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212    "set the ext2/3/4 filesystem label",
2213    "\
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>.  Filesystem labels are limited to
2216 16 characters.
2217
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2220
2221   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2222    [],
2223    "get the ext2/3/4 filesystem label",
2224    "\
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2226 C<device>.");
2227
2228   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229    (let uuid = uuidgen () in
2230     [InitBasicFS, Always, TestOutput (
2231        [["set_e2uuid"; "/dev/sda1"; uuid];
2232         ["get_e2uuid"; "/dev/sda1"]], uuid);
2233      InitBasicFS, Always, TestOutput (
2234        [["set_e2uuid"; "/dev/sda1"; "clear"];
2235         ["get_e2uuid"; "/dev/sda1"]], "");
2236      (* We can't predict what UUIDs will be, so just check the commands run. *)
2237      InitBasicFS, Always, TestRun (
2238        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241    "set the ext2/3/4 filesystem UUID",
2242    "\
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>.  The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2247
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2250
2251   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2252    [],
2253    "get the ext2/3/4 filesystem UUID",
2254    "\
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2256 C<device>.");
2257
2258   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259    [InitBasicFS, Always, TestOutputInt (
2260       [["umount"; "/dev/sda1"];
2261        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262     InitBasicFS, Always, TestOutputInt (
2263       [["umount"; "/dev/sda1"];
2264        ["zero"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266    "run the filesystem checker",
2267    "\
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2270
2271 The returned integer is the status.  See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2273
2274 Notes:
2275
2276 =over 4
2277
2278 =item *
2279
2280 Multiple status codes can be summed together.
2281
2282 =item *
2283
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2286
2287 =item *
2288
2289 Checking or repairing NTFS volumes is not supported
2290 (by linux-ntfs).
2291
2292 =back
2293
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2295
2296   ("zero", (RErr, [Device "device"]), 85, [],
2297    [InitBasicFS, Always, TestOutput (
2298       [["umount"; "/dev/sda1"];
2299        ["zero"; "/dev/sda1"];
2300        ["file"; "/dev/sda1"]], "data")],
2301    "write zeroes to the device",
2302    "\
2303 This command writes zeroes over the first few blocks of C<device>.
2304
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device).  It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2308
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2310
2311   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312    (* Test disabled because grub-install incompatible with virtio-blk driver.
2313     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2314     *)
2315    [InitBasicFS, Disabled, TestOutputTrue (
2316       [["grub_install"; "/"; "/dev/sda1"];
2317        ["is_dir"; "/boot"]])],
2318    "install GRUB",
2319    "\
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2322
2323   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324    [InitBasicFS, Always, TestOutput (
2325       [["write"; "/old"; "file content"];
2326        ["cp"; "/old"; "/new"];
2327        ["cat"; "/new"]], "file content");
2328     InitBasicFS, Always, TestOutputTrue (
2329       [["write"; "/old"; "file content"];
2330        ["cp"; "/old"; "/new"];
2331        ["is_file"; "/old"]]);
2332     InitBasicFS, Always, TestOutput (
2333       [["write"; "/old"; "file content"];
2334        ["mkdir"; "/dir"];
2335        ["cp"; "/old"; "/dir/new"];
2336        ["cat"; "/dir/new"]], "file content")],
2337    "copy a file",
2338    "\
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2341
2342   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["mkdir"; "/olddir"];
2345        ["mkdir"; "/newdir"];
2346        ["write"; "/olddir/file"; "file content"];
2347        ["cp_a"; "/olddir"; "/newdir"];
2348        ["cat"; "/newdir/olddir/file"]], "file content")],
2349    "copy a file or directory recursively",
2350    "\
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2353
2354   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355    [InitBasicFS, Always, TestOutput (
2356       [["write"; "/old"; "file content"];
2357        ["mv"; "/old"; "/new"];
2358        ["cat"; "/new"]], "file content");
2359     InitBasicFS, Always, TestOutputFalse (
2360       [["write"; "/old"; "file content"];
2361        ["mv"; "/old"; "/new"];
2362        ["is_file"; "/old"]])],
2363    "move a file",
2364    "\
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2367
2368   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369    [InitEmpty, Always, TestRun (
2370       [["drop_caches"; "3"]])],
2371    "drop kernel page cache, dentries and inodes",
2372    "\
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches.  The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2377
2378 Setting C<whattodrop> to 3 should drop everything.
2379
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2382
2383   ("dmesg", (RString "kmsgs", []), 91, [],
2384    [InitEmpty, Always, TestRun (
2385       [["dmesg"]])],
2386    "return kernel messages",
2387    "\
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel.  This is sometimes useful for extended
2390 debugging of problems.
2391
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2396
2397   ("ping_daemon", (RErr, []), 92, [],
2398    [InitEmpty, Always, TestRun (
2399       [["ping_daemon"]])],
2400    "ping the guest daemon",
2401    "\
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess.  Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2406
2407   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408    [InitBasicFS, Always, TestOutputTrue (
2409       [["write"; "/file1"; "contents of a file"];
2410        ["cp"; "/file1"; "/file2"];
2411        ["equal"; "/file1"; "/file2"]]);
2412     InitBasicFS, Always, TestOutputFalse (
2413       [["write"; "/file1"; "contents of a file"];
2414        ["write"; "/file2"; "contents of another file"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestLastFail (
2417       [["equal"; "/file1"; "/file2"]])],
2418    "test if two files have equal contents",
2419    "\
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2422
2423 The external L<cmp(1)> program is used for the comparison.");
2424
2425   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428     InitISOFS, Always, TestOutputList (
2429       [["strings"; "/empty"]], []);
2430     (* Test for RHBZ#579608, absolute symbolic links. *)
2431     InitISOFS, Always, TestRun (
2432       [["strings"; "/abssymlink"]])],
2433    "print the printable strings in a file",
2434    "\
2435 This runs the L<strings(1)> command on a file and returns
2436 the list of printable strings found.");
2437
2438   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2439    [InitISOFS, Always, TestOutputList (
2440       [["strings_e"; "b"; "/known-5"]], []);
2441     InitBasicFS, Always, TestOutputList (
2442       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2443        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2444    "print the printable strings in a file",
2445    "\
2446 This is like the C<guestfs_strings> command, but allows you to
2447 specify the encoding of strings that are looked for in
2448 the source file C<path>.
2449
2450 Allowed encodings are:
2451
2452 =over 4
2453
2454 =item s
2455
2456 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2457 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2458
2459 =item S
2460
2461 Single 8-bit-byte characters.
2462
2463 =item b
2464
2465 16-bit big endian strings such as those encoded in
2466 UTF-16BE or UCS-2BE.
2467
2468 =item l (lower case letter L)
2469
2470 16-bit little endian such as UTF-16LE and UCS-2LE.
2471 This is useful for examining binaries in Windows guests.
2472
2473 =item B
2474
2475 32-bit big endian such as UCS-4BE.
2476
2477 =item L
2478
2479 32-bit little endian such as UCS-4LE.
2480
2481 =back
2482
2483 The returned strings are transcoded to UTF-8.");
2484
2485   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2486    [InitISOFS, Always, TestOutput (
2487       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2488     (* Test for RHBZ#501888c2 regression which caused large hexdump
2489      * commands to segfault.
2490      *)
2491     InitISOFS, Always, TestRun (
2492       [["hexdump"; "/100krandom"]]);
2493     (* Test for RHBZ#579608, absolute symbolic links. *)
2494     InitISOFS, Always, TestRun (
2495       [["hexdump"; "/abssymlink"]])],
2496    "dump a file in hexadecimal",
2497    "\
2498 This runs C<hexdump -C> on the given C<path>.  The result is
2499 the human-readable, canonical hex dump of the file.");
2500
2501   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2502    [InitNone, Always, TestOutput (
2503       [["part_disk"; "/dev/sda"; "mbr"];
2504        ["mkfs"; "ext3"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["write"; "/new"; "test file"];
2507        ["umount"; "/dev/sda1"];
2508        ["zerofree"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["cat"; "/new"]], "test file")],
2511    "zero unused inodes and disk blocks on ext2/3 filesystem",
2512    "\
2513 This runs the I<zerofree> program on C<device>.  This program
2514 claims to zero unused inodes and disk blocks on an ext2/3
2515 filesystem, thus making it possible to compress the filesystem
2516 more effectively.
2517
2518 You should B<not> run this program if the filesystem is
2519 mounted.
2520
2521 It is possible that using this program can damage the filesystem
2522 or data on the filesystem.");
2523
2524   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2525    [],
2526    "resize an LVM physical volume",
2527    "\
2528 This resizes (expands or shrinks) an existing LVM physical
2529 volume to match the new size of the underlying device.");
2530
2531   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2532                        Int "cyls"; Int "heads"; Int "sectors";
2533                        String "line"]), 99, [DangerWillRobinson],
2534    [],
2535    "modify a single partition on a block device",
2536    "\
2537 This runs L<sfdisk(8)> option to modify just the single
2538 partition C<n> (note: C<n> counts from 1).
2539
2540 For other parameters, see C<guestfs_sfdisk>.  You should usually
2541 pass C<0> for the cyls/heads/sectors parameters.
2542
2543 See also: C<guestfs_part_add>");
2544
2545   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2546    [],
2547    "display the partition table",
2548    "\
2549 This displays the partition table on C<device>, in the
2550 human-readable output of the L<sfdisk(8)> command.  It is
2551 not intended to be parsed.
2552
2553 See also: C<guestfs_part_list>");
2554
2555   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2556    [],
2557    "display the kernel geometry",
2558    "\
2559 This displays the kernel's idea of the geometry of C<device>.
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2565    [],
2566    "display the disk geometry from the partition table",
2567    "\
2568 This displays the disk geometry of C<device> read from the
2569 partition table.  Especially in the case where the underlying
2570 block device has been resized, this can be different from the
2571 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2572
2573 The result is in human-readable format, and not designed to
2574 be parsed.");
2575
2576   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate all volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in all volume groups.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n>");
2587
2588   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2589    [],
2590    "activate or deactivate some volume groups",
2591    "\
2592 This command activates or (if C<activate> is false) deactivates
2593 all logical volumes in the listed volume groups C<volgroups>.
2594 If activated, then they are made known to the
2595 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2596 then those devices disappear.
2597
2598 This command is the same as running C<vgchange -a y|n volgroups...>
2599
2600 Note that if C<volgroups> is an empty list then B<all> volume groups
2601 are activated or deactivated.");
2602
2603   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2604    [InitNone, Always, TestOutput (
2605       [["part_disk"; "/dev/sda"; "mbr"];
2606        ["pvcreate"; "/dev/sda1"];
2607        ["vgcreate"; "VG"; "/dev/sda1"];
2608        ["lvcreate"; "LV"; "VG"; "10"];
2609        ["mkfs"; "ext2"; "/dev/VG/LV"];
2610        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2611        ["write"; "/new"; "test content"];
2612        ["umount"; "/"];
2613        ["lvresize"; "/dev/VG/LV"; "20"];
2614        ["e2fsck_f"; "/dev/VG/LV"];
2615        ["resize2fs"; "/dev/VG/LV"];
2616        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2617        ["cat"; "/new"]], "test content");
2618     InitNone, Always, TestRun (
2619       (* Make an LV smaller to test RHBZ#587484. *)
2620       [["part_disk"; "/dev/sda"; "mbr"];
2621        ["pvcreate"; "/dev/sda1"];
2622        ["vgcreate"; "VG"; "/dev/sda1"];
2623        ["lvcreate"; "LV"; "VG"; "20"];
2624        ["lvresize"; "/dev/VG/LV"; "10"]])],
2625    "resize an LVM logical volume",
2626    "\
2627 This resizes (expands or shrinks) an existing LVM logical
2628 volume to C<mbytes>.  When reducing, data in the reduced part
2629 is lost.");
2630
2631   ("resize2fs", (RErr, [Device "device"]), 106, [],
2632    [], (* lvresize tests this *)
2633    "resize an ext2/ext3 filesystem",
2634    "\
2635 This resizes an ext2 or ext3 filesystem to match the size of
2636 the underlying device.
2637
2638 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2639 on the C<device> before calling this command.  For unknown reasons
2640 C<resize2fs> sometimes gives an error about this and sometimes not.
2641 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2642 calling this function.");
2643
2644   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2645    [InitBasicFS, Always, TestOutputList (
2646       [["find"; "/"]], ["lost+found"]);
2647     InitBasicFS, Always, TestOutputList (
2648       [["touch"; "/a"];
2649        ["mkdir"; "/b"];
2650        ["touch"; "/b/c"];
2651        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2652     InitBasicFS, Always, TestOutputList (
2653       [["mkdir_p"; "/a/b/c"];
2654        ["touch"; "/a/b/c/d"];
2655        ["find"; "/a/b/"]], ["c"; "c/d"])],
2656    "find all files and directories",
2657    "\
2658 This command lists out all files and directories, recursively,
2659 starting at C<directory>.  It is essentially equivalent to
2660 running the shell command C<find directory -print> but some
2661 post-processing happens on the output, described below.
2662
2663 This returns a list of strings I<without any prefix>.  Thus
2664 if the directory structure was:
2665
2666  /tmp/a
2667  /tmp/b
2668  /tmp/c/d
2669
2670 then the returned list from C<guestfs_find> C</tmp> would be
2671 4 elements:
2672
2673  a
2674  b
2675  c
2676  c/d
2677
2678 If C<directory> is not a directory, then this command returns
2679 an error.
2680
2681 The returned list is sorted.
2682
2683 See also C<guestfs_find0>.");
2684
2685   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2686    [], (* lvresize tests this *)
2687    "check an ext2/ext3 filesystem",
2688    "\
2689 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2690 filesystem checker on C<device>, noninteractively (C<-p>),
2691 even if the filesystem appears to be clean (C<-f>).
2692
2693 This command is only needed because of C<guestfs_resize2fs>
2694 (q.v.).  Normally you should use C<guestfs_fsck>.");
2695
2696   ("sleep", (RErr, [Int "secs"]), 109, [],
2697    [InitNone, Always, TestRun (
2698       [["sleep"; "1"]])],
2699    "sleep for some seconds",
2700    "\
2701 Sleep for C<secs> seconds.");
2702
2703   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2704    [InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ntfs"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2708     InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ext2"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2712    "probe NTFS volume",
2713    "\
2714 This command runs the L<ntfs-3g.probe(8)> command which probes
2715 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2716 be mounted read-write, and some cannot be mounted at all).
2717
2718 C<rw> is a boolean flag.  Set it to true if you want to test
2719 if the volume can be mounted read-write.  Set it to false if
2720 you want to test if the volume can be mounted read-only.
2721
2722 The return value is an integer which C<0> if the operation
2723 would succeed, or some non-zero value documented in the
2724 L<ntfs-3g.probe(8)> manual page.");
2725
2726   ("sh", (RString "output", [String "command"]), 111, [],
2727    [], (* XXX needs tests *)
2728    "run a command via the shell",
2729    "\
2730 This call runs a command from the guest filesystem via the
2731 guest's C</bin/sh>.
2732
2733 This is like C<guestfs_command>, but passes the command to:
2734
2735  /bin/sh -c \"command\"
2736
2737 Depending on the guest's shell, this usually results in
2738 wildcards being expanded, shell expressions being interpolated
2739 and so on.
2740
2741 All the provisos about C<guestfs_command> apply to this call.");
2742
2743   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2744    [], (* XXX needs tests *)
2745    "run a command via the shell returning lines",
2746    "\
2747 This is the same as C<guestfs_sh>, but splits the result
2748 into a list of lines.
2749
2750 See also: C<guestfs_command_lines>");
2751
2752   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2753    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2754     * code in stubs.c, since all valid glob patterns must start with "/".
2755     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2756     *)
2757    [InitBasicFS, Always, TestOutputList (
2758       [["mkdir_p"; "/a/b/c"];
2759        ["touch"; "/a/b/c/d"];
2760        ["touch"; "/a/b/c/e"];
2761        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2762     InitBasicFS, Always, TestOutputList (
2763       [["mkdir_p"; "/a/b/c"];
2764        ["touch"; "/a/b/c/d"];
2765        ["touch"; "/a/b/c/e"];
2766        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2767     InitBasicFS, Always, TestOutputList (
2768       [["mkdir_p"; "/a/b/c"];
2769        ["touch"; "/a/b/c/d"];
2770        ["touch"; "/a/b/c/e"];
2771        ["glob_expand"; "/a/*/x/*"]], [])],
2772    "expand a wildcard path",
2773    "\
2774 This command searches for all the pathnames matching
2775 C<pattern> according to the wildcard expansion rules
2776 used by the shell.
2777
2778 If no paths match, then this returns an empty list
2779 (note: not an error).
2780
2781 It is just a wrapper around the C L<glob(3)> function
2782 with flags C<GLOB_MARK|GLOB_BRACE>.
2783 See that manual page for more details.");
2784
2785   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2786    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2787       [["scrub_device"; "/dev/sdc"]])],
2788    "scrub (securely wipe) a device",
2789    "\
2790 This command writes patterns over C<device> to make data retrieval
2791 more difficult.
2792
2793 It is an interface to the L<scrub(1)> program.  See that
2794 manual page for more details.");
2795
2796   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2797    [InitBasicFS, Always, TestRun (
2798       [["write"; "/file"; "content"];
2799        ["scrub_file"; "/file"]])],
2800    "scrub (securely wipe) a file",
2801    "\
2802 This command writes patterns over a file to make data retrieval
2803 more difficult.
2804
2805 The file is I<removed> after scrubbing.
2806
2807 It is an interface to the L<scrub(1)> program.  See that
2808 manual page for more details.");
2809
2810   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2811    [], (* XXX needs testing *)
2812    "scrub (securely wipe) free space",
2813    "\
2814 This command creates the directory C<dir> and then fills it
2815 with files until the filesystem is full, and scrubs the files
2816 as for C<guestfs_scrub_file>, and deletes them.
2817 The intention is to scrub any free space on the partition
2818 containing C<dir>.
2819
2820 It is an interface to the L<scrub(1)> program.  See that
2821 manual page for more details.");
2822
2823   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2824    [InitBasicFS, Always, TestRun (
2825       [["mkdir"; "/tmp"];
2826        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2827    "create a temporary directory",
2828    "\
2829 This command creates a temporary directory.  The
2830 C<template> parameter should be a full pathname for the
2831 temporary directory name with the final six characters being
2832 \"XXXXXX\".
2833
2834 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2835 the second one being suitable for Windows filesystems.
2836
2837 The name of the temporary directory that was created
2838 is returned.
2839
2840 The temporary directory is created with mode 0700
2841 and is owned by root.
2842
2843 The caller is responsible for deleting the temporary
2844 directory and its contents after use.
2845
2846 See also: L<mkdtemp(3)>");
2847
2848   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2849    [InitISOFS, Always, TestOutputInt (
2850       [["wc_l"; "/10klines"]], 10000);
2851     (* Test for RHBZ#579608, absolute symbolic links. *)
2852     InitISOFS, Always, TestOutputInt (
2853       [["wc_l"; "/abssymlink"]], 10000)],
2854    "count lines in a file",
2855    "\
2856 This command counts the lines in a file, using the
2857 C<wc -l> external command.");
2858
2859   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2860    [InitISOFS, Always, TestOutputInt (
2861       [["wc_w"; "/10klines"]], 10000)],
2862    "count words in a file",
2863    "\
2864 This command counts the words in a file, using the
2865 C<wc -w> external command.");
2866
2867   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2868    [InitISOFS, Always, TestOutputInt (
2869       [["wc_c"; "/100kallspaces"]], 102400)],
2870    "count characters in a file",
2871    "\
2872 This command counts the characters in a file, using the
2873 C<wc -c> external command.");
2874
2875   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2876    [InitISOFS, Always, TestOutputList (
2877       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2878     (* Test for RHBZ#579608, absolute symbolic links. *)
2879     InitISOFS, Always, TestOutputList (
2880       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2881    "return first 10 lines of a file",
2882    "\
2883 This command returns up to the first 10 lines of a file as
2884 a list of strings.");
2885
2886   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2887    [InitISOFS, Always, TestOutputList (
2888       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2889     InitISOFS, Always, TestOutputList (
2890       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2891     InitISOFS, Always, TestOutputList (
2892       [["head_n"; "0"; "/10klines"]], [])],
2893    "return first N lines of a file",
2894    "\
2895 If the parameter C<nrlines> is a positive number, this returns the first
2896 C<nrlines> lines of the file C<path>.
2897
2898 If the parameter C<nrlines> is a negative number, this returns lines
2899 from the file C<path>, excluding the last C<nrlines> lines.
2900
2901 If the parameter C<nrlines> is zero, this returns an empty list.");
2902
2903   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2904    [InitISOFS, Always, TestOutputList (
2905       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2906    "return last 10 lines of a file",
2907    "\
2908 This command returns up to the last 10 lines of a file as
2909 a list of strings.");
2910
2911   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2912    [InitISOFS, Always, TestOutputList (
2913       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2914     InitISOFS, Always, TestOutputList (
2915       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2916     InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "0"; "/10klines"]], [])],
2918    "return last N lines of a file",
2919    "\
2920 If the parameter C<nrlines> is a positive number, this returns the last
2921 C<nrlines> lines of the file C<path>.
2922
2923 If the parameter C<nrlines> is a negative number, this returns lines
2924 from the file C<path>, starting with the C<-nrlines>th line.
2925
2926 If the parameter C<nrlines> is zero, this returns an empty list.");
2927
2928   ("df", (RString "output", []), 125, [],
2929    [], (* XXX Tricky to test because it depends on the exact format
2930         * of the 'df' command and other imponderables.
2931         *)
2932    "report file system disk space usage",
2933    "\
2934 This command runs the C<df> command to report disk space used.
2935
2936 This command is mostly useful for interactive sessions.  It
2937 is I<not> intended that you try to parse the output string.
2938 Use C<statvfs> from programs.");
2939
2940   ("df_h", (RString "output", []), 126, [],
2941    [], (* XXX Tricky to test because it depends on the exact format
2942         * of the 'df' command and other imponderables.
2943         *)
2944    "report file system disk space usage (human readable)",
2945    "\
2946 This command runs the C<df -h> command to report disk space used
2947 in human-readable format.
2948
2949 This command is mostly useful for interactive sessions.  It
2950 is I<not> intended that you try to parse the output string.
2951 Use C<statvfs> from programs.");
2952
2953   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2954    [InitISOFS, Always, TestOutputInt (
2955       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2956    "estimate file space usage",
2957    "\
2958 This command runs the C<du -s> command to estimate file space
2959 usage for C<path>.
2960
2961 C<path> can be a file or a directory.  If C<path> is a directory
2962 then the estimate includes the contents of the directory and all
2963 subdirectories (recursively).
2964
2965 The result is the estimated size in I<kilobytes>
2966 (ie. units of 1024 bytes).");
2967
2968   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2969    [InitISOFS, Always, TestOutputList (
2970       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2971    "list files in an initrd",
2972    "\
2973 This command lists out files contained in an initrd.
2974
2975 The files are listed without any initial C</> character.  The
2976 files are listed in the order they appear (not necessarily
2977 alphabetical).  Directory names are listed as separate items.
2978
2979 Old Linux kernels (2.4 and earlier) used a compressed ext2
2980 filesystem as initrd.  We I<only> support the newer initramfs
2981 format (compressed cpio files).");
2982
2983   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2984    [],
2985    "mount a file using the loop device",
2986    "\
2987 This command lets you mount C<file> (a filesystem image
2988 in a file) on a mount point.  It is entirely equivalent to
2989 the command C<mount -o loop file mountpoint>.");
2990
2991   ("mkswap", (RErr, [Device "device"]), 130, [],
2992    [InitEmpty, Always, TestRun (
2993       [["part_disk"; "/dev/sda"; "mbr"];
2994        ["mkswap"; "/dev/sda1"]])],
2995    "create a swap partition",
2996    "\
2997 Create a swap partition on C<device>.");
2998
2999   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3000    [InitEmpty, Always, TestRun (
3001       [["part_disk"; "/dev/sda"; "mbr"];
3002        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3003    "create a swap partition with a label",
3004    "\
3005 Create a swap partition on C<device> with label C<label>.
3006
3007 Note that you cannot attach a swap label to a block device
3008 (eg. C</dev/sda>), just to a partition.  This appears to be
3009 a limitation of the kernel or swap tools.");
3010
3011   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3012    (let uuid = uuidgen () in
3013     [InitEmpty, Always, TestRun (
3014        [["part_disk"; "/dev/sda"; "mbr"];
3015         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3016    "create a swap partition with an explicit UUID",
3017    "\
3018 Create a swap partition on C<device> with UUID C<uuid>.");
3019
3020   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3021    [InitBasicFS, Always, TestOutputStruct (
3022       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3023        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3024        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3025     InitBasicFS, Always, TestOutputStruct (
3026       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3027        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3028    "make block, character or FIFO devices",
3029    "\
3030 This call creates block or character special devices, or
3031 named pipes (FIFOs).
3032
3033 The C<mode> parameter should be the mode, using the standard
3034 constants.  C<devmajor> and C<devminor> are the
3035 device major and minor numbers, only used when creating block
3036 and character special devices.
3037
3038 Note that, just like L<mknod(2)>, the mode must be bitwise
3039 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3040 just creates a regular file).  These constants are
3041 available in the standard Linux header files, or you can use
3042 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3043 which are wrappers around this command which bitwise OR
3044 in the appropriate constant for you.
3045
3046 The mode actually set is affected by the umask.");
3047
3048   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3049    [InitBasicFS, Always, TestOutputStruct (
3050       [["mkfifo"; "0o777"; "/node"];
3051        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3052    "make FIFO (named pipe)",
3053    "\
3054 This call creates a FIFO (named pipe) called C<path> with
3055 mode C<mode>.  It is just a convenient wrapper around
3056 C<guestfs_mknod>.
3057
3058 The mode actually set is affected by the umask.");
3059
3060   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3061    [InitBasicFS, Always, TestOutputStruct (
3062       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3063        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3064    "make block device node",
3065    "\
3066 This call creates a block device node called C<path> with
3067 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3068 It is just a convenient wrapper around C<guestfs_mknod>.
3069
3070 The mode actually set is affected by the umask.");
3071
3072   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3073    [InitBasicFS, Always, TestOutputStruct (
3074       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3075        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3076    "make char device node",
3077    "\
3078 This call creates a char device node called C<path> with
3079 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3080 It is just a convenient wrapper around C<guestfs_mknod>.
3081
3082 The mode actually set is affected by the umask.");
3083
3084   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3085    [InitEmpty, Always, TestOutputInt (
3086       [["umask"; "0o22"]], 0o22)],
3087    "set file mode creation mask (umask)",
3088    "\
3089 This function sets the mask used for creating new files and
3090 device nodes to C<mask & 0777>.
3091
3092 Typical umask values would be C<022> which creates new files
3093 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3094 C<002> which creates new files with permissions like
3095 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3096
3097 The default umask is C<022>.  This is important because it
3098 means that directories and device nodes will be created with
3099 C<0644> or C<0755> mode even if you specify C<0777>.
3100
3101 See also C<guestfs_get_umask>,
3102 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3103
3104 This call returns the previous umask.");
3105
3106   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3107    [],
3108    "read directories entries",
3109    "\
3110 This returns the list of directory entries in directory C<dir>.
3111
3112 All entries in the directory are returned, including C<.> and
3113 C<..>.  The entries are I<not> sorted, but returned in the same
3114 order as the underlying filesystem.
3115
3116 Also this call returns basic file type information about each
3117 file.  The C<ftyp> field will contain one of the following characters:
3118
3119 =over 4
3120
3121 =item 'b'
3122
3123 Block special
3124
3125 =item 'c'
3126
3127 Char special
3128
3129 =item 'd'
3130
3131 Directory
3132
3133 =item 'f'
3134
3135 FIFO (named pipe)
3136
3137 =item 'l'
3138
3139 Symbolic link
3140
3141 =item 'r'
3142
3143 Regular file
3144
3145 =item 's'
3146
3147 Socket
3148
3149 =item 'u'
3150
3151 Unknown file type
3152
3153 =item '?'
3154
3155 The L<readdir(3)> call returned a C<d_type> field with an
3156 unexpected value
3157
3158 =back
3159
3160 This function is primarily intended for use by programs.  To
3161 get a simple list of names, use C<guestfs_ls>.  To get a printable
3162 directory for human consumption, use C<guestfs_ll>.");
3163
3164   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3165    [],
3166    "create partitions on a block device",
3167    "\
3168 This is a simplified interface to the C<guestfs_sfdisk>
3169 command, where partition sizes are specified in megabytes
3170 only (rounded to the nearest cylinder) and you don't need
3171 to specify the cyls, heads and sectors parameters which
3172 were rarely if ever used anyway.
3173
3174 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3175 and C<guestfs_part_disk>");
3176
3177   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3178    [],
3179    "determine file type inside a compressed file",
3180    "\
3181 This command runs C<file> after first decompressing C<path>
3182 using C<method>.
3183
3184 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3185
3186 Since 1.0.63, use C<guestfs_file> instead which can now
3187 process compressed files.");
3188
3189   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3190    [],
3191    "list extended attributes of a file or directory",
3192    "\
3193 This call lists the extended attributes of the file or directory
3194 C<path>.
3195
3196 At the system call level, this is a combination of the
3197 L<listxattr(2)> and L<getxattr(2)> calls.
3198
3199 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3200
3201   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3202    [],
3203    "list extended attributes of a file or directory",
3204    "\
3205 This is the same as C<guestfs_getxattrs>, but if C<path>
3206 is a symbolic link, then it returns the extended attributes
3207 of the link itself.");
3208
3209   ("setxattr", (RErr, [String "xattr";
3210                        String "val"; Int "vallen"; (* will be BufferIn *)
3211                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3212    [],
3213    "set extended attribute of a file or directory",
3214    "\
3215 This call sets the extended attribute named C<xattr>
3216 of the file C<path> to the value C<val> (of length C<vallen>).
3217 The value is arbitrary 8 bit data.
3218
3219 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3220
3221   ("lsetxattr", (RErr, [String "xattr";
3222                         String "val"; Int "vallen"; (* will be BufferIn *)
3223                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3224    [],
3225    "set extended attribute of a file or directory",
3226    "\
3227 This is the same as C<guestfs_setxattr>, but if C<path>
3228 is a symbolic link, then it sets an extended attribute
3229 of the link itself.");
3230
3231   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3232    [],
3233    "remove extended attribute of a file or directory",
3234    "\
3235 This call removes the extended attribute named C<xattr>
3236 of the file C<path>.
3237
3238 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3239
3240   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3241    [],
3242    "remove extended attribute of a file or directory",
3243    "\
3244 This is the same as C<guestfs_removexattr>, but if C<path>
3245 is a symbolic link, then it removes an extended attribute
3246 of the link itself.");
3247
3248   ("mountpoints", (RHashtable "mps", []), 147, [],
3249    [],
3250    "show mountpoints",
3251    "\
3252 This call is similar to C<guestfs_mounts>.  That call returns
3253 a list of devices.  This one returns a hash table (map) of
3254 device name to directory where the device is mounted.");
3255
3256   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3257    (* This is a special case: while you would expect a parameter
3258     * of type "Pathname", that doesn't work, because it implies
3259     * NEED_ROOT in the generated calling code in stubs.c, and
3260     * this function cannot use NEED_ROOT.
3261     *)
3262    [],
3263    "create a mountpoint",
3264    "\
3265 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3266 specialized calls that can be used to create extra mountpoints
3267 before mounting the first filesystem.
3268
3269 These calls are I<only> necessary in some very limited circumstances,
3270 mainly the case where you want to mount a mix of unrelated and/or
3271 read-only filesystems together.
3272
3273 For example, live CDs often contain a \"Russian doll\" nest of
3274 filesystems, an ISO outer layer, with a squashfs image inside, with
3275 an ext2/3 image inside that.  You can unpack this as follows
3276 in guestfish:
3277
3278  add-ro Fedora-11-i686-Live.iso
3279  run
3280  mkmountpoint /cd
3281  mkmountpoint /squash
3282  mkmountpoint /ext3
3283  mount /dev/sda /cd
3284  mount-loop /cd/LiveOS/squashfs.img /squash
3285  mount-loop /squash/LiveOS/ext3fs.img /ext3
3286
3287 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3288
3289   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3290    [],
3291    "remove a mountpoint",
3292    "\
3293 This calls removes a mountpoint that was previously created
3294 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3295 for full details.");
3296
3297   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3298    [InitISOFS, Always, TestOutputBuffer (
3299       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3300     (* Test various near large, large and too large files (RHBZ#589039). *)
3301     InitBasicFS, Always, TestLastFail (
3302       [["touch"; "/a"];
3303        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3304        ["read_file"; "/a"]]);
3305     InitBasicFS, Always, TestLastFail (
3306       [["touch"; "/a"];
3307        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3308        ["read_file"; "/a"]]);
3309     InitBasicFS, Always, TestLastFail (
3310       [["touch"; "/a"];
3311        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3312        ["read_file"; "/a"]])],
3313    "read a file",
3314    "\
3315 This calls returns the contents of the file C<path> as a
3316 buffer.
3317
3318 Unlike C<guestfs_cat>, this function can correctly
3319 handle files that contain embedded ASCII NUL characters.
3320 However unlike C<guestfs_download>, this function is limited
3321 in the total size of file that can be handled.");
3322
3323   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3326     InitISOFS, Always, TestOutputList (
3327       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3328     (* Test for RHBZ#579608, absolute symbolic links. *)
3329     InitISOFS, Always, TestOutputList (
3330       [["grep"; "nomatch"; "/abssymlink"]], [])],
3331    "return lines matching a pattern",
3332    "\
3333 This calls the external C<grep> program and returns the
3334 matching lines.");
3335
3336   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3337    [InitISOFS, Always, TestOutputList (
3338       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3339    "return lines matching a pattern",
3340    "\
3341 This calls the external C<egrep> program and returns the
3342 matching lines.");
3343
3344   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3345    [InitISOFS, Always, TestOutputList (
3346       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3347    "return lines matching a pattern",
3348    "\
3349 This calls the external C<fgrep> program and returns the
3350 matching lines.");
3351
3352   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3353    [InitISOFS, Always, TestOutputList (
3354       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3355    "return lines matching a pattern",
3356    "\
3357 This calls the external C<grep -i> program and returns the
3358 matching lines.");
3359
3360   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3361    [InitISOFS, Always, TestOutputList (
3362       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3363    "return lines matching a pattern",
3364    "\
3365 This calls the external C<egrep -i> program and returns the
3366 matching lines.");
3367
3368   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3369    [InitISOFS, Always, TestOutputList (
3370       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3371    "return lines matching a pattern",
3372    "\
3373 This calls the external C<fgrep -i> program and returns the
3374 matching lines.");
3375
3376   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3377    [InitISOFS, Always, TestOutputList (
3378       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3379    "return lines matching a pattern",
3380    "\
3381 This calls the external C<zgrep> program and returns the
3382 matching lines.");
3383
3384   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3385    [InitISOFS, Always, TestOutputList (
3386       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3387    "return lines matching a pattern",
3388    "\
3389 This calls the external C<zegrep> program and returns the
3390 matching lines.");
3391
3392   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3393    [InitISOFS, Always, TestOutputList (
3394       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3395    "return lines matching a pattern",
3396    "\
3397 This calls the external C<zfgrep> program and returns the
3398 matching lines.");
3399
3400   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3401    [InitISOFS, Always, TestOutputList (
3402       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3403    "return lines matching a pattern",
3404    "\
3405 This calls the external C<zgrep -i> program and returns the
3406 matching lines.");
3407
3408   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3409    [InitISOFS, Always, TestOutputList (
3410       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3411    "return lines matching a pattern",
3412    "\
3413 This calls the external C<zegrep -i> program and returns the
3414 matching lines.");
3415
3416   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3417    [InitISOFS, Always, TestOutputList (
3418       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3419    "return lines matching a pattern",
3420    "\
3421 This calls the external C<zfgrep -i> program and returns the
3422 matching lines.");
3423
3424   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3425    [InitISOFS, Always, TestOutput (
3426       [["realpath"; "/../directory"]], "/directory")],
3427    "canonicalized absolute pathname",
3428    "\
3429 Return the canonicalized absolute pathname of C<path>.  The
3430 returned path has no C<.>, C<..> or symbolic link path elements.");
3431
3432   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3433    [InitBasicFS, Always, TestOutputStruct (
3434       [["touch"; "/a"];
3435        ["ln"; "/a"; "/b"];
3436        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437    "create a hard link",
3438    "\
3439 This command creates a hard link using the C<ln> command.");
3440
3441   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3442    [InitBasicFS, Always, TestOutputStruct (
3443       [["touch"; "/a"];
3444        ["touch"; "/b"];
3445        ["ln_f"; "/a"; "/b"];
3446        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3447    "create a hard link",
3448    "\
3449 This command creates a hard link using the C<ln -f> command.
3450 The C<-f> option removes the link (C<linkname>) if it exists already.");
3451
3452   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3453    [InitBasicFS, Always, TestOutputStruct (
3454       [["touch"; "/a"];
3455        ["ln_s"; "a"; "/b"];
3456        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3457    "create a symbolic link",
3458    "\
3459 This command creates a symbolic link using the C<ln -s> command.");
3460
3461   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3462    [InitBasicFS, Always, TestOutput (
3463       [["mkdir_p"; "/a/b"];
3464        ["touch"; "/a/b/c"];
3465        ["ln_sf"; "../d"; "/a/b/c"];
3466        ["readlink"; "/a/b/c"]], "../d")],
3467    "create a symbolic link",
3468    "\
3469 This command creates a symbolic link using the C<ln -sf> command,
3470 The C<-f> option removes the link (C<linkname>) if it exists already.");
3471
3472   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3473    [] (* XXX tested above *),
3474    "read the target of a symbolic link",
3475    "\
3476 This command reads the target of a symbolic link.");
3477
3478   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3479    [InitBasicFS, Always, TestOutputStruct (
3480       [["fallocate"; "/a"; "1000000"];
3481        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3482    "preallocate a file in the guest filesystem",
3483    "\
3484 This command preallocates a file (containing zero bytes) named
3485 C<path> of size C<len> bytes.  If the file exists already, it
3486 is overwritten.
3487
3488 Do not confuse this with the guestfish-specific
3489 C<alloc> command which allocates a file in the host and
3490 attaches it as a device.");
3491
3492   ("swapon_device", (RErr, [Device "device"]), 170, [],
3493    [InitPartition, Always, TestRun (
3494       [["mkswap"; "/dev/sda1"];
3495        ["swapon_device"; "/dev/sda1"];
3496        ["swapoff_device"; "/dev/sda1"]])],
3497    "enable swap on device",
3498    "\
3499 This command enables the libguestfs appliance to use the
3500 swap device or partition named C<device>.  The increased
3501 memory is made available for all commands, for example
3502 those run using C<guestfs_command> or C<guestfs_sh>.
3503
3504 Note that you should not swap to existing guest swap
3505 partitions unless you know what you are doing.  They may
3506 contain hibernation information, or other information that
3507 the guest doesn't want you to trash.  You also risk leaking
3508 information about the host to the guest this way.  Instead,
3509 attach a new host device to the guest and swap on that.");
3510
3511   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3512    [], (* XXX tested by swapon_device *)
3513    "disable swap on device",
3514    "\
3515 This command disables the libguestfs appliance swap
3516 device or partition named C<device>.
3517 See C<guestfs_swapon_device>.");
3518
3519   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3520    [InitBasicFS, Always, TestRun (
3521       [["fallocate"; "/swap"; "8388608"];
3522        ["mkswap_file"; "/swap"];
3523        ["swapon_file"; "/swap"];
3524        ["swapoff_file"; "/swap"]])],
3525    "enable swap on file",
3526    "\
3527 This command enables swap to a file.
3528 See C<guestfs_swapon_device> for other notes.");
3529
3530   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3531    [], (* XXX tested by swapon_file *)
3532    "disable swap on file",
3533    "\
3534 This command disables the libguestfs appliance swap on file.");
3535
3536   ("swapon_label", (RErr, [String "label"]), 174, [],
3537    [InitEmpty, Always, TestRun (
3538       [["part_disk"; "/dev/sdb"; "mbr"];
3539        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3540        ["swapon_label"; "swapit"];
3541        ["swapoff_label"; "swapit"];
3542        ["zero"; "/dev/sdb"];
3543        ["blockdev_rereadpt"; "/dev/sdb"]])],
3544    "enable swap on labeled swap partition",
3545    "\
3546 This command enables swap to a labeled swap partition.
3547 See C<guestfs_swapon_device> for other notes.");
3548
3549   ("swapoff_label", (RErr, [String "label"]), 175, [],
3550    [], (* XXX tested by swapon_label *)
3551    "disable swap on labeled swap partition",
3552    "\
3553 This command disables the libguestfs appliance swap on
3554 labeled swap partition.");
3555
3556   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3557    (let uuid = uuidgen () in
3558     [InitEmpty, Always, TestRun (
3559        [["mkswap_U"; uuid; "/dev/sdb"];
3560         ["swapon_uuid"; uuid];
3561         ["swapoff_uuid"; uuid]])]),
3562    "enable swap on swap partition by UUID",
3563    "\
3564 This command enables swap to a swap partition with the given UUID.
3565 See C<guestfs_swapon_device> for other notes.");
3566
3567   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3568    [], (* XXX tested by swapon_uuid *)
3569    "disable swap on swap partition by UUID",
3570    "\
3571 This command disables the libguestfs appliance swap partition
3572 with the given UUID.");
3573
3574   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3575    [InitBasicFS, Always, TestRun (
3576       [["fallocate"; "/swap"; "8388608"];
3577        ["mkswap_file"; "/swap"]])],
3578    "create a swap file",
3579    "\
3580 Create a swap file.
3581
3582 This command just writes a swap file signature to an existing
3583 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3584
3585   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3586    [InitISOFS, Always, TestRun (
3587       [["inotify_init"; "0"]])],
3588    "create an inotify handle",
3589    "\
3590 This command creates a new inotify handle.
3591 The inotify subsystem can be used to notify events which happen to
3592 objects in the guest filesystem.
3593
3594 C<maxevents> is the maximum number of events which will be
3595 queued up between calls to C<guestfs_inotify_read> or
3596 C<guestfs_inotify_files>.
3597 If this is passed as C<0>, then the kernel (or previously set)
3598 default is used.  For Linux 2.6.29 the default was 16384 events.
3599 Beyond this limit, the kernel throws away events, but records
3600 the fact that it threw them away by setting a flag
3601 C<IN_Q_OVERFLOW> in the returned structure list (see
3602 C<guestfs_inotify_read>).
3603
3604 Before any events are generated, you have to add some
3605 watches to the internal watch list.  See:
3606 C<guestfs_inotify_add_watch>,
3607 C<guestfs_inotify_rm_watch> and
3608 C<guestfs_inotify_watch_all>.
3609
3610 Queued up events should be read periodically by calling
3611 C<guestfs_inotify_read>
3612 (or C<guestfs_inotify_files> which is just a helpful
3613 wrapper around C<guestfs_inotify_read>).  If you don't
3614 read the events out often enough then you risk the internal
3615 queue overflowing.
3616
3617 The handle should be closed after use by calling
3618 C<guestfs_inotify_close>.  This also removes any
3619 watches automatically.
3620
3621 See also L<inotify(7)> for an overview of the inotify interface
3622 as exposed by the Linux kernel, which is roughly what we expose
3623 via libguestfs.  Note that there is one global inotify handle
3624 per libguestfs instance.");
3625
3626   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3627    [InitBasicFS, Always, TestOutputList (
3628       [["inotify_init"; "0"];
3629        ["inotify_add_watch"; "/"; "1073741823"];
3630        ["touch"; "/a"];
3631        ["touch"; "/b"];
3632        ["inotify_files"]], ["a"; "b"])],
3633    "add an inotify watch",
3634    "\
3635 Watch C<path> for the events listed in C<mask>.
3636
3637 Note that if C<path> is a directory then events within that
3638 directory are watched, but this does I<not> happen recursively
3639 (in subdirectories).
3640
3641 Note for non-C or non-Linux callers: the inotify events are
3642 defined by the Linux kernel ABI and are listed in
3643 C</usr/include/sys/inotify.h>.");
3644
3645   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3646    [],
3647    "remove an inotify watch",
3648    "\
3649 Remove a previously defined inotify watch.
3650 See C<guestfs_inotify_add_watch>.");
3651
3652   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3653    [],
3654    "return list of inotify events",
3655    "\
3656 Return the complete queue of events that have happened
3657 since the previous read call.
3658
3659 If no events have happened, this returns an empty list.
3660
3661 I<Note>: In order to make sure that all events have been
3662 read, you must call this function repeatedly until it
3663 returns an empty list.  The reason is that the call will
3664 read events up to the maximum appliance-to-host message
3665 size and leave remaining events in the queue.");
3666
3667   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3668    [],
3669    "return list of watched files that had events",
3670    "\
3671 This function is a helpful wrapper around C<guestfs_inotify_read>
3672 which just returns a list of pathnames of objects that were
3673 touched.  The returned pathnames are sorted and deduplicated.");
3674
3675   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3676    [],
3677    "close the inotify handle",
3678    "\
3679 This closes the inotify handle which was previously
3680 opened by inotify_init.  It removes all watches, throws
3681 away any pending events, and deallocates all resources.");
3682
3683   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3684    [],
3685    "set SELinux security context",
3686    "\
3687 This sets the SELinux security context of the daemon
3688 to the string C<context>.
3689
3690 See the documentation about SELINUX in L<guestfs(3)>.");
3691
3692   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3693    [],
3694    "get SELinux security context",
3695    "\
3696 This gets the SELinux security context of the daemon.
3697
3698 See the documentation about SELINUX in L<guestfs(3)>,
3699 and C<guestfs_setcon>");
3700
3701   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3702    [InitEmpty, Always, TestOutput (
3703       [["part_disk"; "/dev/sda"; "mbr"];
3704        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3705        ["mount_options"; ""; "/dev/sda1"; "/"];
3706        ["write"; "/new"; "new file contents"];
3707        ["cat"; "/new"]], "new file contents")],
3708    "make a filesystem with block size",
3709    "\
3710 This call is similar to C<guestfs_mkfs>, but it allows you to
3711 control the block size of the resulting filesystem.  Supported
3712 block sizes depend on the filesystem type, but typically they
3713 are C<1024>, C<2048> or C<4096> only.");
3714
3715   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3716    [InitEmpty, Always, TestOutput (
3717       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3718        ["mke2journal"; "4096"; "/dev/sda1"];
3719        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3720        ["mount_options"; ""; "/dev/sda2"; "/"];
3721        ["write"; "/new"; "new file contents"];
3722        ["cat"; "/new"]], "new file contents")],
3723    "make ext2/3/4 external journal",
3724    "\
3725 This creates an ext2 external journal on C<device>.  It is equivalent
3726 to the command:
3727
3728  mke2fs -O journal_dev -b blocksize device");
3729
3730   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3731    [InitEmpty, Always, TestOutput (
3732       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3733        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3734        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3735        ["mount_options"; ""; "/dev/sda2"; "/"];
3736        ["write"; "/new"; "new file contents"];
3737        ["cat"; "/new"]], "new file contents")],
3738    "make ext2/3/4 external journal with label",
3739    "\
3740 This creates an ext2 external journal on C<device> with label C<label>.");
3741
3742   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3743    (let uuid = uuidgen () in
3744     [InitEmpty, Always, TestOutput (
3745        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3746         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3747         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3748         ["mount_options"; ""; "/dev/sda2"; "/"];
3749         ["write"; "/new"; "new file contents"];
3750         ["cat"; "/new"]], "new file contents")]),
3751    "make ext2/3/4 external journal with UUID",
3752    "\
3753 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3754
3755   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3756    [],
3757    "make ext2/3/4 filesystem with external journal",
3758    "\
3759 This creates an ext2/3/4 filesystem on C<device> with
3760 an external journal on C<journal>.  It is equivalent
3761 to the command:
3762
3763  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3764
3765 See also C<guestfs_mke2journal>.");
3766
3767   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3768    [],
3769    "make ext2/3/4 filesystem with external journal",
3770    "\
3771 This creates an ext2/3/4 filesystem on C<device> with
3772 an external journal on the journal labeled C<label>.
3773
3774 See also C<guestfs_mke2journal_L>.");
3775
3776   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3777    [],
3778    "make ext2/3/4 filesystem with external journal",
3779    "\
3780 This creates an ext2/3/4 filesystem on C<device> with
3781 an external journal on the journal with UUID C<uuid>.
3782
3783 See also C<guestfs_mke2journal_U>.");
3784
3785   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3786    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3787    "load a kernel module",
3788    "\
3789 This loads a kernel module in the appliance.
3790
3791 The kernel module must have been whitelisted when libguestfs
3792 was built (see C<appliance/kmod.whitelist.in> in the source).");
3793
3794   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3795    [InitNone, Always, TestOutput (
3796       [["echo_daemon"; "This is a test"]], "This is a test"
3797     )],
3798    "echo arguments back to the client",
3799    "\
3800 This command concatenates the list of C<words> passed with single spaces
3801 between them and returns the resulting string.
3802
3803 You can use this command to test the connection through to the daemon.
3804
3805 See also C<guestfs_ping_daemon>.");
3806
3807   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3808    [], (* There is a regression test for this. *)
3809    "find all files and directories, returning NUL-separated list",
3810    "\
3811 This command lists out all files and directories, recursively,
3812 starting at C<directory>, placing the resulting list in the
3813 external file called C<files>.
3814
3815 This command works the same way as C<guestfs_find> with the
3816 following exceptions:
3817
3818 =over 4
3819
3820 =item *
3821
3822 The resulting list is written to an external file.
3823
3824 =item *
3825
3826 Items (filenames) in the result are separated
3827 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3828
3829 =item *
3830
3831 This command is not limited in the number of names that it
3832 can return.
3833
3834 =item *
3835
3836 The result list is not sorted.
3837
3838 =back");
3839
3840   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3841    [InitISOFS, Always, TestOutput (
3842       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3843     InitISOFS, Always, TestOutput (
3844       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3845     InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3847     InitISOFS, Always, TestLastFail (
3848       [["case_sensitive_path"; "/Known-1/"]]);
3849     InitBasicFS, Always, TestOutput (
3850       [["mkdir"; "/a"];
3851        ["mkdir"; "/a/bbb"];
3852        ["touch"; "/a/bbb/c"];
3853        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3854     InitBasicFS, Always, TestOutput (
3855       [["mkdir"; "/a"];
3856        ["mkdir"; "/a/bbb"];
3857        ["touch"; "/a/bbb/c"];
3858        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3859     InitBasicFS, Always, TestLastFail (
3860       [["mkdir"; "/a"];
3861        ["mkdir"; "/a/bbb"];
3862        ["touch"; "/a/bbb/c"];
3863        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3864    "return true path on case-insensitive filesystem",
3865    "\
3866 This can be used to resolve case insensitive paths on
3867 a filesystem which is case sensitive.  The use case is
3868 to resolve paths which you have read from Windows configuration
3869 files or the Windows Registry, to the true path.
3870
3871 The command handles a peculiarity of the Linux ntfs-3g
3872 filesystem driver (and probably others), which is that although
3873 the underlying filesystem is case-insensitive, the driver
3874 exports the filesystem to Linux as case-sensitive.
3875
3876 One consequence of this is that special directories such
3877 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3878 (or other things) depending on the precise details of how
3879 they were created.  In Windows itself this would not be
3880 a problem.
3881
3882 Bug or feature?  You decide:
3883 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3884
3885 This function resolves the true case of each element in the
3886 path and returns the case-sensitive path.
3887
3888 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3889 might return C<\"/WINDOWS/system32\"> (the exact return value
3890 would depend on details of how the directories were originally
3891 created under Windows).
3892
3893 I<Note>:
3894 This function does not handle drive names, backslashes etc.
3895
3896 See also C<guestfs_realpath>.");
3897
3898   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3899    [InitBasicFS, Always, TestOutput (
3900       [["vfs_type"; "/dev/sda1"]], "ext2")],
3901    "get the Linux VFS type corresponding to a mounted device",
3902    "\
3903 This command gets the block device type corresponding to
3904 a mounted device called C<device>.
3905
3906 Usually the result is the name of the Linux VFS module that
3907 is used to mount this device (probably determined automatically
3908 if you used the C<guestfs_mount> call).");
3909
3910   ("truncate", (RErr, [Pathname "path"]), 199, [],
3911    [InitBasicFS, Always, TestOutputStruct (
3912       [["write"; "/test"; "some stuff so size is not zero"];
3913        ["truncate"; "/test"];
3914        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3915    "truncate a file to zero size",
3916    "\
3917 This command truncates C<path> to a zero-length file.  The
3918 file must exist already.");
3919
3920   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3921    [InitBasicFS, Always, TestOutputStruct (
3922       [["touch"; "/test"];
3923        ["truncate_size"; "/test"; "1000"];
3924        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3925    "truncate a file to a particular size",
3926    "\
3927 This command truncates C<path> to size C<size> bytes.  The file
3928 must exist already.
3929
3930 If the current file size is less than C<size> then
3931 the file is extended to the required size with zero bytes.
3932 This creates a sparse file (ie. disk blocks are not allocated
3933 for the file until you write to it).  To create a non-sparse
3934 file of zeroes, use C<guestfs_fallocate64> instead.");
3935
3936   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3937    [InitBasicFS, Always, TestOutputStruct (
3938       [["touch"; "/test"];
3939        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3940        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3941    "set timestamp of a file with nanosecond precision",
3942    "\
3943 This command sets the timestamps of a file with nanosecond
3944 precision.
3945
3946 C<atsecs, atnsecs> are the last access time (atime) in secs and
3947 nanoseconds from the epoch.
3948
3949 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3950 secs and nanoseconds from the epoch.
3951
3952 If the C<*nsecs> field contains the special value C<-1> then
3953 the corresponding timestamp is set to the current time.  (The
3954 C<*secs> field is ignored in this case).
3955
3956 If the C<*nsecs> field contains the special value C<-2> then
3957 the corresponding timestamp is left unchanged.  (The
3958 C<*secs> field is ignored in this case).");
3959
3960   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3961    [InitBasicFS, Always, TestOutputStruct (
3962       [["mkdir_mode"; "/test"; "0o111"];
3963        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3964    "create a directory with a particular mode",
3965    "\
3966 This command creates a directory, setting the initial permissions
3967 of the directory to C<mode>.
3968
3969 For common Linux filesystems, the actual mode which is set will
3970 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3971 interpret the mode in other ways.
3972
3973 See also C<guestfs_mkdir>, C<guestfs_umask>");
3974
3975   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3976    [], (* XXX *)
3977    "change file owner and group",
3978    "\
3979 Change the file owner to C<owner> and group to C<group>.
3980 This is like C<guestfs_chown> but if C<path> is a symlink then
3981 the link itself is changed, not the target.
3982
3983 Only numeric uid and gid are supported.  If you want to use
3984 names, you will need to locate and parse the password file
3985 yourself (Augeas support makes this relatively easy).");
3986
3987   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3988    [], (* XXX *)
3989    "lstat on multiple files",
3990    "\
3991 This call allows you to perform the C<guestfs_lstat> operation
3992 on multiple files, where all files are in the directory C<path>.
3993 C<names> is the list of files from this directory.
3994
3995 On return you get a list of stat structs, with a one-to-one
3996 correspondence to the C<names> list.  If any name did not exist
3997 or could not be lstat'd, then the C<ino> field of that structure
3998 is set to C<-1>.
3999
4000 This call is intended for programs that want to efficiently
4001 list a directory contents without making many round-trips.
4002 See also C<guestfs_lxattrlist> for a similarly efficient call
4003 for getting extended attributes.  Very long directory listings
4004 might cause the protocol message size to be exceeded, causing
4005 this call to fail.  The caller must split up such requests
4006 into smaller groups of names.");
4007
4008   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4009    [], (* XXX *)
4010    "lgetxattr on multiple files",
4011    "\
4012 This call allows you to get the extended attributes
4013 of multiple files, where all files are in the directory C<path>.
4014 C<names> is the list of files from this directory.
4015
4016 On return you get a flat list of xattr structs which must be
4017 interpreted sequentially.  The first xattr struct always has a zero-length
4018 C<attrname>.  C<attrval> in this struct is zero-length
4019 to indicate there was an error doing C<lgetxattr> for this
4020 file, I<or> is a C string which is a decimal number
4021 (the number of following attributes for this file, which could
4022 be C<\"0\">).  Then after the first xattr struct are the
4023 zero or more attributes for the first named file.
4024 This repeats for the second and subsequent files.
4025
4026 This call is intended for programs that want to efficiently
4027 list a directory contents without making many round-trips.
4028 See also C<guestfs_lstatlist> for a similarly efficient call
4029 for getting standard stats.  Very long directory listings
4030 might cause the protocol message size to be exceeded, causing
4031 this call to fail.  The caller must split up such requests
4032 into smaller groups of names.");
4033
4034   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4035    [], (* XXX *)
4036    "readlink on multiple files",
4037    "\
4038 This call allows you to do a C<readlink> operation
4039 on multiple files, where all files are in the directory C<path>.
4040 C<names> is the list of files from this directory.
4041
4042 On return you get a list of strings, with a one-to-one
4043 correspondence to the C<names> list.  Each string is the
4044 value of the symbolic link.
4045
4046 If the C<readlink(2)> operation fails on any name, then
4047 the corresponding result string is the empty string C<\"\">.
4048 However the whole operation is completed even if there
4049 were C<readlink(2)> errors, and so you can call this
4050 function with names where you don't know if they are
4051 symbolic links already (albeit slightly less efficient).
4052
4053 This call is intended for programs that want to efficiently
4054 list a directory contents without making many round-trips.
4055 Very long directory listings might cause the protocol
4056 message size to be exceeded, causing
4057 this call to fail.  The caller must split up such requests
4058 into smaller groups of names.");
4059
4060   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4061    [InitISOFS, Always, TestOutputBuffer (
4062       [["pread"; "/known-4"; "1"; "3"]], "\n");
4063     InitISOFS, Always, TestOutputBuffer (
4064       [["pread"; "/empty"; "0"; "100"]], "")],
4065    "read part of a file",
4066    "\
4067 This command lets you read part of a file.  It reads C<count>
4068 bytes of the file, starting at C<offset>, from file C<path>.
4069
4070 This may read fewer bytes than requested.  For further details
4071 see the L<pread(2)> system call.
4072
4073 See also C<guestfs_pwrite>.");
4074
4075   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4076    [InitEmpty, Always, TestRun (
4077       [["part_init"; "/dev/sda"; "gpt"]])],
4078    "create an empty partition table",
4079    "\
4080 This creates an empty partition table on C<device> of one of the
4081 partition types listed below.  Usually C<parttype> should be
4082 either C<msdos> or C<gpt> (for large disks).
4083
4084 Initially there are no partitions.  Following this, you should
4085 call C<guestfs_part_add> for each partition required.
4086
4087 Possible values for C<parttype> are:
4088
4089 =over 4
4090
4091 =item B<efi> | B<gpt>
4092
4093 Intel EFI / GPT partition table.
4094
4095 This is recommended for >= 2 TB partitions that will be accessed
4096 from Linux and Intel-based Mac OS X.  It also has limited backwards
4097 compatibility with the C<mbr> format.
4098
4099 =item B<mbr> | B<msdos>
4100
4101 The standard PC \"Master Boot Record\" (MBR) format used
4102 by MS-DOS and Windows.  This partition type will B<only> work
4103 for device sizes up to 2 TB.  For large disks we recommend
4104 using C<gpt>.
4105
4106 =back
4107
4108 Other partition table types that may work but are not
4109 supported include:
4110
4111 =over 4
4112
4113 =item B<aix>
4114
4115 AIX disk labels.
4116
4117 =item B<amiga> | B<rdb>
4118
4119 Amiga \"Rigid Disk Block\" format.
4120
4121 =item B<bsd>
4122
4123 BSD disk labels.
4124
4125 =item B<dasd>
4126
4127 DASD, used on IBM mainframes.
4128
4129 =item B<dvh>
4130
4131 MIPS/SGI volumes.
4132
4133 =item B<mac>
4134
4135 Old Mac partition format.  Modern Macs use C<gpt>.
4136
4137 =item B<pc98>
4138
4139 NEC PC-98 format, common in Japan apparently.
4140
4141 =item B<sun>
4142
4143 Sun disk labels.
4144
4145 =back");
4146
4147   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4148    [InitEmpty, Always, TestRun (
4149       [["part_init"; "/dev/sda"; "mbr"];
4150        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4151     InitEmpty, Always, TestRun (
4152       [["part_init"; "/dev/sda"; "gpt"];
4153        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4154        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4155     InitEmpty, Always, TestRun (
4156       [["part_init"; "/dev/sda"; "mbr"];
4157        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4158        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4159        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4160        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4161    "add a partition to the device",
4162    "\
4163 This command adds a partition to C<device>.  If there is no partition
4164 table on the device, call C<guestfs_part_init> first.
4165
4166 The C<prlogex> parameter is the type of partition.  Normally you
4167 should pass C<p> or C<primary> here, but MBR partition tables also
4168 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4169 types.
4170
4171 C<startsect> and C<endsect> are the start and end of the partition
4172 in I<sectors>.  C<endsect> may be negative, which means it counts
4173 backwards from the end of the disk (C<-1> is the last sector).
4174
4175 Creating a partition which covers the whole disk is not so easy.
4176 Use C<guestfs_part_disk> to do that.");
4177
4178   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4179    [InitEmpty, Always, TestRun (
4180       [["part_disk"; "/dev/sda"; "mbr"]]);
4181     InitEmpty, Always, TestRun (
4182       [["part_disk"; "/dev/sda"; "gpt"]])],
4183    "partition whole disk with a single primary partition",
4184    "\
4185 This command is simply a combination of C<guestfs_part_init>
4186 followed by C<guestfs_part_add> to create a single primary partition
4187 covering the whole disk.
4188
4189 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4190 but other possible values are described in C<guestfs_part_init>.");
4191
4192   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4193    [InitEmpty, Always, TestRun (
4194       [["part_disk"; "/dev/sda"; "mbr"];
4195        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4196    "make a partition bootable",
4197    "\
4198 This sets the bootable flag on partition numbered C<partnum> on
4199 device C<device>.  Note that partitions are numbered from 1.
4200
4201 The bootable flag is used by some operating systems (notably
4202 Windows) to determine which partition to boot from.  It is by
4203 no means universally recognized.");
4204
4205   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4206    [InitEmpty, Always, TestRun (
4207       [["part_disk"; "/dev/sda"; "gpt"];
4208        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4209    "set partition name",
4210    "\
4211 This sets the partition name on partition numbered C<partnum> on
4212 device C<device>.  Note that partitions are numbered from 1.
4213
4214 The partition name can only be set on certain types of partition
4215 table.  This works on C<gpt> but not on C<mbr> partitions.");
4216
4217   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4218    [], (* XXX Add a regression test for this. *)
4219    "list partitions on a device",
4220    "\
4221 This command parses the partition table on C<device> and
4222 returns the list of partitions found.
4223
4224 The fields in the returned structure are:
4225
4226 =over 4
4227
4228 =item B<part_num>
4229
4230 Partition number, counting from 1.
4231
4232 =item B<part_start>
4233
4234 Start of the partition I<in bytes>.  To get sectors you have to
4235 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4236
4237 =item B<part_end>
4238
4239 End of the partition in bytes.
4240
4241 =item B<part_size>
4242
4243 Size of the partition in bytes.
4244
4245 =back");
4246
4247   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4248    [InitEmpty, Always, TestOutput (
4249       [["part_disk"; "/dev/sda"; "gpt"];
4250        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4251    "get the partition table type",
4252    "\
4253 This command examines the partition table on C<device> and
4254 returns the partition table type (format) being used.
4255
4256 Common return values include: C<msdos> (a DOS/Windows style MBR
4257 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4258 values are possible, although unusual.  See C<guestfs_part_init>
4259 for a full list.");
4260
4261   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4262    [InitBasicFS, Always, TestOutputBuffer (
4263       [["fill"; "0x63"; "10"; "/test"];
4264        ["read_file"; "/test"]], "cccccccccc")],
4265    "fill a file with octets",
4266    "\
4267 This command creates a new file called C<path>.  The initial
4268 content of the file is C<len> octets of C<c>, where C<c>
4269 must be a number in the range C<[0..255]>.
4270
4271 To fill a file with zero bytes (sparsely), it is
4272 much more efficient to use C<guestfs_truncate_size>.
4273 To create a file with a pattern of repeating bytes
4274 use C<guestfs_fill_pattern>.");
4275
4276   ("available", (RErr, [StringList "groups"]), 216, [],
4277    [InitNone, Always, TestRun [["available"; ""]]],
4278    "test availability of some parts of the API",
4279    "\
4280 This command is used to check the availability of some
4281 groups of functionality in the appliance, which not all builds of
4282 the libguestfs appliance will be able to provide.
4283
4284 The libguestfs groups, and the functions that those
4285 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4286 You can also fetch this list at runtime by calling
4287 C<guestfs_available_all_groups>.
4288
4289 The argument C<groups> is a list of group names, eg:
4290 C<[\"inotify\", \"augeas\"]> would check for the availability of
4291 the Linux inotify functions and Augeas (configuration file
4292 editing) functions.
4293
4294 The command returns no error if I<all> requested groups are available.
4295
4296 It fails with an error if one or more of the requested
4297 groups is unavailable in the appliance.
4298
4299 If an unknown group name is included in the
4300 list of groups then an error is always returned.
4301
4302 I<Notes:>
4303
4304 =over 4
4305
4306 =item *
4307
4308 You must call C<guestfs_launch> before calling this function.
4309
4310 The reason is because we don't know what groups are
4311 supported by the appliance/daemon until it is running and can
4312 be queried.
4313
4314 =item *
4315
4316 If a group of functions is available, this does not necessarily
4317 mean that they will work.  You still have to check for errors
4318 when calling individual API functions even if they are
4319 available.
4320
4321 =item *
4322
4323 It is usually the job of distro packagers to build
4324 complete functionality into the libguestfs appliance.
4325 Upstream libguestfs, if built from source with all
4326 requirements satisfied, will support everything.
4327
4328 =item *
4329
4330 This call was added in version C<1.0.80>.  In previous
4331 versions of libguestfs all you could do would be to speculatively
4332 execute a command to find out if the daemon implemented it.
4333 See also C<guestfs_version>.
4334
4335 =back");
4336
4337   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4338    [InitBasicFS, Always, TestOutputBuffer (
4339       [["write"; "/src"; "hello, world"];
4340        ["dd"; "/src"; "/dest"];
4341        ["read_file"; "/dest"]], "hello, world")],
4342    "copy from source to destination using dd",
4343    "\
4344 This command copies from one source device or file C<src>
4345 to another destination device or file C<dest>.  Normally you
4346 would use this to copy to or from a device or partition, for
4347 example to duplicate a filesystem.
4348
4349 If the destination is a device, it must be as large or larger
4350 than the source file or device, otherwise the copy will fail.
4351 This command cannot do partial copies (see C<guestfs_copy_size>).");
4352
4353   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4354    [InitBasicFS, Always, TestOutputInt (
4355       [["write"; "/file"; "hello, world"];
4356        ["filesize"; "/file"]], 12)],
4357    "return the size of the file in bytes",
4358    "\
4359 This command returns the size of C<file> in bytes.
4360
4361 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4362 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4363 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4364
4365   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4366    [InitBasicFSonLVM, Always, TestOutputList (
4367       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4368        ["lvs"]], ["/dev/VG/LV2"])],
4369    "rename an LVM logical volume",
4370    "\
4371 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4372
4373   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4374    [InitBasicFSonLVM, Always, TestOutputList (
4375       [["umount"; "/"];
4376        ["vg_activate"; "false"; "VG"];
4377        ["vgrename"; "VG"; "VG2"];
4378        ["vg_activate"; "true"; "VG2"];
4379        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4380        ["vgs"]], ["VG2"])],
4381    "rename an LVM volume group",
4382    "\
4383 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4384
4385   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4386    [InitISOFS, Always, TestOutputBuffer (
4387       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4388    "list the contents of a single file in an initrd",
4389    "\
4390 This command unpacks the file C<filename> from the initrd file
4391 called C<initrdpath>.  The filename must be given I<without> the
4392 initial C</> character.
4393
4394 For example, in guestfish you could use the following command
4395 to examine the boot script (usually called C</init>)
4396 contained in a Linux initrd or initramfs image:
4397
4398  initrd-cat /boot/initrd-<version>.img init
4399
4400 See also C<guestfs_initrd_list>.");
4401
4402   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4403    [],
4404    "get the UUID of a physical volume",
4405    "\
4406 This command returns the UUID of the LVM PV C<device>.");
4407
4408   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4409    [],
4410    "get the UUID of a volume group",
4411    "\
4412 This command returns the UUID of the LVM VG named C<vgname>.");
4413
4414   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4415    [],
4416    "get the UUID of a logical volume",
4417    "\
4418 This command returns the UUID of the LVM LV C<device>.");
4419
4420   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4421    [],
4422    "get the PV UUIDs containing the volume group",
4423    "\
4424 Given a VG called C<vgname>, this returns the UUIDs of all
4425 the physical volumes that this volume group resides on.
4426
4427 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4428 calls to associate physical volumes and volume groups.
4429
4430 See also C<guestfs_vglvuuids>.");
4431
4432   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4433    [],
4434    "get the LV UUIDs of all LVs in the volume group",
4435    "\
4436 Given a VG called C<vgname>, this returns the UUIDs of all
4437 the logical volumes created in this volume group.
4438
4439 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4440 calls to associate logical volumes and volume groups.
4441
4442 See also C<guestfs_vgpvuuids>.");
4443
4444   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4445    [InitBasicFS, Always, TestOutputBuffer (
4446       [["write"; "/src"; "hello, world"];
4447        ["copy_size"; "/src"; "/dest"; "5"];
4448        ["read_file"; "/dest"]], "hello")],
4449    "copy size bytes from source to destination using dd",
4450    "\
4451 This command copies exactly C<size> bytes from one source device
4452 or file C<src> to another destination device or file C<dest>.
4453
4454 Note this will fail if the source is too short or if the destination
4455 is not large enough.");
4456
4457   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4458    [InitBasicFSonLVM, Always, TestRun (
4459       [["zero_device"; "/dev/VG/LV"]])],
4460    "write zeroes to an entire device",
4461    "\
4462 This command writes zeroes over the entire C<device>.  Compare
4463 with C<guestfs_zero> which just zeroes the first few blocks of
4464 a device.");
4465
4466   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4467    [InitBasicFS, Always, TestOutput (
4468       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4469        ["cat"; "/hello"]], "hello\n")],
4470    "unpack compressed tarball to directory",
4471    "\
4472 This command uploads and unpacks local file C<tarball> (an
4473 I<xz compressed> tar file) into C<directory>.");
4474
4475   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4476    [],
4477    "pack directory into compressed tarball",
4478    "\
4479 This command packs the contents of C<directory> and downloads
4480 it to local file C<tarball> (as an xz compressed tar archive).");
4481
4482   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4483    [],
4484    "resize an NTFS filesystem",
4485    "\
4486 This command resizes an NTFS filesystem, expanding or
4487 shrinking it to the size of the underlying device.
4488 See also L<ntfsresize(8)>.");
4489
4490   ("vgscan", (RErr, []), 232, [],
4491    [InitEmpty, Always, TestRun (
4492       [["vgscan"]])],
4493    "rescan for LVM physical volumes, volume groups and logical volumes",
4494    "\
4495 This rescans all block devices and rebuilds the list of LVM
4496 physical volumes, volume groups and logical volumes.");
4497
4498   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4499    [InitEmpty, Always, TestRun (
4500       [["part_init"; "/dev/sda"; "mbr"];
4501        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4502        ["part_del"; "/dev/sda"; "1"]])],
4503    "delete a partition",
4504    "\
4505 This command deletes the partition numbered C<partnum> on C<device>.
4506
4507 Note that in the case of MBR partitioning, deleting an
4508 extended partition also deletes any logical partitions
4509 it contains.");
4510
4511   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4512    [InitEmpty, Always, TestOutputTrue (
4513       [["part_init"; "/dev/sda"; "mbr"];
4514        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4515        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4516        ["part_get_bootable"; "/dev/sda"; "1"]])],
4517    "return true if a partition is bootable",
4518    "\
4519 This command returns true if the partition C<partnum> on
4520 C<device> has the bootable flag set.
4521
4522 See also C<guestfs_part_set_bootable>.");
4523
4524   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4525    [InitEmpty, Always, TestOutputInt (
4526       [["part_init"; "/dev/sda"; "mbr"];
4527        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4528        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4529        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4530    "get the MBR type byte (ID byte) from a partition",
4531    "\
4532 Returns the MBR type byte (also known as the ID byte) from
4533 the numbered partition C<partnum>.
4534
4535 Note that only MBR (old DOS-style) partitions have type bytes.
4536 You will get undefined results for other partition table
4537 types (see C<guestfs_part_get_parttype>).");
4538
4539   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4540    [], (* tested by part_get_mbr_id *)
4541    "set the MBR type byte (ID byte) of a partition",
4542    "\
4543 Sets the MBR type byte (also known as the ID byte) of
4544 the numbered partition C<partnum> to C<idbyte>.  Note
4545 that the type bytes quoted in most documentation are
4546 in fact hexadecimal numbers, but usually documented
4547 without any leading \"0x\" which might be confusing.
4548
4549 Note that only MBR (old DOS-style) partitions have type bytes.
4550 You will get undefined results for other partition table
4551 types (see C<guestfs_part_get_parttype>).");
4552
4553   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4554    [InitISOFS, Always, TestOutput (
4555       [["checksum_device"; "md5"; "/dev/sdd"]],
4556       (Digest.to_hex (Digest.file "images/test.iso")))],
4557    "compute MD5, SHAx or CRC checksum of the contents of a device",
4558    "\
4559 This call computes the MD5, SHAx or CRC checksum of the
4560 contents of the device named C<device>.  For the types of
4561 checksums supported see the C<guestfs_checksum> command.");
4562
4563   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4564    [InitNone, Always, TestRun (
4565       [["part_disk"; "/dev/sda"; "mbr"];
4566        ["pvcreate"; "/dev/sda1"];
4567        ["vgcreate"; "VG"; "/dev/sda1"];
4568        ["lvcreate"; "LV"; "VG"; "10"];
4569        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4570    "expand an LV to fill free space",
4571    "\
4572 This expands an existing logical volume C<lv> so that it fills
4573 C<pc>% of the remaining free space in the volume group.  Commonly
4574 you would call this with pc = 100 which expands the logical volume
4575 as much as possible, using all remaining free space in the volume
4576 group.");
4577
4578   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4579    [], (* XXX Augeas code needs tests. *)
4580    "clear Augeas path",
4581    "\
4582 Set the value associated with C<path> to C<NULL>.  This
4583 is the same as the L<augtool(1)> C<clear> command.");
4584
4585   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4586    [InitEmpty, Always, TestOutputInt (
4587       [["get_umask"]], 0o22)],
4588    "get the current umask",
4589    "\
4590 Return the current umask.  By default the umask is C<022>
4591 unless it has been set by calling C<guestfs_umask>.");
4592
4593   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4594    [],
4595    "upload a file to the appliance (internal use only)",
4596    "\
4597 The C<guestfs_debug_upload> command uploads a file to
4598 the libguestfs appliance.
4599
4600 There is no comprehensive help for this command.  You have
4601 to look at the file C<daemon/debug.c> in the libguestfs source
4602 to find out what it is for.");
4603
4604   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4605    [InitBasicFS, Always, TestOutput (
4606       [["base64_in"; "../images/hello.b64"; "/hello"];
4607        ["cat"; "/hello"]], "hello\n")],
4608    "upload base64-encoded data to file",
4609    "\
4610 This command uploads base64-encoded data from C<base64file>
4611 to C<filename>.");
4612
4613   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4614    [],
4615    "download file and encode as base64",
4616    "\
4617 This command downloads the contents of C<filename>, writing
4618 it out to local file C<base64file> encoded as base64.");
4619
4620   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4621    [],
4622    "compute MD5, SHAx or CRC checksum of files in a directory",
4623    "\
4624 This command computes the checksums of all regular files in
4625 C<directory> and then emits a list of those checksums to
4626 the local output file C<sumsfile>.
4627
4628 This can be used for verifying the integrity of a virtual
4629 machine.  However to be properly secure you should pay
4630 attention to the output of the checksum command (it uses
4631 the ones from GNU coreutils).  In particular when the
4632 filename is not printable, coreutils uses a special
4633 backslash syntax.  For more information, see the GNU
4634 coreutils info file.");
4635
4636   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4637    [InitBasicFS, Always, TestOutputBuffer (
4638       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4639        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4640    "fill a file with a repeating pattern of bytes",
4641    "\
4642 This function is like C<guestfs_fill> except that it creates
4643 a new file of length C<len> containing the repeating pattern
4644 of bytes in C<pattern>.  The pattern is truncated if necessary
4645 to ensure the length of the file is exactly C<len> bytes.");
4646
4647   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4648    [InitBasicFS, Always, TestOutput (
4649       [["write"; "/new"; "new file contents"];
4650        ["cat"; "/new"]], "new file contents");
4651     InitBasicFS, Always, TestOutput (
4652       [["write"; "/new"; "\nnew file contents\n"];
4653        ["cat"; "/new"]], "\nnew file contents\n");
4654     InitBasicFS, Always, TestOutput (
4655       [["write"; "/new"; "\n\n"];
4656        ["cat"; "/new"]], "\n\n");
4657     InitBasicFS, Always, TestOutput (
4658       [["write"; "/new"; ""];
4659        ["cat"; "/new"]], "");
4660     InitBasicFS, Always, TestOutput (
4661       [["write"; "/new"; "\n\n\n"];
4662        ["cat"; "/new"]], "\n\n\n");
4663     InitBasicFS, Always, TestOutput (
4664       [["write"; "/new"; "\n"];
4665        ["cat"; "/new"]], "\n")],
4666    "create a new file",
4667    "\
4668 This call creates a file called C<path>.  The content of the
4669 file is the string C<content> (which can contain any 8 bit data).");
4670
4671   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4672    [InitBasicFS, Always, TestOutput (
4673       [["write"; "/new"; "new file contents"];
4674        ["pwrite"; "/new"; "data"; "4"];
4675        ["cat"; "/new"]], "new data contents");
4676     InitBasicFS, Always, TestOutput (
4677       [["write"; "/new"; "new file contents"];
4678        ["pwrite"; "/new"; "is extended"; "9"];
4679        ["cat"; "/new"]], "new file is extended");
4680     InitBasicFS, Always, TestOutput (
4681       [["write"; "/new"; "new file contents"];
4682        ["pwrite"; "/new"; ""; "4"];
4683        ["cat"; "/new"]], "new file contents")],
4684    "write to part of a file",
4685    "\
4686 This command writes to part of a file.  It writes the data
4687 buffer C<content> to the file C<path> starting at offset C<offset>.
4688
4689 This command implements the L<pwrite(2)> system call, and like
4690 that system call it may not write the full data requested.  The
4691 return value is the number of bytes that were actually written
4692 to the file.  This could even be 0, although short writes are
4693 unlikely for regular files in ordinary circumstances.
4694
4695 See also C<guestfs_pread>.");
4696
4697   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4698    [],
4699    "resize an ext2/ext3 filesystem (with size)",
4700    "\
4701 This command is the same as C<guestfs_resize2fs> except that it
4702 allows you to specify the new size (in bytes) explicitly.");
4703
4704   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4705    [],
4706    "resize an LVM physical volume (with size)",
4707    "\
4708 This command is the same as C<guestfs_pvresize> except that it
4709 allows you to specify the new size (in bytes) explicitly.");
4710
4711   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4712    [],
4713    "resize an NTFS filesystem (with size)",
4714    "\
4715 This command is the same as C<guestfs_ntfsresize> except that it
4716 allows you to specify the new size (in bytes) explicitly.");
4717
4718   ("available_all_groups", (RStringList "groups", []), 251, [],
4719    [InitNone, Always, TestRun [["available_all_groups"]]],
4720    "return a list of all optional groups",
4721    "\
4722 This command returns a list of all optional groups that this
4723 daemon knows about.  Note this returns both supported and unsupported
4724 groups.  To find out which ones the daemon can actually support
4725 you have to call C<guestfs_available> on each member of the
4726 returned list.
4727
4728 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4729
4730   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4731    [InitBasicFS, Always, TestOutputStruct (
4732       [["fallocate64"; "/a"; "1000000"];
4733        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4734    "preallocate a file in the guest filesystem",
4735    "\
4736 This command preallocates a file (containing zero bytes) named
4737 C<path> of size C<len> bytes.  If the file exists already, it
4738 is overwritten.
4739
4740 Note that this call allocates disk blocks for the file.
4741 To create a sparse file use C<guestfs_truncate_size> instead.
4742
4743 The deprecated call C<guestfs_fallocate> does the same,
4744 but owing to an oversight it only allowed 30 bit lengths
4745 to be specified, effectively limiting the maximum size
4746 of files created through that call to 1GB.
4747
4748 Do not confuse this with the guestfish-specific
4749 C<alloc> and C<sparse> commands which create
4750 a file in the host and attach it as a device.");
4751
4752 ]
4753
4754 let all_functions = non_daemon_functions @ daemon_functions
4755
4756 (* In some places we want the functions to be displayed sorted
4757  * alphabetically, so this is useful:
4758  *)
4759 let all_functions_sorted =
4760   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4761                compare n1 n2) all_functions
4762
4763 (* This is used to generate the src/MAX_PROC_NR file which
4764  * contains the maximum procedure number, a surrogate for the
4765  * ABI version number.  See src/Makefile.am for the details.
4766  *)
4767 let max_proc_nr =
4768   let proc_nrs = List.map (
4769     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4770   ) daemon_functions in
4771   List.fold_left max 0 proc_nrs
4772
4773 (* Field types for structures. *)
4774 type field =
4775   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4776   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4777   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4778   | FUInt32
4779   | FInt32
4780   | FUInt64
4781   | FInt64
4782   | FBytes                      (* Any int measure that counts bytes. *)
4783   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4784   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4785
4786 (* Because we generate extra parsing code for LVM command line tools,
4787  * we have to pull out the LVM columns separately here.
4788  *)
4789 let lvm_pv_cols = [
4790   "pv_name", FString;
4791   "pv_uuid", FUUID;
4792   "pv_fmt", FString;
4793   "pv_size", FBytes;
4794   "dev_size", FBytes;
4795   "pv_free", FBytes;
4796   "pv_used", FBytes;
4797   "pv_attr", FString (* XXX *);
4798   "pv_pe_count", FInt64;
4799   "pv_pe_alloc_count", FInt64;
4800   "pv_tags", FString;
4801   "pe_start", FBytes;
4802   "pv_mda_count", FInt64;
4803   "pv_mda_free", FBytes;
4804   (* Not in Fedora 10:
4805      "pv_mda_size", FBytes;
4806   *)
4807 ]
4808 let lvm_vg_cols = [
4809   "vg_name", FString;
4810   "vg_uuid", FUUID;
4811   "vg_fmt", FString;
4812   "vg_attr", FString (* XXX *);
4813   "vg_size", FBytes;
4814   "vg_free", FBytes;
4815   "vg_sysid", FString;
4816   "vg_extent_size", FBytes;
4817   "vg_extent_count", FInt64;
4818   "vg_free_count", FInt64;
4819   "max_lv", FInt64;
4820   "max_pv", FInt64;
4821   "pv_count", FInt64;
4822   "lv_count", FInt64;
4823   "snap_count", FInt64;
4824   "vg_seqno", FInt64;
4825   "vg_tags", FString;
4826   "vg_mda_count", FInt64;
4827   "vg_mda_free", FBytes;
4828   (* Not in Fedora 10:
4829      "vg_mda_size", FBytes;
4830   *)
4831 ]
4832 let lvm_lv_cols = [
4833   "lv_name", FString;
4834   "lv_uuid", FUUID;
4835   "lv_attr", FString (* XXX *);
4836   "lv_major", FInt64;
4837   "lv_minor", FInt64;
4838   "lv_kernel_major", FInt64;
4839   "lv_kernel_minor", FInt64;
4840   "lv_size", FBytes;
4841   "seg_count", FInt64;
4842   "origin", FString;
4843   "snap_percent", FOptPercent;
4844   "copy_percent", FOptPercent;
4845   "move_pv", FString;
4846   "lv_tags", FString;
4847   "mirror_log", FString;
4848   "modules", FString;
4849 ]
4850
4851 (* Names and fields in all structures (in RStruct and RStructList)
4852  * that we support.
4853  *)
4854 let structs = [
4855   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4856    * not use this struct in any new code.
4857    *)
4858   "int_bool", [
4859     "i", FInt32;                (* for historical compatibility *)
4860     "b", FInt32;                (* for historical compatibility *)
4861   ];
4862
4863   (* LVM PVs, VGs, LVs. *)
4864   "lvm_pv", lvm_pv_cols;
4865   "lvm_vg", lvm_vg_cols;
4866   "lvm_lv", lvm_lv_cols;
4867
4868   (* Column names and types from stat structures.
4869    * NB. Can't use things like 'st_atime' because glibc header files
4870    * define some of these as macros.  Ugh.
4871    *)
4872   "stat", [
4873     "dev", FInt64;
4874     "ino", FInt64;
4875     "mode", FInt64;
4876     "nlink", FInt64;
4877     "uid", FInt64;
4878     "gid", FInt64;
4879     "rdev", FInt64;
4880     "size", FInt64;
4881     "blksize", FInt64;
4882     "blocks", FInt64;
4883     "atime", FInt64;
4884     "mtime", FInt64;
4885     "ctime", FInt64;
4886   ];
4887   "statvfs", [
4888     "bsize", FInt64;
4889     "frsize", FInt64;
4890     "blocks", FInt64;
4891     "bfree", FInt64;
4892     "bavail", FInt64;
4893     "files", FInt64;
4894     "ffree", FInt64;
4895     "favail", FInt64;
4896     "fsid", FInt64;
4897     "flag", FInt64;
4898     "namemax", FInt64;
4899   ];
4900
4901   (* Column names in dirent structure. *)
4902   "dirent", [
4903     "ino", FInt64;
4904     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4905     "ftyp", FChar;
4906     "name", FString;
4907   ];
4908
4909   (* Version numbers. *)
4910   "version", [
4911     "major", FInt64;
4912     "minor", FInt64;
4913     "release", FInt64;
4914     "extra", FString;
4915   ];
4916
4917   (* Extended attribute. *)
4918   "xattr", [
4919     "attrname", FString;
4920     "attrval", FBuffer;
4921   ];
4922
4923   (* Inotify events. *)
4924   "inotify_event", [
4925     "in_wd", FInt64;
4926     "in_mask", FUInt32;
4927     "in_cookie", FUInt32;
4928     "in_name", FString;
4929   ];
4930
4931   (* Partition table entry. *)
4932   "partition", [
4933     "part_num", FInt32;
4934     "part_start", FBytes;
4935     "part_end", FBytes;
4936     "part_size", FBytes;
4937   ];
4938 ] (* end of structs *)
4939
4940 (* Ugh, Java has to be different ..
4941  * These names are also used by the Haskell bindings.
4942  *)
4943 let java_structs = [
4944   "int_bool", "IntBool";
4945   "lvm_pv", "PV";
4946   "lvm_vg", "VG";
4947   "lvm_lv", "LV";
4948   "stat", "Stat";
4949   "statvfs", "StatVFS";
4950   "dirent", "Dirent";
4951   "version", "Version";
4952   "xattr", "XAttr";
4953   "inotify_event", "INotifyEvent";
4954   "partition", "Partition";
4955 ]
4956
4957 (* What structs are actually returned. *)
4958 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4959
4960 (* Returns a list of RStruct/RStructList structs that are returned
4961  * by any function.  Each element of returned list is a pair:
4962  *
4963  * (structname, RStructOnly)
4964  *    == there exists function which returns RStruct (_, structname)
4965  * (structname, RStructListOnly)
4966  *    == there exists function which returns RStructList (_, structname)
4967  * (structname, RStructAndList)
4968  *    == there are functions returning both RStruct (_, structname)
4969  *                                      and RStructList (_, structname)
4970  *)
4971 let rstructs_used_by functions =
4972   (* ||| is a "logical OR" for rstructs_used_t *)
4973   let (|||) a b =
4974     match a, b with
4975     | RStructAndList, _
4976     | _, RStructAndList -> RStructAndList
4977     | RStructOnly, RStructListOnly
4978     | RStructListOnly, RStructOnly -> RStructAndList
4979     | RStructOnly, RStructOnly -> RStructOnly
4980     | RStructListOnly, RStructListOnly -> RStructListOnly
4981   in
4982
4983   let h = Hashtbl.create 13 in
4984
4985   (* if elem->oldv exists, update entry using ||| operator,
4986    * else just add elem->newv to the hash
4987    *)
4988   let update elem newv =
4989     try  let oldv = Hashtbl.find h elem in
4990          Hashtbl.replace h elem (newv ||| oldv)
4991     with Not_found -> Hashtbl.add h elem newv
4992   in
4993
4994   List.iter (
4995     fun (_, style, _, _, _, _, _) ->
4996       match fst style with
4997       | RStruct (_, structname) -> update structname RStructOnly
4998       | RStructList (_, structname) -> update structname RStructListOnly
4999       | _ -> ()
5000   ) functions;
5001
5002   (* return key->values as a list of (key,value) *)
5003   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5004
5005 (* Used for testing language bindings. *)
5006 type callt =
5007   | CallString of string
5008   | CallOptString of string option
5009   | CallStringList of string list
5010   | CallInt of int
5011   | CallInt64 of int64
5012   | CallBool of bool
5013   | CallBuffer of string
5014
5015 (* Used to memoize the result of pod2text. *)
5016 let pod2text_memo_filename = "src/.pod2text.data"
5017 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5018   try
5019     let chan = open_in pod2text_memo_filename in
5020     let v = input_value chan in
5021     close_in chan;
5022     v
5023   with
5024     _ -> Hashtbl.create 13
5025 let pod2text_memo_updated () =
5026   let chan = open_out pod2text_memo_filename in
5027   output_value chan pod2text_memo;
5028   close_out chan
5029
5030 (* Useful functions.
5031  * Note we don't want to use any external OCaml libraries which
5032  * makes this a bit harder than it should be.
5033  *)
5034 module StringMap = Map.Make (String)
5035
5036 let failwithf fs = ksprintf failwith fs
5037
5038 let unique = let i = ref 0 in fun () -> incr i; !i
5039
5040 let replace_char s c1 c2 =
5041   let s2 = String.copy s in
5042   let r = ref false in
5043   for i = 0 to String.length s2 - 1 do
5044     if String.unsafe_get s2 i = c1 then (
5045       String.unsafe_set s2 i c2;
5046       r := true
5047     )
5048   done;
5049   if not !r then s else s2
5050
5051 let isspace c =
5052   c = ' '
5053   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5054
5055 let triml ?(test = isspace) str =
5056   let i = ref 0 in
5057   let n = ref (String.length str) in
5058   while !n > 0 && test str.[!i]; do
5059     decr n;
5060     incr i
5061   done;
5062   if !i = 0 then str
5063   else String.sub str !i !n
5064
5065 let trimr ?(test = isspace) str =
5066   let n = ref (String.length str) in
5067   while !n > 0 && test str.[!n-1]; do
5068     decr n
5069   done;
5070   if !n = String.length str then str
5071   else String.sub str 0 !n
5072
5073 let trim ?(test = isspace) str =
5074   trimr ~test (triml ~test str)
5075
5076 let rec find s sub =
5077   let len = String.length s in
5078   let sublen = String.length sub in
5079   let rec loop i =
5080     if i <= len-sublen then (
5081       let rec loop2 j =
5082         if j < sublen then (
5083           if s.[i+j] = sub.[j] then loop2 (j+1)
5084           else -1
5085         ) else
5086           i (* found *)
5087       in
5088       let r = loop2 0 in
5089       if r = -1 then loop (i+1) else r
5090     ) else
5091       -1 (* not found *)
5092   in
5093   loop 0
5094
5095 let rec replace_str s s1 s2 =
5096   let len = String.length s in
5097   let sublen = String.length s1 in
5098   let i = find s s1 in
5099   if i = -1 then s
5100   else (
5101     let s' = String.sub s 0 i in
5102     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5103     s' ^ s2 ^ replace_str s'' s1 s2
5104   )
5105
5106 let rec string_split sep str =
5107   let len = String.length str in
5108   let seplen = String.length sep in
5109   let i = find str sep in
5110   if i = -1 then [str]
5111   else (
5112     let s' = String.sub str 0 i in
5113     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5114     s' :: string_split sep s''
5115   )
5116
5117 let files_equal n1 n2 =
5118   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5119   match Sys.command cmd with
5120   | 0 -> true
5121   | 1 -> false
5122   | i -> failwithf "%s: failed with error code %d" cmd i
5123
5124 let rec filter_map f = function
5125   | [] -> []
5126   | x :: xs ->
5127       match f x with
5128       | Some y -> y :: filter_map f xs
5129       | None -> filter_map f xs
5130
5131 let rec find_map f = function
5132   | [] -> raise Not_found
5133   | x :: xs ->
5134       match f x with
5135       | Some y -> y
5136       | None -> find_map f xs
5137
5138 let iteri f xs =
5139   let rec loop i = function
5140     | [] -> ()
5141     | x :: xs -> f i x; loop (i+1) xs
5142   in
5143   loop 0 xs
5144
5145 let mapi f xs =
5146   let rec loop i = function
5147     | [] -> []
5148     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5149   in
5150   loop 0 xs
5151
5152 let count_chars c str =
5153   let count = ref 0 in
5154   for i = 0 to String.length str - 1 do
5155     if c = String.unsafe_get str i then incr count
5156   done;
5157   !count
5158
5159 let explode str =
5160   let r = ref [] in
5161   for i = 0 to String.length str - 1 do
5162     let c = String.unsafe_get str i in
5163     r := c :: !r;
5164   done;
5165   List.rev !r
5166
5167 let map_chars f str =
5168   List.map f (explode str)
5169
5170 let name_of_argt = function
5171   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5172   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5173   | FileIn n | FileOut n | BufferIn n -> n
5174
5175 let java_name_of_struct typ =
5176   try List.assoc typ java_structs
5177   with Not_found ->
5178     failwithf
5179       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5180
5181 let cols_of_struct typ =
5182   try List.assoc typ structs
5183   with Not_found ->
5184     failwithf "cols_of_struct: unknown struct %s" typ
5185
5186 let seq_of_test = function
5187   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5188   | TestOutputListOfDevices (s, _)
5189   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5190   | TestOutputTrue s | TestOutputFalse s
5191   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5192   | TestOutputStruct (s, _)
5193   | TestLastFail s -> s
5194
5195 (* Handling for function flags. *)
5196 let protocol_limit_warning =
5197   "Because of the message protocol, there is a transfer limit
5198 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5199
5200 let danger_will_robinson =
5201   "B<This command is dangerous.  Without careful use you
5202 can easily destroy all your data>."
5203
5204 let deprecation_notice flags =
5205   try
5206     let alt =
5207       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5208     let txt =
5209       sprintf "This function is deprecated.
5210 In new code, use the C<%s> call instead.
5211
5212 Deprecated functions will not be removed from the API, but the
5213 fact that they are deprecated indicates that there are problems
5214 with correct use of these functions." alt in
5215     Some txt
5216   with
5217     Not_found -> None
5218
5219 (* Create list of optional groups. *)
5220 let optgroups =
5221   let h = Hashtbl.create 13 in
5222   List.iter (
5223     fun (name, _, _, flags, _, _, _) ->
5224       List.iter (
5225         function
5226         | Optional group ->
5227             let names = try Hashtbl.find h group with Not_found -> [] in
5228             Hashtbl.replace h group (name :: names)
5229         | _ -> ()
5230       ) flags
5231   ) daemon_functions;
5232   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5233   let groups =
5234     List.map (
5235       fun group -> group, List.sort compare (Hashtbl.find h group)
5236     ) groups in
5237   List.sort (fun x y -> compare (fst x) (fst y)) groups
5238
5239 (* Check function names etc. for consistency. *)
5240 let check_functions () =
5241   let contains_uppercase str =
5242     let len = String.length str in
5243     let rec loop i =
5244       if i >= len then false
5245       else (
5246         let c = str.[i] in
5247         if c >= 'A' && c <= 'Z' then true
5248         else loop (i+1)
5249       )
5250     in
5251     loop 0
5252   in
5253
5254   (* Check function names. *)
5255   List.iter (
5256     fun (name, _, _, _, _, _, _) ->
5257       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5258         failwithf "function name %s does not need 'guestfs' prefix" name;
5259       if name = "" then
5260         failwithf "function name is empty";
5261       if name.[0] < 'a' || name.[0] > 'z' then
5262         failwithf "function name %s must start with lowercase a-z" name;
5263       if String.contains name '-' then
5264         failwithf "function name %s should not contain '-', use '_' instead."
5265           name
5266   ) all_functions;
5267
5268   (* Check function parameter/return names. *)
5269   List.iter (
5270     fun (name, style, _, _, _, _, _) ->
5271       let check_arg_ret_name n =
5272         if contains_uppercase n then
5273           failwithf "%s param/ret %s should not contain uppercase chars"
5274             name n;
5275         if String.contains n '-' || String.contains n '_' then
5276           failwithf "%s param/ret %s should not contain '-' or '_'"
5277             name n;
5278         if n = "value" then
5279           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;
5280         if n = "int" || n = "char" || n = "short" || n = "long" then
5281           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5282         if n = "i" || n = "n" then
5283           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5284         if n = "argv" || n = "args" then
5285           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5286
5287         (* List Haskell, OCaml and C keywords here.
5288          * http://www.haskell.org/haskellwiki/Keywords
5289          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5290          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5291          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5292          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5293          * Omitting _-containing words, since they're handled above.
5294          * Omitting the OCaml reserved word, "val", is ok,
5295          * and saves us from renaming several parameters.
5296          *)
5297         let reserved = [
5298           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5299           "char"; "class"; "const"; "constraint"; "continue"; "data";
5300           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5301           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5302           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5303           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5304           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5305           "interface";
5306           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5307           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5308           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5309           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5310           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5311           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5312           "volatile"; "when"; "where"; "while";
5313           ] in
5314         if List.mem n reserved then
5315           failwithf "%s has param/ret using reserved word %s" name n;
5316       in
5317
5318       (match fst style with
5319        | RErr -> ()
5320        | RInt n | RInt64 n | RBool n
5321        | RConstString n | RConstOptString n | RString n
5322        | RStringList n | RStruct (n, _) | RStructList (n, _)
5323        | RHashtable n | RBufferOut n ->
5324            check_arg_ret_name n
5325       );
5326       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5327   ) all_functions;
5328
5329   (* Check short descriptions. *)
5330   List.iter (
5331     fun (name, _, _, _, _, shortdesc, _) ->
5332       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5333         failwithf "short description of %s should begin with lowercase." name;
5334       let c = shortdesc.[String.length shortdesc-1] in
5335       if c = '\n' || c = '.' then
5336         failwithf "short description of %s should not end with . or \\n." name
5337   ) all_functions;
5338
5339   (* Check long descriptions. *)
5340   List.iter (
5341     fun (name, _, _, _, _, _, longdesc) ->
5342       if longdesc.[String.length longdesc-1] = '\n' then
5343         failwithf "long description of %s should not end with \\n." name
5344   ) all_functions;
5345
5346   (* Check proc_nrs. *)
5347   List.iter (
5348     fun (name, _, proc_nr, _, _, _, _) ->
5349       if proc_nr <= 0 then
5350         failwithf "daemon function %s should have proc_nr > 0" name
5351   ) daemon_functions;
5352
5353   List.iter (
5354     fun (name, _, proc_nr, _, _, _, _) ->
5355       if proc_nr <> -1 then
5356         failwithf "non-daemon function %s should have proc_nr -1" name
5357   ) non_daemon_functions;
5358
5359   let proc_nrs =
5360     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5361       daemon_functions in
5362   let proc_nrs =
5363     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5364   let rec loop = function
5365     | [] -> ()
5366     | [_] -> ()
5367     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5368         loop rest
5369     | (name1,nr1) :: (name2,nr2) :: _ ->
5370         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5371           name1 name2 nr1 nr2
5372   in
5373   loop proc_nrs;
5374
5375   (* Check tests. *)
5376   List.iter (
5377     function
5378       (* Ignore functions that have no tests.  We generate a
5379        * warning when the user does 'make check' instead.
5380        *)
5381     | name, _, _, _, [], _, _ -> ()
5382     | name, _, _, _, tests, _, _ ->
5383         let funcs =
5384           List.map (
5385             fun (_, _, test) ->
5386               match seq_of_test test with
5387               | [] ->
5388                   failwithf "%s has a test containing an empty sequence" name
5389               | cmds -> List.map List.hd cmds
5390           ) tests in
5391         let funcs = List.flatten funcs in
5392
5393         let tested = List.mem name funcs in
5394
5395         if not tested then
5396           failwithf "function %s has tests but does not test itself" name
5397   ) all_functions
5398
5399 (* 'pr' prints to the current output file. *)
5400 let chan = ref Pervasives.stdout
5401 let lines = ref 0
5402 let pr fs =
5403   ksprintf
5404     (fun str ->
5405        let i = count_chars '\n' str in
5406        lines := !lines + i;
5407        output_string !chan str
5408     ) fs
5409
5410 let copyright_years =
5411   let this_year = 1900 + (localtime (time ())).tm_year in
5412   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5413
5414 (* Generate a header block in a number of standard styles. *)
5415 type comment_style =
5416     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5417 type license = GPLv2plus | LGPLv2plus
5418
5419 let generate_header ?(extra_inputs = []) comment license =
5420   let inputs = "src/generator.ml" :: extra_inputs in
5421   let c = match comment with
5422     | CStyle ->         pr "/* "; " *"
5423     | CPlusPlusStyle -> pr "// "; "//"
5424     | HashStyle ->      pr "# ";  "#"
5425     | OCamlStyle ->     pr "(* "; " *"
5426     | HaskellStyle ->   pr "{- "; "  " in
5427   pr "libguestfs generated file\n";
5428   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5429   List.iter (pr "%s   %s\n" c) inputs;
5430   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5431   pr "%s\n" c;
5432   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5433   pr "%s\n" c;
5434   (match license with
5435    | GPLv2plus ->
5436        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5437        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5438        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5439        pr "%s (at your option) any later version.\n" c;
5440        pr "%s\n" c;
5441        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5442        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5443        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5444        pr "%s GNU General Public License for more details.\n" c;
5445        pr "%s\n" c;
5446        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5447        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5448        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5449
5450    | LGPLv2plus ->
5451        pr "%s This library is free software; you can redistribute it and/or\n" c;
5452        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5453        pr "%s License as published by the Free Software Foundation; either\n" c;
5454        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5455        pr "%s\n" c;
5456        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5457        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5458        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5459        pr "%s Lesser General Public License for more details.\n" c;
5460        pr "%s\n" c;
5461        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5462        pr "%s License along with this library; if not, write to the Free Software\n" c;
5463        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5464   );
5465   (match comment with
5466    | CStyle -> pr " */\n"
5467    | CPlusPlusStyle
5468    | HashStyle -> ()
5469    | OCamlStyle -> pr " *)\n"
5470    | HaskellStyle -> pr "-}\n"
5471   );
5472   pr "\n"
5473
5474 (* Start of main code generation functions below this line. *)
5475
5476 (* Generate the pod documentation for the C API. *)
5477 let rec generate_actions_pod () =
5478   List.iter (
5479     fun (shortname, style, _, flags, _, _, longdesc) ->
5480       if not (List.mem NotInDocs flags) then (
5481         let name = "guestfs_" ^ shortname in
5482         pr "=head2 %s\n\n" name;
5483         pr " ";
5484         generate_prototype ~extern:false ~handle:"g" name style;
5485         pr "\n\n";
5486         pr "%s\n\n" longdesc;
5487         (match fst style with
5488          | RErr ->
5489              pr "This function returns 0 on success or -1 on error.\n\n"
5490          | RInt _ ->
5491              pr "On error this function returns -1.\n\n"
5492          | RInt64 _ ->
5493              pr "On error this function returns -1.\n\n"
5494          | RBool _ ->
5495              pr "This function returns a C truth value on success or -1 on error.\n\n"
5496          | RConstString _ ->
5497              pr "This function returns a string, or NULL on error.
5498 The string is owned by the guest handle and must I<not> be freed.\n\n"
5499          | RConstOptString _ ->
5500              pr "This function returns a string which may be NULL.
5501 There is way to return an error from this function.
5502 The string is owned by the guest handle and must I<not> be freed.\n\n"
5503          | RString _ ->
5504              pr "This function returns a string, or NULL on error.
5505 I<The caller must free the returned string after use>.\n\n"
5506          | RStringList _ ->
5507              pr "This function returns a NULL-terminated array of strings
5508 (like L<environ(3)>), or NULL if there was an error.
5509 I<The caller must free the strings and the array after use>.\n\n"
5510          | RStruct (_, typ) ->
5511              pr "This function returns a C<struct guestfs_%s *>,
5512 or NULL if there was an error.
5513 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5514          | RStructList (_, typ) ->
5515              pr "This function returns a C<struct guestfs_%s_list *>
5516 (see E<lt>guestfs-structs.hE<gt>),
5517 or NULL if there was an error.
5518 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5519          | RHashtable _ ->
5520              pr "This function returns a NULL-terminated array of
5521 strings, or NULL if there was an error.
5522 The array of strings will always have length C<2n+1>, where
5523 C<n> keys and values alternate, followed by the trailing NULL entry.
5524 I<The caller must free the strings and the array after use>.\n\n"
5525          | RBufferOut _ ->
5526              pr "This function returns a buffer, or NULL on error.
5527 The size of the returned buffer is written to C<*size_r>.
5528 I<The caller must free the returned buffer after use>.\n\n"
5529         );
5530         if List.mem ProtocolLimitWarning flags then
5531           pr "%s\n\n" protocol_limit_warning;
5532         if List.mem DangerWillRobinson flags then
5533           pr "%s\n\n" danger_will_robinson;
5534         match deprecation_notice flags with
5535         | None -> ()
5536         | Some txt -> pr "%s\n\n" txt
5537       )
5538   ) all_functions_sorted
5539
5540 and generate_structs_pod () =
5541   (* Structs documentation. *)
5542   List.iter (
5543     fun (typ, cols) ->
5544       pr "=head2 guestfs_%s\n" typ;
5545       pr "\n";
5546       pr " struct guestfs_%s {\n" typ;
5547       List.iter (
5548         function
5549         | name, FChar -> pr "   char %s;\n" name
5550         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5551         | name, FInt32 -> pr "   int32_t %s;\n" name
5552         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5553         | name, FInt64 -> pr "   int64_t %s;\n" name
5554         | name, FString -> pr "   char *%s;\n" name
5555         | name, FBuffer ->
5556             pr "   /* The next two fields describe a byte array. */\n";
5557             pr "   uint32_t %s_len;\n" name;
5558             pr "   char *%s;\n" name
5559         | name, FUUID ->
5560             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5561             pr "   char %s[32];\n" name
5562         | name, FOptPercent ->
5563             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5564             pr "   float %s;\n" name
5565       ) cols;
5566       pr " };\n";
5567       pr " \n";
5568       pr " struct guestfs_%s_list {\n" typ;
5569       pr "   uint32_t len; /* Number of elements in list. */\n";
5570       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5571       pr " };\n";
5572       pr " \n";
5573       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5574       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5575         typ typ;
5576       pr "\n"
5577   ) structs
5578
5579 and generate_availability_pod () =
5580   (* Availability documentation. *)
5581   pr "=over 4\n";
5582   pr "\n";
5583   List.iter (
5584     fun (group, functions) ->
5585       pr "=item B<%s>\n" group;
5586       pr "\n";
5587       pr "The following functions:\n";
5588       List.iter (pr "L</guestfs_%s>\n") functions;
5589       pr "\n"
5590   ) optgroups;
5591   pr "=back\n";
5592   pr "\n"
5593
5594 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5595  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5596  *
5597  * We have to use an underscore instead of a dash because otherwise
5598  * rpcgen generates incorrect code.
5599  *
5600  * This header is NOT exported to clients, but see also generate_structs_h.
5601  *)
5602 and generate_xdr () =
5603   generate_header CStyle LGPLv2plus;
5604
5605   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5606   pr "typedef string str<>;\n";
5607   pr "\n";
5608
5609   (* Internal structures. *)
5610   List.iter (
5611     function
5612     | typ, cols ->
5613         pr "struct guestfs_int_%s {\n" typ;
5614         List.iter (function
5615                    | name, FChar -> pr "  char %s;\n" name
5616                    | name, FString -> pr "  string %s<>;\n" name
5617                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5618                    | name, FUUID -> pr "  opaque %s[32];\n" name
5619                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5620                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5621                    | name, FOptPercent -> pr "  float %s;\n" name
5622                   ) cols;
5623         pr "};\n";
5624         pr "\n";
5625         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5626         pr "\n";
5627   ) structs;
5628
5629   List.iter (
5630     fun (shortname, style, _, _, _, _, _) ->
5631       let name = "guestfs_" ^ shortname in
5632
5633       (match snd style with
5634        | [] -> ()
5635        | args ->
5636            pr "struct %s_args {\n" name;
5637            List.iter (
5638              function
5639              | Pathname n | Device n | Dev_or_Path n | String n ->
5640                  pr "  string %s<>;\n" n
5641              | OptString n -> pr "  str *%s;\n" n
5642              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5643              | Bool n -> pr "  bool %s;\n" n
5644              | Int n -> pr "  int %s;\n" n
5645              | Int64 n -> pr "  hyper %s;\n" n
5646              | BufferIn n ->
5647                  pr "  opaque %s<>;\n" n
5648              | FileIn _ | FileOut _ -> ()
5649            ) args;
5650            pr "};\n\n"
5651       );
5652       (match fst style with
5653        | RErr -> ()
5654        | RInt n ->
5655            pr "struct %s_ret {\n" name;
5656            pr "  int %s;\n" n;
5657            pr "};\n\n"
5658        | RInt64 n ->
5659            pr "struct %s_ret {\n" name;
5660            pr "  hyper %s;\n" n;
5661            pr "};\n\n"
5662        | RBool n ->
5663            pr "struct %s_ret {\n" name;
5664            pr "  bool %s;\n" n;
5665            pr "};\n\n"
5666        | RConstString _ | RConstOptString _ ->
5667            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5668        | RString n ->
5669            pr "struct %s_ret {\n" name;
5670            pr "  string %s<>;\n" n;
5671            pr "};\n\n"
5672        | RStringList n ->
5673            pr "struct %s_ret {\n" name;
5674            pr "  str %s<>;\n" n;
5675            pr "};\n\n"
5676        | RStruct (n, typ) ->
5677            pr "struct %s_ret {\n" name;
5678            pr "  guestfs_int_%s %s;\n" typ n;
5679            pr "};\n\n"
5680        | RStructList (n, typ) ->
5681            pr "struct %s_ret {\n" name;
5682            pr "  guestfs_int_%s_list %s;\n" typ n;
5683            pr "};\n\n"
5684        | RHashtable n ->
5685            pr "struct %s_ret {\n" name;
5686            pr "  str %s<>;\n" n;
5687            pr "};\n\n"
5688        | RBufferOut n ->
5689            pr "struct %s_ret {\n" name;
5690            pr "  opaque %s<>;\n" n;
5691            pr "};\n\n"
5692       );
5693   ) daemon_functions;
5694
5695   (* Table of procedure numbers. *)
5696   pr "enum guestfs_procedure {\n";
5697   List.iter (
5698     fun (shortname, _, proc_nr, _, _, _, _) ->
5699       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5700   ) daemon_functions;
5701   pr "  GUESTFS_PROC_NR_PROCS\n";
5702   pr "};\n";
5703   pr "\n";
5704
5705   (* Having to choose a maximum message size is annoying for several
5706    * reasons (it limits what we can do in the API), but it (a) makes
5707    * the protocol a lot simpler, and (b) provides a bound on the size
5708    * of the daemon which operates in limited memory space.
5709    *)
5710   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5711   pr "\n";
5712
5713   (* Message header, etc. *)
5714   pr "\
5715 /* The communication protocol is now documented in the guestfs(3)
5716  * manpage.
5717  */
5718
5719 const GUESTFS_PROGRAM = 0x2000F5F5;
5720 const GUESTFS_PROTOCOL_VERSION = 1;
5721
5722 /* These constants must be larger than any possible message length. */
5723 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5724 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5725
5726 enum guestfs_message_direction {
5727   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5728   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5729 };
5730
5731 enum guestfs_message_status {
5732   GUESTFS_STATUS_OK = 0,
5733   GUESTFS_STATUS_ERROR = 1
5734 };
5735
5736 const GUESTFS_ERROR_LEN = 256;
5737
5738 struct guestfs_message_error {
5739   string error_message<GUESTFS_ERROR_LEN>;
5740 };
5741
5742 struct guestfs_message_header {
5743   unsigned prog;                     /* GUESTFS_PROGRAM */
5744   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5745   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5746   guestfs_message_direction direction;
5747   unsigned serial;                   /* message serial number */
5748   guestfs_message_status status;
5749 };
5750
5751 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5752
5753 struct guestfs_chunk {
5754   int cancel;                        /* if non-zero, transfer is cancelled */
5755   /* data size is 0 bytes if the transfer has finished successfully */
5756   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5757 };
5758 "
5759
5760 (* Generate the guestfs-structs.h file. *)
5761 and generate_structs_h () =
5762   generate_header CStyle LGPLv2plus;
5763
5764   (* This is a public exported header file containing various
5765    * structures.  The structures are carefully written to have
5766    * exactly the same in-memory format as the XDR structures that
5767    * we use on the wire to the daemon.  The reason for creating
5768    * copies of these structures here is just so we don't have to
5769    * export the whole of guestfs_protocol.h (which includes much
5770    * unrelated and XDR-dependent stuff that we don't want to be
5771    * public, or required by clients).
5772    *
5773    * To reiterate, we will pass these structures to and from the
5774    * client with a simple assignment or memcpy, so the format
5775    * must be identical to what rpcgen / the RFC defines.
5776    *)
5777
5778   (* Public structures. *)
5779   List.iter (
5780     fun (typ, cols) ->
5781       pr "struct guestfs_%s {\n" typ;
5782       List.iter (
5783         function
5784         | name, FChar -> pr "  char %s;\n" name
5785         | name, FString -> pr "  char *%s;\n" name
5786         | name, FBuffer ->
5787             pr "  uint32_t %s_len;\n" name;
5788             pr "  char *%s;\n" name
5789         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5790         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5791         | name, FInt32 -> pr "  int32_t %s;\n" name
5792         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5793         | name, FInt64 -> pr "  int64_t %s;\n" name
5794         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5795       ) cols;
5796       pr "};\n";
5797       pr "\n";
5798       pr "struct guestfs_%s_list {\n" typ;
5799       pr "  uint32_t len;\n";
5800       pr "  struct guestfs_%s *val;\n" typ;
5801       pr "};\n";
5802       pr "\n";
5803       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5804       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5805       pr "\n"
5806   ) structs
5807
5808 (* Generate the guestfs-actions.h file. *)
5809 and generate_actions_h () =
5810   generate_header CStyle LGPLv2plus;
5811   List.iter (
5812     fun (shortname, style, _, _, _, _, _) ->
5813       let name = "guestfs_" ^ shortname in
5814       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5815         name style
5816   ) all_functions
5817
5818 (* Generate the guestfs-internal-actions.h file. *)
5819 and generate_internal_actions_h () =
5820   generate_header CStyle LGPLv2plus;
5821   List.iter (
5822     fun (shortname, style, _, _, _, _, _) ->
5823       let name = "guestfs__" ^ shortname in
5824       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5825         name style
5826   ) non_daemon_functions
5827
5828 (* Generate the client-side dispatch stubs. *)
5829 and generate_client_actions () =
5830   generate_header CStyle LGPLv2plus;
5831
5832   pr "\
5833 #include <stdio.h>
5834 #include <stdlib.h>
5835 #include <stdint.h>
5836 #include <string.h>
5837 #include <inttypes.h>
5838
5839 #include \"guestfs.h\"
5840 #include \"guestfs-internal.h\"
5841 #include \"guestfs-internal-actions.h\"
5842 #include \"guestfs_protocol.h\"
5843
5844 #define error guestfs_error
5845 //#define perrorf guestfs_perrorf
5846 #define safe_malloc guestfs_safe_malloc
5847 #define safe_realloc guestfs_safe_realloc
5848 //#define safe_strdup guestfs_safe_strdup
5849 #define safe_memdup guestfs_safe_memdup
5850
5851 /* Check the return message from a call for validity. */
5852 static int
5853 check_reply_header (guestfs_h *g,
5854                     const struct guestfs_message_header *hdr,
5855                     unsigned int proc_nr, unsigned int serial)
5856 {
5857   if (hdr->prog != GUESTFS_PROGRAM) {
5858     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5859     return -1;
5860   }
5861   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5862     error (g, \"wrong protocol version (%%d/%%d)\",
5863            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5864     return -1;
5865   }
5866   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5867     error (g, \"unexpected message direction (%%d/%%d)\",
5868            hdr->direction, GUESTFS_DIRECTION_REPLY);
5869     return -1;
5870   }
5871   if (hdr->proc != proc_nr) {
5872     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5873     return -1;
5874   }
5875   if (hdr->serial != serial) {
5876     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5877     return -1;
5878   }
5879
5880   return 0;
5881 }
5882
5883 /* Check we are in the right state to run a high-level action. */
5884 static int
5885 check_state (guestfs_h *g, const char *caller)
5886 {
5887   if (!guestfs__is_ready (g)) {
5888     if (guestfs__is_config (g) || guestfs__is_launching (g))
5889       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5890         caller);
5891     else
5892       error (g, \"%%s called from the wrong state, %%d != READY\",
5893         caller, guestfs__get_state (g));
5894     return -1;
5895   }
5896   return 0;
5897 }
5898
5899 ";
5900
5901   let error_code_of = function
5902     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5903     | RConstString _ | RConstOptString _
5904     | RString _ | RStringList _
5905     | RStruct _ | RStructList _
5906     | RHashtable _ | RBufferOut _ -> "NULL"
5907   in
5908
5909   (* Generate code to check String-like parameters are not passed in
5910    * as NULL (returning an error if they are).
5911    *)
5912   let check_null_strings shortname style =
5913     let pr_newline = ref false in
5914     List.iter (
5915       function
5916       (* parameters which should not be NULL *)
5917       | String n
5918       | Device n
5919       | Pathname n
5920       | Dev_or_Path n
5921       | FileIn n
5922       | FileOut n
5923       | BufferIn n
5924       | StringList n
5925       | DeviceList n ->
5926           pr "  if (%s == NULL) {\n" n;
5927           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5928           pr "           \"%s\", \"%s\");\n" shortname n;
5929           pr "    return %s;\n" (error_code_of (fst style));
5930           pr "  }\n";
5931           pr_newline := true
5932
5933       (* can be NULL *)
5934       | OptString _
5935
5936       (* not applicable *)
5937       | Bool _
5938       | Int _
5939       | Int64 _ -> ()
5940     ) (snd style);
5941
5942     if !pr_newline then pr "\n";
5943   in
5944
5945   (* Generate code to generate guestfish call traces. *)
5946   let trace_call shortname style =
5947     pr "  if (guestfs__get_trace (g)) {\n";
5948
5949     let needs_i =
5950       List.exists (function
5951                    | StringList _ | DeviceList _ -> true
5952                    | _ -> false) (snd style) in
5953     if needs_i then (
5954       pr "    int i;\n";
5955       pr "\n"
5956     );
5957
5958     pr "    printf (\"%s\");\n" shortname;
5959     List.iter (
5960       function
5961       | String n                        (* strings *)
5962       | Device n
5963       | Pathname n
5964       | Dev_or_Path n
5965       | FileIn n
5966       | FileOut n
5967       | BufferIn n ->
5968           (* guestfish doesn't support string escaping, so neither do we *)
5969           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5970       | OptString n ->                  (* string option *)
5971           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5972           pr "    else printf (\" null\");\n"
5973       | StringList n
5974       | DeviceList n ->                 (* string list *)
5975           pr "    putchar (' ');\n";
5976           pr "    putchar ('\"');\n";
5977           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5978           pr "      if (i > 0) putchar (' ');\n";
5979           pr "      fputs (%s[i], stdout);\n" n;
5980           pr "    }\n";
5981           pr "    putchar ('\"');\n";
5982       | Bool n ->                       (* boolean *)
5983           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5984       | Int n ->                        (* int *)
5985           pr "    printf (\" %%d\", %s);\n" n
5986       | Int64 n ->
5987           pr "    printf (\" %%\" PRIi64, %s);\n" n
5988     ) (snd style);
5989     pr "    putchar ('\\n');\n";
5990     pr "  }\n";
5991     pr "\n";
5992   in
5993
5994   (* For non-daemon functions, generate a wrapper around each function. *)
5995   List.iter (
5996     fun (shortname, style, _, _, _, _, _) ->
5997       let name = "guestfs_" ^ shortname in
5998
5999       generate_prototype ~extern:false ~semicolon:false ~newline:true
6000         ~handle:"g" name style;
6001       pr "{\n";
6002       check_null_strings shortname style;
6003       trace_call shortname style;
6004       pr "  return guestfs__%s " shortname;
6005       generate_c_call_args ~handle:"g" style;
6006       pr ";\n";
6007       pr "}\n";
6008       pr "\n"
6009   ) non_daemon_functions;
6010
6011   (* Client-side stubs for each function. *)
6012   List.iter (
6013     fun (shortname, style, _, _, _, _, _) ->
6014       let name = "guestfs_" ^ shortname in
6015       let error_code = error_code_of (fst style) in
6016
6017       (* Generate the action stub. *)
6018       generate_prototype ~extern:false ~semicolon:false ~newline:true
6019         ~handle:"g" name style;
6020
6021       pr "{\n";
6022
6023       (match snd style with
6024        | [] -> ()
6025        | _ -> pr "  struct %s_args args;\n" name
6026       );
6027
6028       pr "  guestfs_message_header hdr;\n";
6029       pr "  guestfs_message_error err;\n";
6030       let has_ret =
6031         match fst style with
6032         | RErr -> false
6033         | RConstString _ | RConstOptString _ ->
6034             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6035         | RInt _ | RInt64 _
6036         | RBool _ | RString _ | RStringList _
6037         | RStruct _ | RStructList _
6038         | RHashtable _ | RBufferOut _ ->
6039             pr "  struct %s_ret ret;\n" name;
6040             true in
6041
6042       pr "  int serial;\n";
6043       pr "  int r;\n";
6044       pr "\n";
6045       check_null_strings shortname style;
6046       trace_call shortname style;
6047       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6048         shortname error_code;
6049       pr "  guestfs___set_busy (g);\n";
6050       pr "\n";
6051
6052       (* Send the main header and arguments. *)
6053       (match snd style with
6054        | [] ->
6055            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6056              (String.uppercase shortname)
6057        | args ->
6058            List.iter (
6059              function
6060              | Pathname n | Device n | Dev_or_Path n | String n ->
6061                  pr "  args.%s = (char *) %s;\n" n n
6062              | OptString n ->
6063                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6064              | StringList n | DeviceList n ->
6065                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6066                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6067              | Bool n ->
6068                  pr "  args.%s = %s;\n" n n
6069              | Int n ->
6070                  pr "  args.%s = %s;\n" n n
6071              | Int64 n ->
6072                  pr "  args.%s = %s;\n" n n
6073              | FileIn _ | FileOut _ -> ()
6074              | BufferIn n ->
6075                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6076                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6077                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6078                    shortname;
6079                  pr "    guestfs___end_busy (g);\n";
6080                  pr "    return %s;\n" error_code;
6081                  pr "  }\n";
6082                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6083                  pr "  args.%s.%s_len = %s_size;\n" n n n
6084            ) args;
6085            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6086              (String.uppercase shortname);
6087            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6088              name;
6089       );
6090       pr "  if (serial == -1) {\n";
6091       pr "    guestfs___end_busy (g);\n";
6092       pr "    return %s;\n" error_code;
6093       pr "  }\n";
6094       pr "\n";
6095
6096       (* Send any additional files (FileIn) requested. *)
6097       let need_read_reply_label = ref false in
6098       List.iter (
6099         function
6100         | FileIn n ->
6101             pr "  r = guestfs___send_file (g, %s);\n" n;
6102             pr "  if (r == -1) {\n";
6103             pr "    guestfs___end_busy (g);\n";
6104             pr "    return %s;\n" error_code;
6105             pr "  }\n";
6106             pr "  if (r == -2) /* daemon cancelled */\n";
6107             pr "    goto read_reply;\n";
6108             need_read_reply_label := true;
6109             pr "\n";
6110         | _ -> ()
6111       ) (snd style);
6112
6113       (* Wait for the reply from the remote end. *)
6114       if !need_read_reply_label then pr " read_reply:\n";
6115       pr "  memset (&hdr, 0, sizeof hdr);\n";
6116       pr "  memset (&err, 0, sizeof err);\n";
6117       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6118       pr "\n";
6119       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6120       if not has_ret then
6121         pr "NULL, NULL"
6122       else
6123         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6124       pr ");\n";
6125
6126       pr "  if (r == -1) {\n";
6127       pr "    guestfs___end_busy (g);\n";
6128       pr "    return %s;\n" error_code;
6129       pr "  }\n";
6130       pr "\n";
6131
6132       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6133         (String.uppercase shortname);
6134       pr "    guestfs___end_busy (g);\n";
6135       pr "    return %s;\n" error_code;
6136       pr "  }\n";
6137       pr "\n";
6138
6139       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6140       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6141       pr "    free (err.error_message);\n";
6142       pr "    guestfs___end_busy (g);\n";
6143       pr "    return %s;\n" error_code;
6144       pr "  }\n";
6145       pr "\n";
6146
6147       (* Expecting to receive further files (FileOut)? *)
6148       List.iter (
6149         function
6150         | FileOut n ->
6151             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6152             pr "    guestfs___end_busy (g);\n";
6153             pr "    return %s;\n" error_code;
6154             pr "  }\n";
6155             pr "\n";
6156         | _ -> ()
6157       ) (snd style);
6158
6159       pr "  guestfs___end_busy (g);\n";
6160
6161       (match fst style with
6162        | RErr -> pr "  return 0;\n"
6163        | RInt n | RInt64 n | RBool n ->
6164            pr "  return ret.%s;\n" n
6165        | RConstString _ | RConstOptString _ ->
6166            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6167        | RString n ->
6168            pr "  return ret.%s; /* caller will free */\n" n
6169        | RStringList n | RHashtable n ->
6170            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6171            pr "  ret.%s.%s_val =\n" n n;
6172            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6173            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6174              n n;
6175            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6176            pr "  return ret.%s.%s_val;\n" n n
6177        | RStruct (n, _) ->
6178            pr "  /* caller will free this */\n";
6179            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6180        | RStructList (n, _) ->
6181            pr "  /* caller will free this */\n";
6182            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6183        | RBufferOut n ->
6184            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6185            pr "   * _val might be NULL here.  To make the API saner for\n";
6186            pr "   * callers, we turn this case into a unique pointer (using\n";
6187            pr "   * malloc(1)).\n";
6188            pr "   */\n";
6189            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6190            pr "    *size_r = ret.%s.%s_len;\n" n n;
6191            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6192            pr "  } else {\n";
6193            pr "    free (ret.%s.%s_val);\n" n n;
6194            pr "    char *p = safe_malloc (g, 1);\n";
6195            pr "    *size_r = ret.%s.%s_len;\n" n n;
6196            pr "    return p;\n";
6197            pr "  }\n";
6198       );
6199
6200       pr "}\n\n"
6201   ) daemon_functions;
6202
6203   (* Functions to free structures. *)
6204   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6205   pr " * structure format is identical to the XDR format.  See note in\n";
6206   pr " * generator.ml.\n";
6207   pr " */\n";
6208   pr "\n";
6209
6210   List.iter (
6211     fun (typ, _) ->
6212       pr "void\n";
6213       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6214       pr "{\n";
6215       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6216       pr "  free (x);\n";
6217       pr "}\n";
6218       pr "\n";
6219
6220       pr "void\n";
6221       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6222       pr "{\n";
6223       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6224       pr "  free (x);\n";
6225       pr "}\n";
6226       pr "\n";
6227
6228   ) structs;
6229
6230 (* Generate daemon/actions.h. *)
6231 and generate_daemon_actions_h () =
6232   generate_header CStyle GPLv2plus;
6233
6234   pr "#include \"../src/guestfs_protocol.h\"\n";
6235   pr "\n";
6236
6237   List.iter (
6238     fun (name, style, _, _, _, _, _) ->
6239       generate_prototype
6240         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6241         name style;
6242   ) daemon_functions
6243
6244 (* Generate the linker script which controls the visibility of
6245  * symbols in the public ABI and ensures no other symbols get
6246  * exported accidentally.
6247  *)
6248 and generate_linker_script () =
6249   generate_header HashStyle GPLv2plus;
6250
6251   let globals = [
6252     "guestfs_create";
6253     "guestfs_close";
6254     "guestfs_get_error_handler";
6255     "guestfs_get_out_of_memory_handler";
6256     "guestfs_last_error";
6257     "guestfs_set_error_handler";
6258     "guestfs_set_launch_done_callback";
6259     "guestfs_set_log_message_callback";
6260     "guestfs_set_out_of_memory_handler";
6261     "guestfs_set_subprocess_quit_callback";
6262
6263     (* Unofficial parts of the API: the bindings code use these
6264      * functions, so it is useful to export them.
6265      *)
6266     "guestfs_safe_calloc";
6267     "guestfs_safe_malloc";
6268   ] in
6269   let functions =
6270     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6271       all_functions in
6272   let structs =
6273     List.concat (
6274       List.map (fun (typ, _) ->
6275                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6276         structs
6277     ) in
6278   let globals = List.sort compare (globals @ functions @ structs) in
6279
6280   pr "{\n";
6281   pr "    global:\n";
6282   List.iter (pr "        %s;\n") globals;
6283   pr "\n";
6284
6285   pr "    local:\n";
6286   pr "        *;\n";
6287   pr "};\n"
6288
6289 (* Generate the server-side stubs. *)
6290 and generate_daemon_actions () =
6291   generate_header CStyle GPLv2plus;
6292
6293   pr "#include <config.h>\n";
6294   pr "\n";
6295   pr "#include <stdio.h>\n";
6296   pr "#include <stdlib.h>\n";
6297   pr "#include <string.h>\n";
6298   pr "#include <inttypes.h>\n";
6299   pr "#include <rpc/types.h>\n";
6300   pr "#include <rpc/xdr.h>\n";
6301   pr "\n";
6302   pr "#include \"daemon.h\"\n";
6303   pr "#include \"c-ctype.h\"\n";
6304   pr "#include \"../src/guestfs_protocol.h\"\n";
6305   pr "#include \"actions.h\"\n";
6306   pr "\n";
6307
6308   List.iter (
6309     fun (name, style, _, _, _, _, _) ->
6310       (* Generate server-side stubs. *)
6311       pr "static void %s_stub (XDR *xdr_in)\n" name;
6312       pr "{\n";
6313       let error_code =
6314         match fst style with
6315         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6316         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6317         | RBool _ -> pr "  int r;\n"; "-1"
6318         | RConstString _ | RConstOptString _ ->
6319             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6320         | RString _ -> pr "  char *r;\n"; "NULL"
6321         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6322         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6323         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6324         | RBufferOut _ ->
6325             pr "  size_t size = 1;\n";
6326             pr "  char *r;\n";
6327             "NULL" in
6328
6329       (match snd style with
6330        | [] -> ()
6331        | args ->
6332            pr "  struct guestfs_%s_args args;\n" name;
6333            List.iter (
6334              function
6335              | Device n | Dev_or_Path n
6336              | Pathname n
6337              | String n -> ()
6338              | OptString n -> pr "  char *%s;\n" n
6339              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6340              | Bool n -> pr "  int %s;\n" n
6341              | Int n -> pr "  int %s;\n" n
6342              | Int64 n -> pr "  int64_t %s;\n" n
6343              | FileIn _ | FileOut _ -> ()
6344              | BufferIn n ->
6345                  pr "  const char *%s;\n" n;
6346                  pr "  size_t %s_size;\n" n
6347            ) args
6348       );
6349       pr "\n";
6350
6351       let is_filein =
6352         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6353
6354       (match snd style with
6355        | [] -> ()
6356        | args ->
6357            pr "  memset (&args, 0, sizeof args);\n";
6358            pr "\n";
6359            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6360            if is_filein then
6361              pr "    if (cancel_receive () != -2)\n";
6362            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6363            pr "    goto done;\n";
6364            pr "  }\n";
6365            let pr_args n =
6366              pr "  char *%s = args.%s;\n" n n
6367            in
6368            let pr_list_handling_code n =
6369              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6370              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6371              pr "  if (%s == NULL) {\n" n;
6372              if is_filein then
6373                pr "    if (cancel_receive () != -2)\n";
6374              pr "      reply_with_perror (\"realloc\");\n";
6375              pr "    goto done;\n";
6376              pr "  }\n";
6377              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6378              pr "  args.%s.%s_val = %s;\n" n n n;
6379            in
6380            List.iter (
6381              function
6382              | Pathname n ->
6383                  pr_args n;
6384                  pr "  ABS_PATH (%s, %s, goto done);\n"
6385                    n (if is_filein then "cancel_receive ()" else "0");
6386              | Device n ->
6387                  pr_args n;
6388                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6389                    n (if is_filein then "cancel_receive ()" else "0");
6390              | Dev_or_Path n ->
6391                  pr_args n;
6392                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6393                    n (if is_filein then "cancel_receive ()" else "0");
6394              | String n -> pr_args n
6395              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6396              | StringList n ->
6397                  pr_list_handling_code n;
6398              | DeviceList n ->
6399                  pr_list_handling_code n;
6400                  pr "  /* Ensure that each is a device,\n";
6401                  pr "   * and perform device name translation. */\n";
6402                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6403                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6404                    (if is_filein then "cancel_receive ()" else "0");
6405                  pr "  }\n";
6406              | Bool n -> pr "  %s = args.%s;\n" n n
6407              | Int n -> pr "  %s = args.%s;\n" n n
6408              | Int64 n -> pr "  %s = args.%s;\n" n n
6409              | FileIn _ | FileOut _ -> ()
6410              | BufferIn n ->
6411                  pr "  %s = args.%s.%s_val;\n" n n n;
6412                  pr "  %s_size = args.%s.%s_len;\n" n n n
6413            ) args;
6414            pr "\n"
6415       );
6416
6417       (* this is used at least for do_equal *)
6418       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6419         (* Emit NEED_ROOT just once, even when there are two or
6420            more Pathname args *)
6421         pr "  NEED_ROOT (%s, goto done);\n"
6422           (if is_filein then "cancel_receive ()" else "0");
6423       );
6424
6425       (* Don't want to call the impl with any FileIn or FileOut
6426        * parameters, since these go "outside" the RPC protocol.
6427        *)
6428       let args' =
6429         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6430           (snd style) in
6431       pr "  r = do_%s " name;
6432       generate_c_call_args (fst style, args');
6433       pr ";\n";
6434
6435       (match fst style with
6436        | RErr | RInt _ | RInt64 _ | RBool _
6437        | RConstString _ | RConstOptString _
6438        | RString _ | RStringList _ | RHashtable _
6439        | RStruct (_, _) | RStructList (_, _) ->
6440            pr "  if (r == %s)\n" error_code;
6441            pr "    /* do_%s has already called reply_with_error */\n" name;
6442            pr "    goto done;\n";
6443            pr "\n"
6444        | RBufferOut _ ->
6445            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6446            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6447            pr "   */\n";
6448            pr "  if (size == 1 && r == %s)\n" error_code;
6449            pr "    /* do_%s has already called reply_with_error */\n" name;
6450            pr "    goto done;\n";
6451            pr "\n"
6452       );
6453
6454       (* If there are any FileOut parameters, then the impl must
6455        * send its own reply.
6456        *)
6457       let no_reply =
6458         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6459       if no_reply then
6460         pr "  /* do_%s has already sent a reply */\n" name
6461       else (
6462         match fst style with
6463         | RErr -> pr "  reply (NULL, NULL);\n"
6464         | RInt n | RInt64 n | RBool n ->
6465             pr "  struct guestfs_%s_ret ret;\n" name;
6466             pr "  ret.%s = r;\n" n;
6467             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6468               name
6469         | RConstString _ | RConstOptString _ ->
6470             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6471         | RString n ->
6472             pr "  struct guestfs_%s_ret ret;\n" name;
6473             pr "  ret.%s = r;\n" n;
6474             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6475               name;
6476             pr "  free (r);\n"
6477         | RStringList n | RHashtable n ->
6478             pr "  struct guestfs_%s_ret ret;\n" name;
6479             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6480             pr "  ret.%s.%s_val = r;\n" n n;
6481             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6482               name;
6483             pr "  free_strings (r);\n"
6484         | RStruct (n, _) ->
6485             pr "  struct guestfs_%s_ret ret;\n" name;
6486             pr "  ret.%s = *r;\n" n;
6487             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6488               name;
6489             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6490               name
6491         | RStructList (n, _) ->
6492             pr "  struct guestfs_%s_ret ret;\n" name;
6493             pr "  ret.%s = *r;\n" n;
6494             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6495               name;
6496             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6497               name
6498         | RBufferOut n ->
6499             pr "  struct guestfs_%s_ret ret;\n" name;
6500             pr "  ret.%s.%s_val = r;\n" n n;
6501             pr "  ret.%s.%s_len = size;\n" n n;
6502             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6503               name;
6504             pr "  free (r);\n"
6505       );
6506
6507       (* Free the args. *)
6508       pr "done:\n";
6509       (match snd style with
6510        | [] -> ()
6511        | _ ->
6512            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6513              name
6514       );
6515       pr "  return;\n";
6516       pr "}\n\n";
6517   ) daemon_functions;
6518
6519   (* Dispatch function. *)
6520   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6521   pr "{\n";
6522   pr "  switch (proc_nr) {\n";
6523
6524   List.iter (
6525     fun (name, style, _, _, _, _, _) ->
6526       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6527       pr "      %s_stub (xdr_in);\n" name;
6528       pr "      break;\n"
6529   ) daemon_functions;
6530
6531   pr "    default:\n";
6532   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";
6533   pr "  }\n";
6534   pr "}\n";
6535   pr "\n";
6536
6537   (* LVM columns and tokenization functions. *)
6538   (* XXX This generates crap code.  We should rethink how we
6539    * do this parsing.
6540    *)
6541   List.iter (
6542     function
6543     | typ, cols ->
6544         pr "static const char *lvm_%s_cols = \"%s\";\n"
6545           typ (String.concat "," (List.map fst cols));
6546         pr "\n";
6547
6548         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6549         pr "{\n";
6550         pr "  char *tok, *p, *next;\n";
6551         pr "  int i, j;\n";
6552         pr "\n";
6553         (*
6554           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6555           pr "\n";
6556         *)
6557         pr "  if (!str) {\n";
6558         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6559         pr "    return -1;\n";
6560         pr "  }\n";
6561         pr "  if (!*str || c_isspace (*str)) {\n";
6562         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6563         pr "    return -1;\n";
6564         pr "  }\n";
6565         pr "  tok = str;\n";
6566         List.iter (
6567           fun (name, coltype) ->
6568             pr "  if (!tok) {\n";
6569             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6570             pr "    return -1;\n";
6571             pr "  }\n";
6572             pr "  p = strchrnul (tok, ',');\n";
6573             pr "  if (*p) next = p+1; else next = NULL;\n";
6574             pr "  *p = '\\0';\n";
6575             (match coltype with
6576              | FString ->
6577                  pr "  r->%s = strdup (tok);\n" name;
6578                  pr "  if (r->%s == NULL) {\n" name;
6579                  pr "    perror (\"strdup\");\n";
6580                  pr "    return -1;\n";
6581                  pr "  }\n"
6582              | FUUID ->
6583                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6584                  pr "    if (tok[j] == '\\0') {\n";
6585                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6586                  pr "      return -1;\n";
6587                  pr "    } else if (tok[j] != '-')\n";
6588                  pr "      r->%s[i++] = tok[j];\n" name;
6589                  pr "  }\n";
6590              | FBytes ->
6591                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6592                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6593                  pr "    return -1;\n";
6594                  pr "  }\n";
6595              | FInt64 ->
6596                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6597                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6598                  pr "    return -1;\n";
6599                  pr "  }\n";
6600              | FOptPercent ->
6601                  pr "  if (tok[0] == '\\0')\n";
6602                  pr "    r->%s = -1;\n" name;
6603                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6604                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6605                  pr "    return -1;\n";
6606                  pr "  }\n";
6607              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6608                  assert false (* can never be an LVM column *)
6609             );
6610             pr "  tok = next;\n";
6611         ) cols;
6612
6613         pr "  if (tok != NULL) {\n";
6614         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6615         pr "    return -1;\n";
6616         pr "  }\n";
6617         pr "  return 0;\n";
6618         pr "}\n";
6619         pr "\n";
6620
6621         pr "guestfs_int_lvm_%s_list *\n" typ;
6622         pr "parse_command_line_%ss (void)\n" typ;
6623         pr "{\n";
6624         pr "  char *out, *err;\n";
6625         pr "  char *p, *pend;\n";
6626         pr "  int r, i;\n";
6627         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6628         pr "  void *newp;\n";
6629         pr "\n";
6630         pr "  ret = malloc (sizeof *ret);\n";
6631         pr "  if (!ret) {\n";
6632         pr "    reply_with_perror (\"malloc\");\n";
6633         pr "    return NULL;\n";
6634         pr "  }\n";
6635         pr "\n";
6636         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6637         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6638         pr "\n";
6639         pr "  r = command (&out, &err,\n";
6640         pr "           \"lvm\", \"%ss\",\n" typ;
6641         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6642         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6643         pr "  if (r == -1) {\n";
6644         pr "    reply_with_error (\"%%s\", err);\n";
6645         pr "    free (out);\n";
6646         pr "    free (err);\n";
6647         pr "    free (ret);\n";
6648         pr "    return NULL;\n";
6649         pr "  }\n";
6650         pr "\n";
6651         pr "  free (err);\n";
6652         pr "\n";
6653         pr "  /* Tokenize each line of the output. */\n";
6654         pr "  p = out;\n";
6655         pr "  i = 0;\n";
6656         pr "  while (p) {\n";
6657         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6658         pr "    if (pend) {\n";
6659         pr "      *pend = '\\0';\n";
6660         pr "      pend++;\n";
6661         pr "    }\n";
6662         pr "\n";
6663         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6664         pr "      p++;\n";
6665         pr "\n";
6666         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6667         pr "      p = pend;\n";
6668         pr "      continue;\n";
6669         pr "    }\n";
6670         pr "\n";
6671         pr "    /* Allocate some space to store this next entry. */\n";
6672         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6673         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6674         pr "    if (newp == NULL) {\n";
6675         pr "      reply_with_perror (\"realloc\");\n";
6676         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6677         pr "      free (ret);\n";
6678         pr "      free (out);\n";
6679         pr "      return NULL;\n";
6680         pr "    }\n";
6681         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6682         pr "\n";
6683         pr "    /* Tokenize the next entry. */\n";
6684         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6685         pr "    if (r == -1) {\n";
6686         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6687         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6688         pr "      free (ret);\n";
6689         pr "      free (out);\n";
6690         pr "      return NULL;\n";
6691         pr "    }\n";
6692         pr "\n";
6693         pr "    ++i;\n";
6694         pr "    p = pend;\n";
6695         pr "  }\n";
6696         pr "\n";
6697         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6698         pr "\n";
6699         pr "  free (out);\n";
6700         pr "  return ret;\n";
6701         pr "}\n"
6702
6703   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6704
6705 (* Generate a list of function names, for debugging in the daemon.. *)
6706 and generate_daemon_names () =
6707   generate_header CStyle GPLv2plus;
6708
6709   pr "#include <config.h>\n";
6710   pr "\n";
6711   pr "#include \"daemon.h\"\n";
6712   pr "\n";
6713
6714   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6715   pr "const char *function_names[] = {\n";
6716   List.iter (
6717     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6718   ) daemon_functions;
6719   pr "};\n";
6720
6721 (* Generate the optional groups for the daemon to implement
6722  * guestfs_available.
6723  *)
6724 and generate_daemon_optgroups_c () =
6725   generate_header CStyle GPLv2plus;
6726
6727   pr "#include <config.h>\n";
6728   pr "\n";
6729   pr "#include \"daemon.h\"\n";
6730   pr "#include \"optgroups.h\"\n";
6731   pr "\n";
6732
6733   pr "struct optgroup optgroups[] = {\n";
6734   List.iter (
6735     fun (group, _) ->
6736       pr "  { \"%s\", optgroup_%s_available },\n" group group
6737   ) optgroups;
6738   pr "  { NULL, NULL }\n";
6739   pr "};\n"
6740
6741 and generate_daemon_optgroups_h () =
6742   generate_header CStyle GPLv2plus;
6743
6744   List.iter (
6745     fun (group, _) ->
6746       pr "extern int optgroup_%s_available (void);\n" group
6747   ) optgroups
6748
6749 (* Generate the tests. *)
6750 and generate_tests () =
6751   generate_header CStyle GPLv2plus;
6752
6753   pr "\
6754 #include <stdio.h>
6755 #include <stdlib.h>
6756 #include <string.h>
6757 #include <unistd.h>
6758 #include <sys/types.h>
6759 #include <fcntl.h>
6760
6761 #include \"guestfs.h\"
6762 #include \"guestfs-internal.h\"
6763
6764 static guestfs_h *g;
6765 static int suppress_error = 0;
6766
6767 static void print_error (guestfs_h *g, void *data, const char *msg)
6768 {
6769   if (!suppress_error)
6770     fprintf (stderr, \"%%s\\n\", msg);
6771 }
6772
6773 /* FIXME: nearly identical code appears in fish.c */
6774 static void print_strings (char *const *argv)
6775 {
6776   int argc;
6777
6778   for (argc = 0; argv[argc] != NULL; ++argc)
6779     printf (\"\\t%%s\\n\", argv[argc]);
6780 }
6781
6782 /*
6783 static void print_table (char const *const *argv)
6784 {
6785   int i;
6786
6787   for (i = 0; argv[i] != NULL; i += 2)
6788     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6789 }
6790 */
6791
6792 ";
6793
6794   (* Generate a list of commands which are not tested anywhere. *)
6795   pr "static void no_test_warnings (void)\n";
6796   pr "{\n";
6797
6798   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6799   List.iter (
6800     fun (_, _, _, _, tests, _, _) ->
6801       let tests = filter_map (
6802         function
6803         | (_, (Always|If _|Unless _), test) -> Some test
6804         | (_, Disabled, _) -> None
6805       ) tests in
6806       let seq = List.concat (List.map seq_of_test tests) in
6807       let cmds_tested = List.map List.hd seq in
6808       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6809   ) all_functions;
6810
6811   List.iter (
6812     fun (name, _, _, _, _, _, _) ->
6813       if not (Hashtbl.mem hash name) then
6814         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6815   ) all_functions;
6816
6817   pr "}\n";
6818   pr "\n";
6819
6820   (* Generate the actual tests.  Note that we generate the tests
6821    * in reverse order, deliberately, so that (in general) the
6822    * newest tests run first.  This makes it quicker and easier to
6823    * debug them.
6824    *)
6825   let test_names =
6826     List.map (
6827       fun (name, _, _, flags, tests, _, _) ->
6828         mapi (generate_one_test name flags) tests
6829     ) (List.rev all_functions) in
6830   let test_names = List.concat test_names in
6831   let nr_tests = List.length test_names in
6832
6833   pr "\
6834 int main (int argc, char *argv[])
6835 {
6836   char c = 0;
6837   unsigned long int n_failed = 0;
6838   const char *filename;
6839   int fd;
6840   int nr_tests, test_num = 0;
6841
6842   setbuf (stdout, NULL);
6843
6844   no_test_warnings ();
6845
6846   g = guestfs_create ();
6847   if (g == NULL) {
6848     printf (\"guestfs_create FAILED\\n\");
6849     exit (EXIT_FAILURE);
6850   }
6851
6852   guestfs_set_error_handler (g, print_error, NULL);
6853
6854   guestfs_set_path (g, \"../appliance\");
6855
6856   filename = \"test1.img\";
6857   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6858   if (fd == -1) {
6859     perror (filename);
6860     exit (EXIT_FAILURE);
6861   }
6862   if (lseek (fd, %d, SEEK_SET) == -1) {
6863     perror (\"lseek\");
6864     close (fd);
6865     unlink (filename);
6866     exit (EXIT_FAILURE);
6867   }
6868   if (write (fd, &c, 1) == -1) {
6869     perror (\"write\");
6870     close (fd);
6871     unlink (filename);
6872     exit (EXIT_FAILURE);
6873   }
6874   if (close (fd) == -1) {
6875     perror (filename);
6876     unlink (filename);
6877     exit (EXIT_FAILURE);
6878   }
6879   if (guestfs_add_drive (g, filename) == -1) {
6880     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6881     exit (EXIT_FAILURE);
6882   }
6883
6884   filename = \"test2.img\";
6885   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6886   if (fd == -1) {
6887     perror (filename);
6888     exit (EXIT_FAILURE);
6889   }
6890   if (lseek (fd, %d, SEEK_SET) == -1) {
6891     perror (\"lseek\");
6892     close (fd);
6893     unlink (filename);
6894     exit (EXIT_FAILURE);
6895   }
6896   if (write (fd, &c, 1) == -1) {
6897     perror (\"write\");
6898     close (fd);
6899     unlink (filename);
6900     exit (EXIT_FAILURE);
6901   }
6902   if (close (fd) == -1) {
6903     perror (filename);
6904     unlink (filename);
6905     exit (EXIT_FAILURE);
6906   }
6907   if (guestfs_add_drive (g, filename) == -1) {
6908     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6909     exit (EXIT_FAILURE);
6910   }
6911
6912   filename = \"test3.img\";
6913   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6914   if (fd == -1) {
6915     perror (filename);
6916     exit (EXIT_FAILURE);
6917   }
6918   if (lseek (fd, %d, SEEK_SET) == -1) {
6919     perror (\"lseek\");
6920     close (fd);
6921     unlink (filename);
6922     exit (EXIT_FAILURE);
6923   }
6924   if (write (fd, &c, 1) == -1) {
6925     perror (\"write\");
6926     close (fd);
6927     unlink (filename);
6928     exit (EXIT_FAILURE);
6929   }
6930   if (close (fd) == -1) {
6931     perror (filename);
6932     unlink (filename);
6933     exit (EXIT_FAILURE);
6934   }
6935   if (guestfs_add_drive (g, filename) == -1) {
6936     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6937     exit (EXIT_FAILURE);
6938   }
6939
6940   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6941     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6942     exit (EXIT_FAILURE);
6943   }
6944
6945   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6946   alarm (600);
6947
6948   if (guestfs_launch (g) == -1) {
6949     printf (\"guestfs_launch FAILED\\n\");
6950     exit (EXIT_FAILURE);
6951   }
6952
6953   /* Cancel previous alarm. */
6954   alarm (0);
6955
6956   nr_tests = %d;
6957
6958 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6959
6960   iteri (
6961     fun i test_name ->
6962       pr "  test_num++;\n";
6963       pr "  if (guestfs_get_verbose (g))\n";
6964       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6965       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6966       pr "  if (%s () == -1) {\n" test_name;
6967       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6968       pr "    n_failed++;\n";
6969       pr "  }\n";
6970   ) test_names;
6971   pr "\n";
6972
6973   pr "  guestfs_close (g);\n";
6974   pr "  unlink (\"test1.img\");\n";
6975   pr "  unlink (\"test2.img\");\n";
6976   pr "  unlink (\"test3.img\");\n";
6977   pr "\n";
6978
6979   pr "  if (n_failed > 0) {\n";
6980   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6981   pr "    exit (EXIT_FAILURE);\n";
6982   pr "  }\n";
6983   pr "\n";
6984
6985   pr "  exit (EXIT_SUCCESS);\n";
6986   pr "}\n"
6987
6988 and generate_one_test name flags i (init, prereq, test) =
6989   let test_name = sprintf "test_%s_%d" name i in
6990
6991   pr "\
6992 static int %s_skip (void)
6993 {
6994   const char *str;
6995
6996   str = getenv (\"TEST_ONLY\");
6997   if (str)
6998     return strstr (str, \"%s\") == NULL;
6999   str = getenv (\"SKIP_%s\");
7000   if (str && STREQ (str, \"1\")) return 1;
7001   str = getenv (\"SKIP_TEST_%s\");
7002   if (str && STREQ (str, \"1\")) return 1;
7003   return 0;
7004 }
7005
7006 " test_name name (String.uppercase test_name) (String.uppercase name);
7007
7008   (match prereq with
7009    | Disabled | Always -> ()
7010    | If code | Unless code ->
7011        pr "static int %s_prereq (void)\n" test_name;
7012        pr "{\n";
7013        pr "  %s\n" code;
7014        pr "}\n";
7015        pr "\n";
7016   );
7017
7018   pr "\
7019 static int %s (void)
7020 {
7021   if (%s_skip ()) {
7022     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7023     return 0;
7024   }
7025
7026 " test_name test_name test_name;
7027
7028   (* Optional functions should only be tested if the relevant
7029    * support is available in the daemon.
7030    *)
7031   List.iter (
7032     function
7033     | Optional group ->
7034         pr "  {\n";
7035         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7036         pr "    int r;\n";
7037         pr "    suppress_error = 1;\n";
7038         pr "    r = guestfs_available (g, (char **) groups);\n";
7039         pr "    suppress_error = 0;\n";
7040         pr "    if (r == -1) {\n";
7041         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7042         pr "      return 0;\n";
7043         pr "    }\n";
7044         pr "  }\n";
7045     | _ -> ()
7046   ) flags;
7047
7048   (match prereq with
7049    | Disabled ->
7050        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7051    | If _ ->
7052        pr "  if (! %s_prereq ()) {\n" test_name;
7053        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7054        pr "    return 0;\n";
7055        pr "  }\n";
7056        pr "\n";
7057        generate_one_test_body name i test_name init test;
7058    | Unless _ ->
7059        pr "  if (%s_prereq ()) {\n" test_name;
7060        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7061        pr "    return 0;\n";
7062        pr "  }\n";
7063        pr "\n";
7064        generate_one_test_body name i test_name init test;
7065    | Always ->
7066        generate_one_test_body name i test_name init test
7067   );
7068
7069   pr "  return 0;\n";
7070   pr "}\n";
7071   pr "\n";
7072   test_name
7073
7074 and generate_one_test_body name i test_name init test =
7075   (match init with
7076    | InitNone (* XXX at some point, InitNone and InitEmpty became
7077                * folded together as the same thing.  Really we should
7078                * make InitNone do nothing at all, but the tests may
7079                * need to be checked to make sure this is OK.
7080                *)
7081    | InitEmpty ->
7082        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7083        List.iter (generate_test_command_call test_name)
7084          [["blockdev_setrw"; "/dev/sda"];
7085           ["umount_all"];
7086           ["lvm_remove_all"]]
7087    | InitPartition ->
7088        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7089        List.iter (generate_test_command_call test_name)
7090          [["blockdev_setrw"; "/dev/sda"];
7091           ["umount_all"];
7092           ["lvm_remove_all"];
7093           ["part_disk"; "/dev/sda"; "mbr"]]
7094    | InitBasicFS ->
7095        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7096        List.iter (generate_test_command_call test_name)
7097          [["blockdev_setrw"; "/dev/sda"];
7098           ["umount_all"];
7099           ["lvm_remove_all"];
7100           ["part_disk"; "/dev/sda"; "mbr"];
7101           ["mkfs"; "ext2"; "/dev/sda1"];
7102           ["mount_options"; ""; "/dev/sda1"; "/"]]
7103    | InitBasicFSonLVM ->
7104        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7105          test_name;
7106        List.iter (generate_test_command_call test_name)
7107          [["blockdev_setrw"; "/dev/sda"];
7108           ["umount_all"];
7109           ["lvm_remove_all"];
7110           ["part_disk"; "/dev/sda"; "mbr"];
7111           ["pvcreate"; "/dev/sda1"];
7112           ["vgcreate"; "VG"; "/dev/sda1"];
7113           ["lvcreate"; "LV"; "VG"; "8"];
7114           ["mkfs"; "ext2"; "/dev/VG/LV"];
7115           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7116    | InitISOFS ->
7117        pr "  /* InitISOFS for %s */\n" test_name;
7118        List.iter (generate_test_command_call test_name)
7119          [["blockdev_setrw"; "/dev/sda"];
7120           ["umount_all"];
7121           ["lvm_remove_all"];
7122           ["mount_ro"; "/dev/sdd"; "/"]]
7123   );
7124
7125   let get_seq_last = function
7126     | [] ->
7127         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7128           test_name
7129     | seq ->
7130         let seq = List.rev seq in
7131         List.rev (List.tl seq), List.hd seq
7132   in
7133
7134   match test with
7135   | TestRun seq ->
7136       pr "  /* TestRun for %s (%d) */\n" name i;
7137       List.iter (generate_test_command_call test_name) seq
7138   | TestOutput (seq, expected) ->
7139       pr "  /* TestOutput for %s (%d) */\n" name i;
7140       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7141       let seq, last = get_seq_last seq in
7142       let test () =
7143         pr "    if (STRNEQ (r, expected)) {\n";
7144         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7145         pr "      return -1;\n";
7146         pr "    }\n"
7147       in
7148       List.iter (generate_test_command_call test_name) seq;
7149       generate_test_command_call ~test test_name last
7150   | TestOutputList (seq, expected) ->
7151       pr "  /* TestOutputList for %s (%d) */\n" name i;
7152       let seq, last = get_seq_last seq in
7153       let test () =
7154         iteri (
7155           fun i str ->
7156             pr "    if (!r[%d]) {\n" i;
7157             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7158             pr "      print_strings (r);\n";
7159             pr "      return -1;\n";
7160             pr "    }\n";
7161             pr "    {\n";
7162             pr "      const char *expected = \"%s\";\n" (c_quote str);
7163             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7164             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7165             pr "        return -1;\n";
7166             pr "      }\n";
7167             pr "    }\n"
7168         ) expected;
7169         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7170         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7171           test_name;
7172         pr "      print_strings (r);\n";
7173         pr "      return -1;\n";
7174         pr "    }\n"
7175       in
7176       List.iter (generate_test_command_call test_name) seq;
7177       generate_test_command_call ~test test_name last
7178   | TestOutputListOfDevices (seq, expected) ->
7179       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7180       let seq, last = get_seq_last seq in
7181       let test () =
7182         iteri (
7183           fun i str ->
7184             pr "    if (!r[%d]) {\n" i;
7185             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7186             pr "      print_strings (r);\n";
7187             pr "      return -1;\n";
7188             pr "    }\n";
7189             pr "    {\n";
7190             pr "      const char *expected = \"%s\";\n" (c_quote str);
7191             pr "      r[%d][5] = 's';\n" i;
7192             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7193             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7194             pr "        return -1;\n";
7195             pr "      }\n";
7196             pr "    }\n"
7197         ) expected;
7198         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7199         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7200           test_name;
7201         pr "      print_strings (r);\n";
7202         pr "      return -1;\n";
7203         pr "    }\n"
7204       in
7205       List.iter (generate_test_command_call test_name) seq;
7206       generate_test_command_call ~test test_name last
7207   | TestOutputInt (seq, expected) ->
7208       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7209       let seq, last = get_seq_last seq in
7210       let test () =
7211         pr "    if (r != %d) {\n" expected;
7212         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7213           test_name expected;
7214         pr "               (int) r);\n";
7215         pr "      return -1;\n";
7216         pr "    }\n"
7217       in
7218       List.iter (generate_test_command_call test_name) seq;
7219       generate_test_command_call ~test test_name last
7220   | TestOutputIntOp (seq, op, expected) ->
7221       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7222       let seq, last = get_seq_last seq in
7223       let test () =
7224         pr "    if (! (r %s %d)) {\n" op expected;
7225         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7226           test_name op expected;
7227         pr "               (int) r);\n";
7228         pr "      return -1;\n";
7229         pr "    }\n"
7230       in
7231       List.iter (generate_test_command_call test_name) seq;
7232       generate_test_command_call ~test test_name last
7233   | TestOutputTrue seq ->
7234       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7235       let seq, last = get_seq_last seq in
7236       let test () =
7237         pr "    if (!r) {\n";
7238         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7239           test_name;
7240         pr "      return -1;\n";
7241         pr "    }\n"
7242       in
7243       List.iter (generate_test_command_call test_name) seq;
7244       generate_test_command_call ~test test_name last
7245   | TestOutputFalse seq ->
7246       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7247       let seq, last = get_seq_last seq in
7248       let test () =
7249         pr "    if (r) {\n";
7250         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7251           test_name;
7252         pr "      return -1;\n";
7253         pr "    }\n"
7254       in
7255       List.iter (generate_test_command_call test_name) seq;
7256       generate_test_command_call ~test test_name last
7257   | TestOutputLength (seq, expected) ->
7258       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7259       let seq, last = get_seq_last seq in
7260       let test () =
7261         pr "    int j;\n";
7262         pr "    for (j = 0; j < %d; ++j)\n" expected;
7263         pr "      if (r[j] == NULL) {\n";
7264         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7265           test_name;
7266         pr "        print_strings (r);\n";
7267         pr "        return -1;\n";
7268         pr "      }\n";
7269         pr "    if (r[j] != NULL) {\n";
7270         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7271           test_name;
7272         pr "      print_strings (r);\n";
7273         pr "      return -1;\n";
7274         pr "    }\n"
7275       in
7276       List.iter (generate_test_command_call test_name) seq;
7277       generate_test_command_call ~test test_name last
7278   | TestOutputBuffer (seq, expected) ->
7279       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7280       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7281       let seq, last = get_seq_last seq in
7282       let len = String.length expected in
7283       let test () =
7284         pr "    if (size != %d) {\n" len;
7285         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7286         pr "      return -1;\n";
7287         pr "    }\n";
7288         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7289         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7290         pr "      return -1;\n";
7291         pr "    }\n"
7292       in
7293       List.iter (generate_test_command_call test_name) seq;
7294       generate_test_command_call ~test test_name last
7295   | TestOutputStruct (seq, checks) ->
7296       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7297       let seq, last = get_seq_last seq in
7298       let test () =
7299         List.iter (
7300           function
7301           | CompareWithInt (field, expected) ->
7302               pr "    if (r->%s != %d) {\n" field expected;
7303               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7304                 test_name field expected;
7305               pr "               (int) r->%s);\n" field;
7306               pr "      return -1;\n";
7307               pr "    }\n"
7308           | CompareWithIntOp (field, op, expected) ->
7309               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7310               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7311                 test_name field op expected;
7312               pr "               (int) r->%s);\n" field;
7313               pr "      return -1;\n";
7314               pr "    }\n"
7315           | CompareWithString (field, expected) ->
7316               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7317               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7318                 test_name field expected;
7319               pr "               r->%s);\n" field;
7320               pr "      return -1;\n";
7321               pr "    }\n"
7322           | CompareFieldsIntEq (field1, field2) ->
7323               pr "    if (r->%s != r->%s) {\n" field1 field2;
7324               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7325                 test_name field1 field2;
7326               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7327               pr "      return -1;\n";
7328               pr "    }\n"
7329           | CompareFieldsStrEq (field1, field2) ->
7330               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7331               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7332                 test_name field1 field2;
7333               pr "               r->%s, r->%s);\n" field1 field2;
7334               pr "      return -1;\n";
7335               pr "    }\n"
7336         ) checks
7337       in
7338       List.iter (generate_test_command_call test_name) seq;
7339       generate_test_command_call ~test test_name last
7340   | TestLastFail seq ->
7341       pr "  /* TestLastFail for %s (%d) */\n" name i;
7342       let seq, last = get_seq_last seq in
7343       List.iter (generate_test_command_call test_name) seq;
7344       generate_test_command_call test_name ~expect_error:true last
7345
7346 (* Generate the code to run a command, leaving the result in 'r'.
7347  * If you expect to get an error then you should set expect_error:true.
7348  *)
7349 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7350   match cmd with
7351   | [] -> assert false
7352   | name :: args ->
7353       (* Look up the command to find out what args/ret it has. *)
7354       let style =
7355         try
7356           let _, style, _, _, _, _, _ =
7357             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7358           style
7359         with Not_found ->
7360           failwithf "%s: in test, command %s was not found" test_name name in
7361
7362       if List.length (snd style) <> List.length args then
7363         failwithf "%s: in test, wrong number of args given to %s"
7364           test_name name;
7365
7366       pr "  {\n";
7367
7368       List.iter (
7369         function
7370         | OptString n, "NULL" -> ()
7371         | Pathname n, arg
7372         | Device n, arg
7373         | Dev_or_Path n, arg
7374         | String n, arg
7375         | OptString n, arg ->
7376             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7377         | BufferIn n, arg ->
7378             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7379             pr "    size_t %s_size = %d;\n" n (String.length arg)
7380         | Int _, _
7381         | Int64 _, _
7382         | Bool _, _
7383         | FileIn _, _ | FileOut _, _ -> ()
7384         | StringList n, "" | DeviceList n, "" ->
7385             pr "    const char *const %s[1] = { NULL };\n" n
7386         | StringList n, arg | DeviceList n, arg ->
7387             let strs = string_split " " arg in
7388             iteri (
7389               fun i str ->
7390                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7391             ) strs;
7392             pr "    const char *const %s[] = {\n" n;
7393             iteri (
7394               fun i _ -> pr "      %s_%d,\n" n i
7395             ) strs;
7396             pr "      NULL\n";
7397             pr "    };\n";
7398       ) (List.combine (snd style) args);
7399
7400       let error_code =
7401         match fst style with
7402         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7403         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7404         | RConstString _ | RConstOptString _ ->
7405             pr "    const char *r;\n"; "NULL"
7406         | RString _ -> pr "    char *r;\n"; "NULL"
7407         | RStringList _ | RHashtable _ ->
7408             pr "    char **r;\n";
7409             pr "    int i;\n";
7410             "NULL"
7411         | RStruct (_, typ) ->
7412             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7413         | RStructList (_, typ) ->
7414             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7415         | RBufferOut _ ->
7416             pr "    char *r;\n";
7417             pr "    size_t size;\n";
7418             "NULL" in
7419
7420       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7421       pr "    r = guestfs_%s (g" name;
7422
7423       (* Generate the parameters. *)
7424       List.iter (
7425         function
7426         | OptString _, "NULL" -> pr ", NULL"
7427         | Pathname n, _
7428         | Device n, _ | Dev_or_Path n, _
7429         | String n, _
7430         | OptString n, _ ->
7431             pr ", %s" n
7432         | BufferIn n, _ ->
7433             pr ", %s, %s_size" n n
7434         | FileIn _, arg | FileOut _, arg ->
7435             pr ", \"%s\"" (c_quote arg)
7436         | StringList n, _ | DeviceList n, _ ->
7437             pr ", (char **) %s" n
7438         | Int _, arg ->
7439             let i =
7440               try int_of_string arg
7441               with Failure "int_of_string" ->
7442                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7443             pr ", %d" i
7444         | Int64 _, arg ->
7445             let i =
7446               try Int64.of_string arg
7447               with Failure "int_of_string" ->
7448                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7449             pr ", %Ld" i
7450         | Bool _, arg ->
7451             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7452       ) (List.combine (snd style) args);
7453
7454       (match fst style with
7455        | RBufferOut _ -> pr ", &size"
7456        | _ -> ()
7457       );
7458
7459       pr ");\n";
7460
7461       if not expect_error then
7462         pr "    if (r == %s)\n" error_code
7463       else
7464         pr "    if (r != %s)\n" error_code;
7465       pr "      return -1;\n";
7466
7467       (* Insert the test code. *)
7468       (match test with
7469        | None -> ()
7470        | Some f -> f ()
7471       );
7472
7473       (match fst style with
7474        | RErr | RInt _ | RInt64 _ | RBool _
7475        | RConstString _ | RConstOptString _ -> ()
7476        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7477        | RStringList _ | RHashtable _ ->
7478            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7479            pr "      free (r[i]);\n";
7480            pr "    free (r);\n"
7481        | RStruct (_, typ) ->
7482            pr "    guestfs_free_%s (r);\n" typ
7483        | RStructList (_, typ) ->
7484            pr "    guestfs_free_%s_list (r);\n" typ
7485       );
7486
7487       pr "  }\n"
7488
7489 and c_quote str =
7490   let str = replace_str str "\r" "\\r" in
7491   let str = replace_str str "\n" "\\n" in
7492   let str = replace_str str "\t" "\\t" in
7493   let str = replace_str str "\000" "\\0" in
7494   str
7495
7496 (* Generate a lot of different functions for guestfish. *)
7497 and generate_fish_cmds () =
7498   generate_header CStyle GPLv2plus;
7499
7500   let all_functions =
7501     List.filter (
7502       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7503     ) all_functions in
7504   let all_functions_sorted =
7505     List.filter (
7506       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7507     ) all_functions_sorted in
7508
7509   pr "#include <config.h>\n";
7510   pr "\n";
7511   pr "#include <stdio.h>\n";
7512   pr "#include <stdlib.h>\n";
7513   pr "#include <string.h>\n";
7514   pr "#include <inttypes.h>\n";
7515   pr "\n";
7516   pr "#include <guestfs.h>\n";
7517   pr "#include \"c-ctype.h\"\n";
7518   pr "#include \"full-write.h\"\n";
7519   pr "#include \"xstrtol.h\"\n";
7520   pr "#include \"fish.h\"\n";
7521   pr "\n";
7522   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7523   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7524   pr "\n";
7525
7526   (* list_commands function, which implements guestfish -h *)
7527   pr "void list_commands (void)\n";
7528   pr "{\n";
7529   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7530   pr "  list_builtin_commands ();\n";
7531   List.iter (
7532     fun (name, _, _, flags, _, shortdesc, _) ->
7533       let name = replace_char name '_' '-' in
7534       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7535         name shortdesc
7536   ) all_functions_sorted;
7537   pr "  printf (\"    %%s\\n\",";
7538   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7539   pr "}\n";
7540   pr "\n";
7541
7542   (* display_command function, which implements guestfish -h cmd *)
7543   pr "void display_command (const char *cmd)\n";
7544   pr "{\n";
7545   List.iter (
7546     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7547       let name2 = replace_char name '_' '-' in
7548       let alias =
7549         try find_map (function FishAlias n -> Some n | _ -> None) flags
7550         with Not_found -> name in
7551       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7552       let synopsis =
7553         match snd style with
7554         | [] -> name2
7555         | args ->
7556             sprintf "%s %s"
7557               name2 (String.concat " " (List.map name_of_argt args)) in
7558
7559       let warnings =
7560         if List.mem ProtocolLimitWarning flags then
7561           ("\n\n" ^ protocol_limit_warning)
7562         else "" in
7563
7564       (* For DangerWillRobinson commands, we should probably have
7565        * guestfish prompt before allowing you to use them (especially
7566        * in interactive mode). XXX
7567        *)
7568       let warnings =
7569         warnings ^
7570           if List.mem DangerWillRobinson flags then
7571             ("\n\n" ^ danger_will_robinson)
7572           else "" in
7573
7574       let warnings =
7575         warnings ^
7576           match deprecation_notice flags with
7577           | None -> ""
7578           | Some txt -> "\n\n" ^ txt in
7579
7580       let describe_alias =
7581         if name <> alias then
7582           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7583         else "" in
7584
7585       pr "  if (";
7586       pr "STRCASEEQ (cmd, \"%s\")" name;
7587       if name <> name2 then
7588         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7589       if name <> alias then
7590         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7591       pr ")\n";
7592       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7593         name2 shortdesc
7594         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7595          "=head1 DESCRIPTION\n\n" ^
7596          longdesc ^ warnings ^ describe_alias);
7597       pr "  else\n"
7598   ) all_functions;
7599   pr "    display_builtin_command (cmd);\n";
7600   pr "}\n";
7601   pr "\n";
7602
7603   let emit_print_list_function typ =
7604     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7605       typ typ typ;
7606     pr "{\n";
7607     pr "  unsigned int i;\n";
7608     pr "\n";
7609     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7610     pr "    printf (\"[%%d] = {\\n\", i);\n";
7611     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7612     pr "    printf (\"}\\n\");\n";
7613     pr "  }\n";
7614     pr "}\n";
7615     pr "\n";
7616   in
7617
7618   (* print_* functions *)
7619   List.iter (
7620     fun (typ, cols) ->
7621       let needs_i =
7622         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7623
7624       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7625       pr "{\n";
7626       if needs_i then (
7627         pr "  unsigned int i;\n";
7628         pr "\n"
7629       );
7630       List.iter (
7631         function
7632         | name, FString ->
7633             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7634         | name, FUUID ->
7635             pr "  printf (\"%%s%s: \", indent);\n" name;
7636             pr "  for (i = 0; i < 32; ++i)\n";
7637             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7638             pr "  printf (\"\\n\");\n"
7639         | name, FBuffer ->
7640             pr "  printf (\"%%s%s: \", indent);\n" name;
7641             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7642             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7643             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7644             pr "    else\n";
7645             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7646             pr "  printf (\"\\n\");\n"
7647         | name, (FUInt64|FBytes) ->
7648             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7649               name typ name
7650         | name, FInt64 ->
7651             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7652               name typ name
7653         | name, FUInt32 ->
7654             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7655               name typ name
7656         | name, FInt32 ->
7657             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7658               name typ name
7659         | name, FChar ->
7660             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7661               name typ name
7662         | name, FOptPercent ->
7663             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7664               typ name name typ name;
7665             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7666       ) cols;
7667       pr "}\n";
7668       pr "\n";
7669   ) structs;
7670
7671   (* Emit a print_TYPE_list function definition only if that function is used. *)
7672   List.iter (
7673     function
7674     | typ, (RStructListOnly | RStructAndList) ->
7675         (* generate the function for typ *)
7676         emit_print_list_function typ
7677     | typ, _ -> () (* empty *)
7678   ) (rstructs_used_by all_functions);
7679
7680   (* Emit a print_TYPE function definition only if that function is used. *)
7681   List.iter (
7682     function
7683     | typ, (RStructOnly | RStructAndList) ->
7684         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7685         pr "{\n";
7686         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7687         pr "}\n";
7688         pr "\n";
7689     | typ, _ -> () (* empty *)
7690   ) (rstructs_used_by all_functions);
7691
7692   (* run_<action> actions *)
7693   List.iter (
7694     fun (name, style, _, flags, _, _, _) ->
7695       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7696       pr "{\n";
7697       (match fst style with
7698        | RErr
7699        | RInt _
7700        | RBool _ -> pr "  int r;\n"
7701        | RInt64 _ -> pr "  int64_t r;\n"
7702        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7703        | RString _ -> pr "  char *r;\n"
7704        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7705        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7706        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7707        | RBufferOut _ ->
7708            pr "  char *r;\n";
7709            pr "  size_t size;\n";
7710       );
7711       List.iter (
7712         function
7713         | Device n
7714         | String n
7715         | OptString n -> pr "  const char *%s;\n" n
7716         | Pathname n
7717         | Dev_or_Path n
7718         | FileIn n
7719         | FileOut n -> pr "  char *%s;\n" n
7720         | BufferIn n ->
7721             pr "  const char *%s;\n" n;
7722             pr "  size_t %s_size;\n" n
7723         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7724         | Bool n -> pr "  int %s;\n" n
7725         | Int n -> pr "  int %s;\n" n
7726         | Int64 n -> pr "  int64_t %s;\n" n
7727       ) (snd style);
7728
7729       (* Check and convert parameters. *)
7730       let argc_expected = List.length (snd style) in
7731       pr "  if (argc != %d) {\n" argc_expected;
7732       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7733         argc_expected;
7734       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7735       pr "    return -1;\n";
7736       pr "  }\n";
7737
7738       let parse_integer fn fntyp rtyp range name i =
7739         pr "  {\n";
7740         pr "    strtol_error xerr;\n";
7741         pr "    %s r;\n" fntyp;
7742         pr "\n";
7743         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7744         pr "    if (xerr != LONGINT_OK) {\n";
7745         pr "      fprintf (stderr,\n";
7746         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7747         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7748         pr "      return -1;\n";
7749         pr "    }\n";
7750         (match range with
7751          | None -> ()
7752          | Some (min, max, comment) ->
7753              pr "    /* %s */\n" comment;
7754              pr "    if (r < %s || r > %s) {\n" min max;
7755              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7756                name;
7757              pr "      return -1;\n";
7758              pr "    }\n";
7759              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7760         );
7761         pr "    %s = r;\n" name;
7762         pr "  }\n";
7763       in
7764
7765       iteri (
7766         fun i ->
7767           function
7768           | Device name
7769           | String name ->
7770               pr "  %s = argv[%d];\n" name i
7771           | Pathname name
7772           | Dev_or_Path name ->
7773               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7774               pr "  if (%s == NULL) return -1;\n" name
7775           | OptString name ->
7776               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7777                 name i i
7778           | BufferIn name ->
7779               pr "  %s = argv[%d];\n" name i;
7780               pr "  %s_size = strlen (argv[%d]);\n" name i
7781           | FileIn name ->
7782               pr "  %s = file_in (argv[%d]);\n" name i;
7783               pr "  if (%s == NULL) return -1;\n" name
7784           | FileOut name ->
7785               pr "  %s = file_out (argv[%d]);\n" name i;
7786               pr "  if (%s == NULL) return -1;\n" name
7787           | StringList name | DeviceList name ->
7788               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7789               pr "  if (%s == NULL) return -1;\n" name;
7790           | Bool name ->
7791               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7792           | Int name ->
7793               let range =
7794                 let min = "(-(2LL<<30))"
7795                 and max = "((2LL<<30)-1)"
7796                 and comment =
7797                   "The Int type in the generator is a signed 31 bit int." in
7798                 Some (min, max, comment) in
7799               parse_integer "xstrtoll" "long long" "int" range name i
7800           | Int64 name ->
7801               parse_integer "xstrtoll" "long long" "int64_t" None name i
7802       ) (snd style);
7803
7804       (* Call C API function. *)
7805       pr "  r = guestfs_%s " name;
7806       generate_c_call_args ~handle:"g" style;
7807       pr ";\n";
7808
7809       List.iter (
7810         function
7811         | Device name | String name
7812         | OptString name | Bool name
7813         | Int name | Int64 name
7814         | BufferIn name -> ()
7815         | Pathname name | Dev_or_Path name | FileOut name ->
7816             pr "  free (%s);\n" name
7817         | FileIn name ->
7818             pr "  free_file_in (%s);\n" name
7819         | StringList name | DeviceList name ->
7820             pr "  free_strings (%s);\n" name
7821       ) (snd style);
7822
7823       (* Any output flags? *)
7824       let fish_output =
7825         let flags = filter_map (
7826           function FishOutput flag -> Some flag | _ -> None
7827         ) flags in
7828         match flags with
7829         | [] -> None
7830         | [f] -> Some f
7831         | _ ->
7832             failwithf "%s: more than one FishOutput flag is not allowed" name in
7833
7834       (* Check return value for errors and display command results. *)
7835       (match fst style with
7836        | RErr -> pr "  return r;\n"
7837        | RInt _ ->
7838            pr "  if (r == -1) return -1;\n";
7839            (match fish_output with
7840             | None ->
7841                 pr "  printf (\"%%d\\n\", r);\n";
7842             | Some FishOutputOctal ->
7843                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7844             | Some FishOutputHexadecimal ->
7845                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7846            pr "  return 0;\n"
7847        | RInt64 _ ->
7848            pr "  if (r == -1) return -1;\n";
7849            (match fish_output with
7850             | None ->
7851                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7852             | Some FishOutputOctal ->
7853                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7854             | Some FishOutputHexadecimal ->
7855                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7856            pr "  return 0;\n"
7857        | RBool _ ->
7858            pr "  if (r == -1) return -1;\n";
7859            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7860            pr "  return 0;\n"
7861        | RConstString _ ->
7862            pr "  if (r == NULL) return -1;\n";
7863            pr "  printf (\"%%s\\n\", r);\n";
7864            pr "  return 0;\n"
7865        | RConstOptString _ ->
7866            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7867            pr "  return 0;\n"
7868        | RString _ ->
7869            pr "  if (r == NULL) return -1;\n";
7870            pr "  printf (\"%%s\\n\", r);\n";
7871            pr "  free (r);\n";
7872            pr "  return 0;\n"
7873        | RStringList _ ->
7874            pr "  if (r == NULL) return -1;\n";
7875            pr "  print_strings (r);\n";
7876            pr "  free_strings (r);\n";
7877            pr "  return 0;\n"
7878        | RStruct (_, typ) ->
7879            pr "  if (r == NULL) return -1;\n";
7880            pr "  print_%s (r);\n" typ;
7881            pr "  guestfs_free_%s (r);\n" typ;
7882            pr "  return 0;\n"
7883        | RStructList (_, typ) ->
7884            pr "  if (r == NULL) return -1;\n";
7885            pr "  print_%s_list (r);\n" typ;
7886            pr "  guestfs_free_%s_list (r);\n" typ;
7887            pr "  return 0;\n"
7888        | RHashtable _ ->
7889            pr "  if (r == NULL) return -1;\n";
7890            pr "  print_table (r);\n";
7891            pr "  free_strings (r);\n";
7892            pr "  return 0;\n"
7893        | RBufferOut _ ->
7894            pr "  if (r == NULL) return -1;\n";
7895            pr "  if (full_write (1, r, size) != size) {\n";
7896            pr "    perror (\"write\");\n";
7897            pr "    free (r);\n";
7898            pr "    return -1;\n";
7899            pr "  }\n";
7900            pr "  free (r);\n";
7901            pr "  return 0;\n"
7902       );
7903       pr "}\n";
7904       pr "\n"
7905   ) all_functions;
7906
7907   (* run_action function *)
7908   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7909   pr "{\n";
7910   List.iter (
7911     fun (name, _, _, flags, _, _, _) ->
7912       let name2 = replace_char name '_' '-' in
7913       let alias =
7914         try find_map (function FishAlias n -> Some n | _ -> None) flags
7915         with Not_found -> name in
7916       pr "  if (";
7917       pr "STRCASEEQ (cmd, \"%s\")" name;
7918       if name <> name2 then
7919         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7920       if name <> alias then
7921         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7922       pr ")\n";
7923       pr "    return run_%s (cmd, argc, argv);\n" name;
7924       pr "  else\n";
7925   ) all_functions;
7926   pr "    {\n";
7927   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7928   pr "      if (command_num == 1)\n";
7929   pr "        extended_help_message ();\n";
7930   pr "      return -1;\n";
7931   pr "    }\n";
7932   pr "  return 0;\n";
7933   pr "}\n";
7934   pr "\n"
7935
7936 (* Readline completion for guestfish. *)
7937 and generate_fish_completion () =
7938   generate_header CStyle GPLv2plus;
7939
7940   let all_functions =
7941     List.filter (
7942       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7943     ) all_functions in
7944
7945   pr "\
7946 #include <config.h>
7947
7948 #include <stdio.h>
7949 #include <stdlib.h>
7950 #include <string.h>
7951
7952 #ifdef HAVE_LIBREADLINE
7953 #include <readline/readline.h>
7954 #endif
7955
7956 #include \"fish.h\"
7957
7958 #ifdef HAVE_LIBREADLINE
7959
7960 static const char *const commands[] = {
7961   BUILTIN_COMMANDS_FOR_COMPLETION,
7962 ";
7963
7964   (* Get the commands, including the aliases.  They don't need to be
7965    * sorted - the generator() function just does a dumb linear search.
7966    *)
7967   let commands =
7968     List.map (
7969       fun (name, _, _, flags, _, _, _) ->
7970         let name2 = replace_char name '_' '-' in
7971         let alias =
7972           try find_map (function FishAlias n -> Some n | _ -> None) flags
7973           with Not_found -> name in
7974
7975         if name <> alias then [name2; alias] else [name2]
7976     ) all_functions in
7977   let commands = List.flatten commands in
7978
7979   List.iter (pr "  \"%s\",\n") commands;
7980
7981   pr "  NULL
7982 };
7983
7984 static char *
7985 generator (const char *text, int state)
7986 {
7987   static int index, len;
7988   const char *name;
7989
7990   if (!state) {
7991     index = 0;
7992     len = strlen (text);
7993   }
7994
7995   rl_attempted_completion_over = 1;
7996
7997   while ((name = commands[index]) != NULL) {
7998     index++;
7999     if (STRCASEEQLEN (name, text, len))
8000       return strdup (name);
8001   }
8002
8003   return NULL;
8004 }
8005
8006 #endif /* HAVE_LIBREADLINE */
8007
8008 #ifdef HAVE_RL_COMPLETION_MATCHES
8009 #define RL_COMPLETION_MATCHES rl_completion_matches
8010 #else
8011 #ifdef HAVE_COMPLETION_MATCHES
8012 #define RL_COMPLETION_MATCHES completion_matches
8013 #endif
8014 #endif /* else just fail if we don't have either symbol */
8015
8016 char **
8017 do_completion (const char *text, int start, int end)
8018 {
8019   char **matches = NULL;
8020
8021 #ifdef HAVE_LIBREADLINE
8022   rl_completion_append_character = ' ';
8023
8024   if (start == 0)
8025     matches = RL_COMPLETION_MATCHES (text, generator);
8026   else if (complete_dest_paths)
8027     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8028 #endif
8029
8030   return matches;
8031 }
8032 ";
8033
8034 (* Generate the POD documentation for guestfish. *)
8035 and generate_fish_actions_pod () =
8036   let all_functions_sorted =
8037     List.filter (
8038       fun (_, _, _, flags, _, _, _) ->
8039         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8040     ) all_functions_sorted in
8041
8042   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8043
8044   List.iter (
8045     fun (name, style, _, flags, _, _, longdesc) ->
8046       let longdesc =
8047         Str.global_substitute rex (
8048           fun s ->
8049             let sub =
8050               try Str.matched_group 1 s
8051               with Not_found ->
8052                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8053             "C<" ^ replace_char sub '_' '-' ^ ">"
8054         ) longdesc in
8055       let name = replace_char name '_' '-' in
8056       let alias =
8057         try find_map (function FishAlias n -> Some n | _ -> None) flags
8058         with Not_found -> name in
8059
8060       pr "=head2 %s" name;
8061       if name <> alias then
8062         pr " | %s" alias;
8063       pr "\n";
8064       pr "\n";
8065       pr " %s" name;
8066       List.iter (
8067         function
8068         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8069         | OptString n -> pr " %s" n
8070         | StringList n | DeviceList n -> pr " '%s ...'" n
8071         | Bool _ -> pr " true|false"
8072         | Int n -> pr " %s" n
8073         | Int64 n -> pr " %s" n
8074         | FileIn n | FileOut n -> pr " (%s|-)" n
8075         | BufferIn n -> pr " %s" n
8076       ) (snd style);
8077       pr "\n";
8078       pr "\n";
8079       pr "%s\n\n" longdesc;
8080
8081       if List.exists (function FileIn _ | FileOut _ -> true
8082                       | _ -> false) (snd style) then
8083         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8084
8085       if List.mem ProtocolLimitWarning flags then
8086         pr "%s\n\n" protocol_limit_warning;
8087
8088       if List.mem DangerWillRobinson flags then
8089         pr "%s\n\n" danger_will_robinson;
8090
8091       match deprecation_notice flags with
8092       | None -> ()
8093       | Some txt -> pr "%s\n\n" txt
8094   ) all_functions_sorted
8095
8096 (* Generate a C function prototype. *)
8097 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8098     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8099     ?(prefix = "")
8100     ?handle name style =
8101   if extern then pr "extern ";
8102   if static then pr "static ";
8103   (match fst style with
8104    | RErr -> pr "int "
8105    | RInt _ -> pr "int "
8106    | RInt64 _ -> pr "int64_t "
8107    | RBool _ -> pr "int "
8108    | RConstString _ | RConstOptString _ -> pr "const char *"
8109    | RString _ | RBufferOut _ -> pr "char *"
8110    | RStringList _ | RHashtable _ -> pr "char **"
8111    | RStruct (_, typ) ->
8112        if not in_daemon then pr "struct guestfs_%s *" typ
8113        else pr "guestfs_int_%s *" typ
8114    | RStructList (_, typ) ->
8115        if not in_daemon then pr "struct guestfs_%s_list *" typ
8116        else pr "guestfs_int_%s_list *" typ
8117   );
8118   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8119   pr "%s%s (" prefix name;
8120   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8121     pr "void"
8122   else (
8123     let comma = ref false in
8124     (match handle with
8125      | None -> ()
8126      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8127     );
8128     let next () =
8129       if !comma then (
8130         if single_line then pr ", " else pr ",\n\t\t"
8131       );
8132       comma := true
8133     in
8134     List.iter (
8135       function
8136       | Pathname n
8137       | Device n | Dev_or_Path n
8138       | String n
8139       | OptString n ->
8140           next ();
8141           pr "const char *%s" n
8142       | StringList n | DeviceList n ->
8143           next ();
8144           pr "char *const *%s" n
8145       | Bool n -> next (); pr "int %s" n
8146       | Int n -> next (); pr "int %s" n
8147       | Int64 n -> next (); pr "int64_t %s" n
8148       | FileIn n
8149       | FileOut n ->
8150           if not in_daemon then (next (); pr "const char *%s" n)
8151       | BufferIn n ->
8152           next ();
8153           pr "const char *%s" n;
8154           next ();
8155           pr "size_t %s_size" n
8156     ) (snd style);
8157     if is_RBufferOut then (next (); pr "size_t *size_r");
8158   );
8159   pr ")";
8160   if semicolon then pr ";";
8161   if newline then pr "\n"
8162
8163 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8164 and generate_c_call_args ?handle ?(decl = false) style =
8165   pr "(";
8166   let comma = ref false in
8167   let next () =
8168     if !comma then pr ", ";
8169     comma := true
8170   in
8171   (match handle with
8172    | None -> ()
8173    | Some handle -> pr "%s" handle; comma := true
8174   );
8175   List.iter (
8176     function
8177     | BufferIn n ->
8178         next ();
8179         pr "%s, %s_size" n n
8180     | arg ->
8181         next ();
8182         pr "%s" (name_of_argt arg)
8183   ) (snd style);
8184   (* For RBufferOut calls, add implicit &size parameter. *)
8185   if not decl then (
8186     match fst style with
8187     | RBufferOut _ ->
8188         next ();
8189         pr "&size"
8190     | _ -> ()
8191   );
8192   pr ")"
8193
8194 (* Generate the OCaml bindings interface. *)
8195 and generate_ocaml_mli () =
8196   generate_header OCamlStyle LGPLv2plus;
8197
8198   pr "\
8199 (** For API documentation you should refer to the C API
8200     in the guestfs(3) manual page.  The OCaml API uses almost
8201     exactly the same calls. *)
8202
8203 type t
8204 (** A [guestfs_h] handle. *)
8205
8206 exception Error of string
8207 (** This exception is raised when there is an error. *)
8208
8209 exception Handle_closed of string
8210 (** This exception is raised if you use a {!Guestfs.t} handle
8211     after calling {!close} on it.  The string is the name of
8212     the function. *)
8213
8214 val create : unit -> t
8215 (** Create a {!Guestfs.t} handle. *)
8216
8217 val close : t -> unit
8218 (** Close the {!Guestfs.t} handle and free up all resources used
8219     by it immediately.
8220
8221     Handles are closed by the garbage collector when they become
8222     unreferenced, but callers can call this in order to provide
8223     predictable cleanup. *)
8224
8225 ";
8226   generate_ocaml_structure_decls ();
8227
8228   (* The actions. *)
8229   List.iter (
8230     fun (name, style, _, _, _, shortdesc, _) ->
8231       generate_ocaml_prototype name style;
8232       pr "(** %s *)\n" shortdesc;
8233       pr "\n"
8234   ) all_functions_sorted
8235
8236 (* Generate the OCaml bindings implementation. *)
8237 and generate_ocaml_ml () =
8238   generate_header OCamlStyle LGPLv2plus;
8239
8240   pr "\
8241 type t
8242
8243 exception Error of string
8244 exception Handle_closed of string
8245
8246 external create : unit -> t = \"ocaml_guestfs_create\"
8247 external close : t -> unit = \"ocaml_guestfs_close\"
8248
8249 (* Give the exceptions names, so they can be raised from the C code. *)
8250 let () =
8251   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8252   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8253
8254 ";
8255
8256   generate_ocaml_structure_decls ();
8257
8258   (* The actions. *)
8259   List.iter (
8260     fun (name, style, _, _, _, shortdesc, _) ->
8261       generate_ocaml_prototype ~is_external:true name style;
8262   ) all_functions_sorted
8263
8264 (* Generate the OCaml bindings C implementation. *)
8265 and generate_ocaml_c () =
8266   generate_header CStyle LGPLv2plus;
8267
8268   pr "\
8269 #include <stdio.h>
8270 #include <stdlib.h>
8271 #include <string.h>
8272
8273 #include <caml/config.h>
8274 #include <caml/alloc.h>
8275 #include <caml/callback.h>
8276 #include <caml/fail.h>
8277 #include <caml/memory.h>
8278 #include <caml/mlvalues.h>
8279 #include <caml/signals.h>
8280
8281 #include <guestfs.h>
8282
8283 #include \"guestfs_c.h\"
8284
8285 /* Copy a hashtable of string pairs into an assoc-list.  We return
8286  * the list in reverse order, but hashtables aren't supposed to be
8287  * ordered anyway.
8288  */
8289 static CAMLprim value
8290 copy_table (char * const * argv)
8291 {
8292   CAMLparam0 ();
8293   CAMLlocal5 (rv, pairv, kv, vv, cons);
8294   int i;
8295
8296   rv = Val_int (0);
8297   for (i = 0; argv[i] != NULL; i += 2) {
8298     kv = caml_copy_string (argv[i]);
8299     vv = caml_copy_string (argv[i+1]);
8300     pairv = caml_alloc (2, 0);
8301     Store_field (pairv, 0, kv);
8302     Store_field (pairv, 1, vv);
8303     cons = caml_alloc (2, 0);
8304     Store_field (cons, 1, rv);
8305     rv = cons;
8306     Store_field (cons, 0, pairv);
8307   }
8308
8309   CAMLreturn (rv);
8310 }
8311
8312 ";
8313
8314   (* Struct copy functions. *)
8315
8316   let emit_ocaml_copy_list_function typ =
8317     pr "static CAMLprim value\n";
8318     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8319     pr "{\n";
8320     pr "  CAMLparam0 ();\n";
8321     pr "  CAMLlocal2 (rv, v);\n";
8322     pr "  unsigned int i;\n";
8323     pr "\n";
8324     pr "  if (%ss->len == 0)\n" typ;
8325     pr "    CAMLreturn (Atom (0));\n";
8326     pr "  else {\n";
8327     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8328     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8329     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8330     pr "      caml_modify (&Field (rv, i), v);\n";
8331     pr "    }\n";
8332     pr "    CAMLreturn (rv);\n";
8333     pr "  }\n";
8334     pr "}\n";
8335     pr "\n";
8336   in
8337
8338   List.iter (
8339     fun (typ, cols) ->
8340       let has_optpercent_col =
8341         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8342
8343       pr "static CAMLprim value\n";
8344       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8345       pr "{\n";
8346       pr "  CAMLparam0 ();\n";
8347       if has_optpercent_col then
8348         pr "  CAMLlocal3 (rv, v, v2);\n"
8349       else
8350         pr "  CAMLlocal2 (rv, v);\n";
8351       pr "\n";
8352       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8353       iteri (
8354         fun i col ->
8355           (match col with
8356            | name, FString ->
8357                pr "  v = caml_copy_string (%s->%s);\n" typ name
8358            | name, FBuffer ->
8359                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8360                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8361                  typ name typ name
8362            | name, FUUID ->
8363                pr "  v = caml_alloc_string (32);\n";
8364                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8365            | name, (FBytes|FInt64|FUInt64) ->
8366                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8367            | name, (FInt32|FUInt32) ->
8368                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8369            | name, FOptPercent ->
8370                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8371                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8372                pr "    v = caml_alloc (1, 0);\n";
8373                pr "    Store_field (v, 0, v2);\n";
8374                pr "  } else /* None */\n";
8375                pr "    v = Val_int (0);\n";
8376            | name, FChar ->
8377                pr "  v = Val_int (%s->%s);\n" typ name
8378           );
8379           pr "  Store_field (rv, %d, v);\n" i
8380       ) cols;
8381       pr "  CAMLreturn (rv);\n";
8382       pr "}\n";
8383       pr "\n";
8384   ) structs;
8385
8386   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8387   List.iter (
8388     function
8389     | typ, (RStructListOnly | RStructAndList) ->
8390         (* generate the function for typ *)
8391         emit_ocaml_copy_list_function typ
8392     | typ, _ -> () (* empty *)
8393   ) (rstructs_used_by all_functions);
8394
8395   (* The wrappers. *)
8396   List.iter (
8397     fun (name, style, _, _, _, _, _) ->
8398       pr "/* Automatically generated wrapper for function\n";
8399       pr " * ";
8400       generate_ocaml_prototype name style;
8401       pr " */\n";
8402       pr "\n";
8403
8404       let params =
8405         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8406
8407       let needs_extra_vs =
8408         match fst style with RConstOptString _ -> true | _ -> false in
8409
8410       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8411       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8412       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8413       pr "\n";
8414
8415       pr "CAMLprim value\n";
8416       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8417       List.iter (pr ", value %s") (List.tl params);
8418       pr ")\n";
8419       pr "{\n";
8420
8421       (match params with
8422        | [p1; p2; p3; p4; p5] ->
8423            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8424        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8425            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8426            pr "  CAMLxparam%d (%s);\n"
8427              (List.length rest) (String.concat ", " rest)
8428        | ps ->
8429            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8430       );
8431       if not needs_extra_vs then
8432         pr "  CAMLlocal1 (rv);\n"
8433       else
8434         pr "  CAMLlocal3 (rv, v, v2);\n";
8435       pr "\n";
8436
8437       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8438       pr "  if (g == NULL)\n";
8439       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8440       pr "\n";
8441
8442       List.iter (
8443         function
8444         | Pathname n
8445         | Device n | Dev_or_Path n
8446         | String n
8447         | FileIn n
8448         | FileOut n ->
8449             pr "  const char *%s = String_val (%sv);\n" n n
8450         | OptString n ->
8451             pr "  const char *%s =\n" n;
8452             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8453               n n
8454         | BufferIn n ->
8455             pr "  const char *%s = String_val (%sv);\n" n n;
8456             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8457         | StringList n | DeviceList n ->
8458             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8459         | Bool n ->
8460             pr "  int %s = Bool_val (%sv);\n" n n
8461         | Int n ->
8462             pr "  int %s = Int_val (%sv);\n" n n
8463         | Int64 n ->
8464             pr "  int64_t %s = Int64_val (%sv);\n" n n
8465       ) (snd style);
8466       let error_code =
8467         match fst style with
8468         | RErr -> pr "  int r;\n"; "-1"
8469         | RInt _ -> pr "  int r;\n"; "-1"
8470         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8471         | RBool _ -> pr "  int r;\n"; "-1"
8472         | RConstString _ | RConstOptString _ ->
8473             pr "  const char *r;\n"; "NULL"
8474         | RString _ -> pr "  char *r;\n"; "NULL"
8475         | RStringList _ ->
8476             pr "  int i;\n";
8477             pr "  char **r;\n";
8478             "NULL"
8479         | RStruct (_, typ) ->
8480             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8481         | RStructList (_, typ) ->
8482             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8483         | RHashtable _ ->
8484             pr "  int i;\n";
8485             pr "  char **r;\n";
8486             "NULL"
8487         | RBufferOut _ ->
8488             pr "  char *r;\n";
8489             pr "  size_t size;\n";
8490             "NULL" in
8491       pr "\n";
8492
8493       pr "  caml_enter_blocking_section ();\n";
8494       pr "  r = guestfs_%s " name;
8495       generate_c_call_args ~handle:"g" style;
8496       pr ";\n";
8497       pr "  caml_leave_blocking_section ();\n";
8498
8499       List.iter (
8500         function
8501         | StringList n | DeviceList n ->
8502             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8503         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8504         | Bool _ | Int _ | Int64 _
8505         | FileIn _ | FileOut _ | BufferIn _ -> ()
8506       ) (snd style);
8507
8508       pr "  if (r == %s)\n" error_code;
8509       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8510       pr "\n";
8511
8512       (match fst style with
8513        | RErr -> pr "  rv = Val_unit;\n"
8514        | RInt _ -> pr "  rv = Val_int (r);\n"
8515        | RInt64 _ ->
8516            pr "  rv = caml_copy_int64 (r);\n"
8517        | RBool _ -> pr "  rv = Val_bool (r);\n"
8518        | RConstString _ ->
8519            pr "  rv = caml_copy_string (r);\n"
8520        | RConstOptString _ ->
8521            pr "  if (r) { /* Some string */\n";
8522            pr "    v = caml_alloc (1, 0);\n";
8523            pr "    v2 = caml_copy_string (r);\n";
8524            pr "    Store_field (v, 0, v2);\n";
8525            pr "  } else /* None */\n";
8526            pr "    v = Val_int (0);\n";
8527        | RString _ ->
8528            pr "  rv = caml_copy_string (r);\n";
8529            pr "  free (r);\n"
8530        | RStringList _ ->
8531            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8532            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8533            pr "  free (r);\n"
8534        | RStruct (_, typ) ->
8535            pr "  rv = copy_%s (r);\n" typ;
8536            pr "  guestfs_free_%s (r);\n" typ;
8537        | RStructList (_, typ) ->
8538            pr "  rv = copy_%s_list (r);\n" typ;
8539            pr "  guestfs_free_%s_list (r);\n" typ;
8540        | RHashtable _ ->
8541            pr "  rv = copy_table (r);\n";
8542            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8543            pr "  free (r);\n";
8544        | RBufferOut _ ->
8545            pr "  rv = caml_alloc_string (size);\n";
8546            pr "  memcpy (String_val (rv), r, size);\n";
8547       );
8548
8549       pr "  CAMLreturn (rv);\n";
8550       pr "}\n";
8551       pr "\n";
8552
8553       if List.length params > 5 then (
8554         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8555         pr "CAMLprim value ";
8556         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8557         pr "CAMLprim value\n";
8558         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8559         pr "{\n";
8560         pr "  return ocaml_guestfs_%s (argv[0]" name;
8561         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8562         pr ");\n";
8563         pr "}\n";
8564         pr "\n"
8565       )
8566   ) all_functions_sorted
8567
8568 and generate_ocaml_structure_decls () =
8569   List.iter (
8570     fun (typ, cols) ->
8571       pr "type %s = {\n" typ;
8572       List.iter (
8573         function
8574         | name, FString -> pr "  %s : string;\n" name
8575         | name, FBuffer -> pr "  %s : string;\n" name
8576         | name, FUUID -> pr "  %s : string;\n" name
8577         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8578         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8579         | name, FChar -> pr "  %s : char;\n" name
8580         | name, FOptPercent -> pr "  %s : float option;\n" name
8581       ) cols;
8582       pr "}\n";
8583       pr "\n"
8584   ) structs
8585
8586 and generate_ocaml_prototype ?(is_external = false) name style =
8587   if is_external then pr "external " else pr "val ";
8588   pr "%s : t -> " name;
8589   List.iter (
8590     function
8591     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8592     | BufferIn _ -> pr "string -> "
8593     | OptString _ -> pr "string option -> "
8594     | StringList _ | DeviceList _ -> pr "string array -> "
8595     | Bool _ -> pr "bool -> "
8596     | Int _ -> pr "int -> "
8597     | Int64 _ -> pr "int64 -> "
8598   ) (snd style);
8599   (match fst style with
8600    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8601    | RInt _ -> pr "int"
8602    | RInt64 _ -> pr "int64"
8603    | RBool _ -> pr "bool"
8604    | RConstString _ -> pr "string"
8605    | RConstOptString _ -> pr "string option"
8606    | RString _ | RBufferOut _ -> pr "string"
8607    | RStringList _ -> pr "string array"
8608    | RStruct (_, typ) -> pr "%s" typ
8609    | RStructList (_, typ) -> pr "%s array" typ
8610    | RHashtable _ -> pr "(string * string) list"
8611   );
8612   if is_external then (
8613     pr " = ";
8614     if List.length (snd style) + 1 > 5 then
8615       pr "\"ocaml_guestfs_%s_byte\" " name;
8616     pr "\"ocaml_guestfs_%s\"" name
8617   );
8618   pr "\n"
8619
8620 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8621 and generate_perl_xs () =
8622   generate_header CStyle LGPLv2plus;
8623
8624   pr "\
8625 #include \"EXTERN.h\"
8626 #include \"perl.h\"
8627 #include \"XSUB.h\"
8628
8629 #include <guestfs.h>
8630
8631 #ifndef PRId64
8632 #define PRId64 \"lld\"
8633 #endif
8634
8635 static SV *
8636 my_newSVll(long long val) {
8637 #ifdef USE_64_BIT_ALL
8638   return newSViv(val);
8639 #else
8640   char buf[100];
8641   int len;
8642   len = snprintf(buf, 100, \"%%\" PRId64, val);
8643   return newSVpv(buf, len);
8644 #endif
8645 }
8646
8647 #ifndef PRIu64
8648 #define PRIu64 \"llu\"
8649 #endif
8650
8651 static SV *
8652 my_newSVull(unsigned long long val) {
8653 #ifdef USE_64_BIT_ALL
8654   return newSVuv(val);
8655 #else
8656   char buf[100];
8657   int len;
8658   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8659   return newSVpv(buf, len);
8660 #endif
8661 }
8662
8663 /* http://www.perlmonks.org/?node_id=680842 */
8664 static char **
8665 XS_unpack_charPtrPtr (SV *arg) {
8666   char **ret;
8667   AV *av;
8668   I32 i;
8669
8670   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8671     croak (\"array reference expected\");
8672
8673   av = (AV *)SvRV (arg);
8674   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8675   if (!ret)
8676     croak (\"malloc failed\");
8677
8678   for (i = 0; i <= av_len (av); i++) {
8679     SV **elem = av_fetch (av, i, 0);
8680
8681     if (!elem || !*elem)
8682       croak (\"missing element in list\");
8683
8684     ret[i] = SvPV_nolen (*elem);
8685   }
8686
8687   ret[i] = NULL;
8688
8689   return ret;
8690 }
8691
8692 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8693
8694 PROTOTYPES: ENABLE
8695
8696 guestfs_h *
8697 _create ()
8698    CODE:
8699       RETVAL = guestfs_create ();
8700       if (!RETVAL)
8701         croak (\"could not create guestfs handle\");
8702       guestfs_set_error_handler (RETVAL, NULL, NULL);
8703  OUTPUT:
8704       RETVAL
8705
8706 void
8707 DESTROY (g)
8708       guestfs_h *g;
8709  PPCODE:
8710       guestfs_close (g);
8711
8712 ";
8713
8714   List.iter (
8715     fun (name, style, _, _, _, _, _) ->
8716       (match fst style with
8717        | RErr -> pr "void\n"
8718        | RInt _ -> pr "SV *\n"
8719        | RInt64 _ -> pr "SV *\n"
8720        | RBool _ -> pr "SV *\n"
8721        | RConstString _ -> pr "SV *\n"
8722        | RConstOptString _ -> pr "SV *\n"
8723        | RString _ -> pr "SV *\n"
8724        | RBufferOut _ -> pr "SV *\n"
8725        | RStringList _
8726        | RStruct _ | RStructList _
8727        | RHashtable _ ->
8728            pr "void\n" (* all lists returned implictly on the stack *)
8729       );
8730       (* Call and arguments. *)
8731       pr "%s (g" name;
8732       List.iter (
8733         fun arg -> pr ", %s" (name_of_argt arg)
8734       ) (snd style);
8735       pr ")\n";
8736       pr "      guestfs_h *g;\n";
8737       iteri (
8738         fun i ->
8739           function
8740           | Pathname n | Device n | Dev_or_Path n | String n
8741           | FileIn n | FileOut n ->
8742               pr "      char *%s;\n" n
8743           | BufferIn n ->
8744               pr "      char *%s;\n" n;
8745               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8746           | OptString n ->
8747               (* http://www.perlmonks.org/?node_id=554277
8748                * Note that the implicit handle argument means we have
8749                * to add 1 to the ST(x) operator.
8750                *)
8751               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8752           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8753           | Bool n -> pr "      int %s;\n" n
8754           | Int n -> pr "      int %s;\n" n
8755           | Int64 n -> pr "      int64_t %s;\n" n
8756       ) (snd style);
8757
8758       let do_cleanups () =
8759         List.iter (
8760           function
8761           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8762           | Bool _ | Int _ | Int64 _
8763           | FileIn _ | FileOut _
8764           | BufferIn _ -> ()
8765           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8766         ) (snd style)
8767       in
8768
8769       (* Code. *)
8770       (match fst style with
8771        | RErr ->
8772            pr "PREINIT:\n";
8773            pr "      int r;\n";
8774            pr " PPCODE:\n";
8775            pr "      r = guestfs_%s " name;
8776            generate_c_call_args ~handle:"g" style;
8777            pr ";\n";
8778            do_cleanups ();
8779            pr "      if (r == -1)\n";
8780            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8781        | RInt n
8782        | RBool n ->
8783            pr "PREINIT:\n";
8784            pr "      int %s;\n" n;
8785            pr "   CODE:\n";
8786            pr "      %s = guestfs_%s " n name;
8787            generate_c_call_args ~handle:"g" style;
8788            pr ";\n";
8789            do_cleanups ();
8790            pr "      if (%s == -1)\n" n;
8791            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8792            pr "      RETVAL = newSViv (%s);\n" n;
8793            pr " OUTPUT:\n";
8794            pr "      RETVAL\n"
8795        | RInt64 n ->
8796            pr "PREINIT:\n";
8797            pr "      int64_t %s;\n" n;
8798            pr "   CODE:\n";
8799            pr "      %s = guestfs_%s " n name;
8800            generate_c_call_args ~handle:"g" style;
8801            pr ";\n";
8802            do_cleanups ();
8803            pr "      if (%s == -1)\n" n;
8804            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8805            pr "      RETVAL = my_newSVll (%s);\n" n;
8806            pr " OUTPUT:\n";
8807            pr "      RETVAL\n"
8808        | RConstString n ->
8809            pr "PREINIT:\n";
8810            pr "      const char *%s;\n" n;
8811            pr "   CODE:\n";
8812            pr "      %s = guestfs_%s " n name;
8813            generate_c_call_args ~handle:"g" style;
8814            pr ";\n";
8815            do_cleanups ();
8816            pr "      if (%s == NULL)\n" n;
8817            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8818            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8819            pr " OUTPUT:\n";
8820            pr "      RETVAL\n"
8821        | RConstOptString n ->
8822            pr "PREINIT:\n";
8823            pr "      const char *%s;\n" n;
8824            pr "   CODE:\n";
8825            pr "      %s = guestfs_%s " n name;
8826            generate_c_call_args ~handle:"g" style;
8827            pr ";\n";
8828            do_cleanups ();
8829            pr "      if (%s == NULL)\n" n;
8830            pr "        RETVAL = &PL_sv_undef;\n";
8831            pr "      else\n";
8832            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8833            pr " OUTPUT:\n";
8834            pr "      RETVAL\n"
8835        | RString n ->
8836            pr "PREINIT:\n";
8837            pr "      char *%s;\n" n;
8838            pr "   CODE:\n";
8839            pr "      %s = guestfs_%s " n name;
8840            generate_c_call_args ~handle:"g" style;
8841            pr ";\n";
8842            do_cleanups ();
8843            pr "      if (%s == NULL)\n" n;
8844            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8845            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8846            pr "      free (%s);\n" n;
8847            pr " OUTPUT:\n";
8848            pr "      RETVAL\n"
8849        | RStringList n | RHashtable n ->
8850            pr "PREINIT:\n";
8851            pr "      char **%s;\n" n;
8852            pr "      int i, n;\n";
8853            pr " PPCODE:\n";
8854            pr "      %s = guestfs_%s " n name;
8855            generate_c_call_args ~handle:"g" style;
8856            pr ";\n";
8857            do_cleanups ();
8858            pr "      if (%s == NULL)\n" n;
8859            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8860            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8861            pr "      EXTEND (SP, n);\n";
8862            pr "      for (i = 0; i < n; ++i) {\n";
8863            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8864            pr "        free (%s[i]);\n" n;
8865            pr "      }\n";
8866            pr "      free (%s);\n" n;
8867        | RStruct (n, typ) ->
8868            let cols = cols_of_struct typ in
8869            generate_perl_struct_code typ cols name style n do_cleanups
8870        | RStructList (n, typ) ->
8871            let cols = cols_of_struct typ in
8872            generate_perl_struct_list_code typ cols name style n do_cleanups
8873        | RBufferOut n ->
8874            pr "PREINIT:\n";
8875            pr "      char *%s;\n" n;
8876            pr "      size_t size;\n";
8877            pr "   CODE:\n";
8878            pr "      %s = guestfs_%s " n name;
8879            generate_c_call_args ~handle:"g" style;
8880            pr ";\n";
8881            do_cleanups ();
8882            pr "      if (%s == NULL)\n" n;
8883            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8884            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8885            pr "      free (%s);\n" n;
8886            pr " OUTPUT:\n";
8887            pr "      RETVAL\n"
8888       );
8889
8890       pr "\n"
8891   ) all_functions
8892
8893 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8894   pr "PREINIT:\n";
8895   pr "      struct guestfs_%s_list *%s;\n" typ n;
8896   pr "      int i;\n";
8897   pr "      HV *hv;\n";
8898   pr " PPCODE:\n";
8899   pr "      %s = guestfs_%s " n name;
8900   generate_c_call_args ~handle:"g" style;
8901   pr ";\n";
8902   do_cleanups ();
8903   pr "      if (%s == NULL)\n" n;
8904   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8905   pr "      EXTEND (SP, %s->len);\n" n;
8906   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8907   pr "        hv = newHV ();\n";
8908   List.iter (
8909     function
8910     | name, FString ->
8911         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8912           name (String.length name) n name
8913     | name, FUUID ->
8914         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8915           name (String.length name) n name
8916     | name, FBuffer ->
8917         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8918           name (String.length name) n name n name
8919     | name, (FBytes|FUInt64) ->
8920         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8921           name (String.length name) n name
8922     | name, FInt64 ->
8923         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8924           name (String.length name) n name
8925     | name, (FInt32|FUInt32) ->
8926         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8927           name (String.length name) n name
8928     | name, FChar ->
8929         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8930           name (String.length name) n name
8931     | name, FOptPercent ->
8932         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8933           name (String.length name) n name
8934   ) cols;
8935   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8936   pr "      }\n";
8937   pr "      guestfs_free_%s_list (%s);\n" typ n
8938
8939 and generate_perl_struct_code typ cols name style n do_cleanups =
8940   pr "PREINIT:\n";
8941   pr "      struct guestfs_%s *%s;\n" typ n;
8942   pr " PPCODE:\n";
8943   pr "      %s = guestfs_%s " n name;
8944   generate_c_call_args ~handle:"g" style;
8945   pr ";\n";
8946   do_cleanups ();
8947   pr "      if (%s == NULL)\n" n;
8948   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8949   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8950   List.iter (
8951     fun ((name, _) as col) ->
8952       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8953
8954       match col with
8955       | name, FString ->
8956           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8957             n name
8958       | name, FBuffer ->
8959           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8960             n name n name
8961       | name, FUUID ->
8962           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8963             n name
8964       | name, (FBytes|FUInt64) ->
8965           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8966             n name
8967       | name, FInt64 ->
8968           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8969             n name
8970       | name, (FInt32|FUInt32) ->
8971           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8972             n name
8973       | name, FChar ->
8974           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8975             n name
8976       | name, FOptPercent ->
8977           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8978             n name
8979   ) cols;
8980   pr "      free (%s);\n" n
8981
8982 (* Generate Sys/Guestfs.pm. *)
8983 and generate_perl_pm () =
8984   generate_header HashStyle LGPLv2plus;
8985
8986   pr "\
8987 =pod
8988
8989 =head1 NAME
8990
8991 Sys::Guestfs - Perl bindings for libguestfs
8992
8993 =head1 SYNOPSIS
8994
8995  use Sys::Guestfs;
8996
8997  my $h = Sys::Guestfs->new ();
8998  $h->add_drive ('guest.img');
8999  $h->launch ();
9000  $h->mount ('/dev/sda1', '/');
9001  $h->touch ('/hello');
9002  $h->sync ();
9003
9004 =head1 DESCRIPTION
9005
9006 The C<Sys::Guestfs> module provides a Perl XS binding to the
9007 libguestfs API for examining and modifying virtual machine
9008 disk images.
9009
9010 Amongst the things this is good for: making batch configuration
9011 changes to guests, getting disk used/free statistics (see also:
9012 virt-df), migrating between virtualization systems (see also:
9013 virt-p2v), performing partial backups, performing partial guest
9014 clones, cloning guests and changing registry/UUID/hostname info, and
9015 much else besides.
9016
9017 Libguestfs uses Linux kernel and qemu code, and can access any type of
9018 guest filesystem that Linux and qemu can, including but not limited
9019 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9020 schemes, qcow, qcow2, vmdk.
9021
9022 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9023 LVs, what filesystem is in each LV, etc.).  It can also run commands
9024 in the context of the guest.  Also you can access filesystems over
9025 FUSE.
9026
9027 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9028 functions for using libguestfs from Perl, including integration
9029 with libvirt.
9030
9031 =head1 ERRORS
9032
9033 All errors turn into calls to C<croak> (see L<Carp(3)>).
9034
9035 =head1 METHODS
9036
9037 =over 4
9038
9039 =cut
9040
9041 package Sys::Guestfs;
9042
9043 use strict;
9044 use warnings;
9045
9046 # This version number changes whenever a new function
9047 # is added to the libguestfs API.  It is not directly
9048 # related to the libguestfs version number.
9049 use vars qw($VERSION);
9050 $VERSION = '0.%d';
9051
9052 require XSLoader;
9053 XSLoader::load ('Sys::Guestfs');
9054
9055 =item $h = Sys::Guestfs->new ();
9056
9057 Create a new guestfs handle.
9058
9059 =cut
9060
9061 sub new {
9062   my $proto = shift;
9063   my $class = ref ($proto) || $proto;
9064
9065   my $self = Sys::Guestfs::_create ();
9066   bless $self, $class;
9067   return $self;
9068 }
9069
9070 " max_proc_nr;
9071
9072   (* Actions.  We only need to print documentation for these as
9073    * they are pulled in from the XS code automatically.
9074    *)
9075   List.iter (
9076     fun (name, style, _, flags, _, _, longdesc) ->
9077       if not (List.mem NotInDocs flags) then (
9078         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9079         pr "=item ";
9080         generate_perl_prototype name style;
9081         pr "\n\n";
9082         pr "%s\n\n" longdesc;
9083         if List.mem ProtocolLimitWarning flags then
9084           pr "%s\n\n" protocol_limit_warning;
9085         if List.mem DangerWillRobinson flags then
9086           pr "%s\n\n" danger_will_robinson;
9087         match deprecation_notice flags with
9088         | None -> ()
9089         | Some txt -> pr "%s\n\n" txt
9090       )
9091   ) all_functions_sorted;
9092
9093   (* End of file. *)
9094   pr "\
9095 =cut
9096
9097 1;
9098
9099 =back
9100
9101 =head1 COPYRIGHT
9102
9103 Copyright (C) %s Red Hat Inc.
9104
9105 =head1 LICENSE
9106
9107 Please see the file COPYING.LIB for the full license.
9108
9109 =head1 SEE ALSO
9110
9111 L<guestfs(3)>,
9112 L<guestfish(1)>,
9113 L<http://libguestfs.org>,
9114 L<Sys::Guestfs::Lib(3)>.
9115
9116 =cut
9117 " copyright_years
9118
9119 and generate_perl_prototype name style =
9120   (match fst style with
9121    | RErr -> ()
9122    | RBool n
9123    | RInt n
9124    | RInt64 n
9125    | RConstString n
9126    | RConstOptString n
9127    | RString n
9128    | RBufferOut n -> pr "$%s = " n
9129    | RStruct (n,_)
9130    | RHashtable n -> pr "%%%s = " n
9131    | RStringList n
9132    | RStructList (n,_) -> pr "@%s = " n
9133   );
9134   pr "$h->%s (" name;
9135   let comma = ref false in
9136   List.iter (
9137     fun arg ->
9138       if !comma then pr ", ";
9139       comma := true;
9140       match arg with
9141       | Pathname n | Device n | Dev_or_Path n | String n
9142       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9143       | BufferIn n ->
9144           pr "$%s" n
9145       | StringList n | DeviceList n ->
9146           pr "\\@%s" n
9147   ) (snd style);
9148   pr ");"
9149
9150 (* Generate Python C module. *)
9151 and generate_python_c () =
9152   generate_header CStyle LGPLv2plus;
9153
9154   pr "\
9155 #define PY_SSIZE_T_CLEAN 1
9156 #include <Python.h>
9157
9158 #if PY_VERSION_HEX < 0x02050000
9159 typedef int Py_ssize_t;
9160 #define PY_SSIZE_T_MAX INT_MAX
9161 #define PY_SSIZE_T_MIN INT_MIN
9162 #endif
9163
9164 #include <stdio.h>
9165 #include <stdlib.h>
9166 #include <assert.h>
9167
9168 #include \"guestfs.h\"
9169
9170 typedef struct {
9171   PyObject_HEAD
9172   guestfs_h *g;
9173 } Pyguestfs_Object;
9174
9175 static guestfs_h *
9176 get_handle (PyObject *obj)
9177 {
9178   assert (obj);
9179   assert (obj != Py_None);
9180   return ((Pyguestfs_Object *) obj)->g;
9181 }
9182
9183 static PyObject *
9184 put_handle (guestfs_h *g)
9185 {
9186   assert (g);
9187   return
9188     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9189 }
9190
9191 /* This list should be freed (but not the strings) after use. */
9192 static char **
9193 get_string_list (PyObject *obj)
9194 {
9195   int i, len;
9196   char **r;
9197
9198   assert (obj);
9199
9200   if (!PyList_Check (obj)) {
9201     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9202     return NULL;
9203   }
9204
9205   len = PyList_Size (obj);
9206   r = malloc (sizeof (char *) * (len+1));
9207   if (r == NULL) {
9208     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9209     return NULL;
9210   }
9211
9212   for (i = 0; i < len; ++i)
9213     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9214   r[len] = NULL;
9215
9216   return r;
9217 }
9218
9219 static PyObject *
9220 put_string_list (char * const * const argv)
9221 {
9222   PyObject *list;
9223   int argc, i;
9224
9225   for (argc = 0; argv[argc] != NULL; ++argc)
9226     ;
9227
9228   list = PyList_New (argc);
9229   for (i = 0; i < argc; ++i)
9230     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9231
9232   return list;
9233 }
9234
9235 static PyObject *
9236 put_table (char * const * const argv)
9237 {
9238   PyObject *list, *item;
9239   int argc, i;
9240
9241   for (argc = 0; argv[argc] != NULL; ++argc)
9242     ;
9243
9244   list = PyList_New (argc >> 1);
9245   for (i = 0; i < argc; i += 2) {
9246     item = PyTuple_New (2);
9247     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9248     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9249     PyList_SetItem (list, i >> 1, item);
9250   }
9251
9252   return list;
9253 }
9254
9255 static void
9256 free_strings (char **argv)
9257 {
9258   int argc;
9259
9260   for (argc = 0; argv[argc] != NULL; ++argc)
9261     free (argv[argc]);
9262   free (argv);
9263 }
9264
9265 static PyObject *
9266 py_guestfs_create (PyObject *self, PyObject *args)
9267 {
9268   guestfs_h *g;
9269
9270   g = guestfs_create ();
9271   if (g == NULL) {
9272     PyErr_SetString (PyExc_RuntimeError,
9273                      \"guestfs.create: failed to allocate handle\");
9274     return NULL;
9275   }
9276   guestfs_set_error_handler (g, NULL, NULL);
9277   return put_handle (g);
9278 }
9279
9280 static PyObject *
9281 py_guestfs_close (PyObject *self, PyObject *args)
9282 {
9283   PyObject *py_g;
9284   guestfs_h *g;
9285
9286   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9287     return NULL;
9288   g = get_handle (py_g);
9289
9290   guestfs_close (g);
9291
9292   Py_INCREF (Py_None);
9293   return Py_None;
9294 }
9295
9296 ";
9297
9298   let emit_put_list_function typ =
9299     pr "static PyObject *\n";
9300     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9301     pr "{\n";
9302     pr "  PyObject *list;\n";
9303     pr "  int i;\n";
9304     pr "\n";
9305     pr "  list = PyList_New (%ss->len);\n" typ;
9306     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9307     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9308     pr "  return list;\n";
9309     pr "};\n";
9310     pr "\n"
9311   in
9312
9313   (* Structures, turned into Python dictionaries. *)
9314   List.iter (
9315     fun (typ, cols) ->
9316       pr "static PyObject *\n";
9317       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9318       pr "{\n";
9319       pr "  PyObject *dict;\n";
9320       pr "\n";
9321       pr "  dict = PyDict_New ();\n";
9322       List.iter (
9323         function
9324         | name, FString ->
9325             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9326             pr "                        PyString_FromString (%s->%s));\n"
9327               typ name
9328         | name, FBuffer ->
9329             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9330             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9331               typ name typ name
9332         | name, FUUID ->
9333             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9334             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9335               typ name
9336         | name, (FBytes|FUInt64) ->
9337             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9338             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9339               typ name
9340         | name, FInt64 ->
9341             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9342             pr "                        PyLong_FromLongLong (%s->%s));\n"
9343               typ name
9344         | name, FUInt32 ->
9345             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9346             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9347               typ name
9348         | name, FInt32 ->
9349             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9350             pr "                        PyLong_FromLong (%s->%s));\n"
9351               typ name
9352         | name, FOptPercent ->
9353             pr "  if (%s->%s >= 0)\n" typ name;
9354             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9355             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9356               typ name;
9357             pr "  else {\n";
9358             pr "    Py_INCREF (Py_None);\n";
9359             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9360             pr "  }\n"
9361         | name, FChar ->
9362             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9363             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9364       ) cols;
9365       pr "  return dict;\n";
9366       pr "};\n";
9367       pr "\n";
9368
9369   ) structs;
9370
9371   (* Emit a put_TYPE_list function definition only if that function is used. *)
9372   List.iter (
9373     function
9374     | typ, (RStructListOnly | RStructAndList) ->
9375         (* generate the function for typ *)
9376         emit_put_list_function typ
9377     | typ, _ -> () (* empty *)
9378   ) (rstructs_used_by all_functions);
9379
9380   (* Python wrapper functions. *)
9381   List.iter (
9382     fun (name, style, _, _, _, _, _) ->
9383       pr "static PyObject *\n";
9384       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9385       pr "{\n";
9386
9387       pr "  PyObject *py_g;\n";
9388       pr "  guestfs_h *g;\n";
9389       pr "  PyObject *py_r;\n";
9390
9391       let error_code =
9392         match fst style with
9393         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9394         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9395         | RConstString _ | RConstOptString _ ->
9396             pr "  const char *r;\n"; "NULL"
9397         | RString _ -> pr "  char *r;\n"; "NULL"
9398         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9399         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9400         | RStructList (_, typ) ->
9401             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9402         | RBufferOut _ ->
9403             pr "  char *r;\n";
9404             pr "  size_t size;\n";
9405             "NULL" in
9406
9407       List.iter (
9408         function
9409         | Pathname n | Device n | Dev_or_Path n | String n
9410         | FileIn n | FileOut n ->
9411             pr "  const char *%s;\n" n
9412         | OptString n -> pr "  const char *%s;\n" n
9413         | BufferIn n ->
9414             pr "  const char *%s;\n" n;
9415             pr "  Py_ssize_t %s_size;\n" n
9416         | StringList n | DeviceList n ->
9417             pr "  PyObject *py_%s;\n" n;
9418             pr "  char **%s;\n" n
9419         | Bool n -> pr "  int %s;\n" n
9420         | Int n -> pr "  int %s;\n" n
9421         | Int64 n -> pr "  long long %s;\n" n
9422       ) (snd style);
9423
9424       pr "\n";
9425
9426       (* Convert the parameters. *)
9427       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9428       List.iter (
9429         function
9430         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9431         | OptString _ -> pr "z"
9432         | StringList _ | DeviceList _ -> pr "O"
9433         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9434         | Int _ -> pr "i"
9435         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9436                              * emulate C's int/long/long long in Python?
9437                              *)
9438         | BufferIn _ -> pr "s#"
9439       ) (snd style);
9440       pr ":guestfs_%s\",\n" name;
9441       pr "                         &py_g";
9442       List.iter (
9443         function
9444         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9445         | OptString n -> pr ", &%s" n
9446         | StringList n | DeviceList n -> pr ", &py_%s" n
9447         | Bool n -> pr ", &%s" n
9448         | Int n -> pr ", &%s" n
9449         | Int64 n -> pr ", &%s" n
9450         | BufferIn n -> pr ", &%s, &%s_size" n n
9451       ) (snd style);
9452
9453       pr "))\n";
9454       pr "    return NULL;\n";
9455
9456       pr "  g = get_handle (py_g);\n";
9457       List.iter (
9458         function
9459         | Pathname _ | Device _ | Dev_or_Path _ | String _
9460         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9461         | BufferIn _ -> ()
9462         | StringList n | DeviceList n ->
9463             pr "  %s = get_string_list (py_%s);\n" n n;
9464             pr "  if (!%s) return NULL;\n" n
9465       ) (snd style);
9466
9467       pr "\n";
9468
9469       pr "  r = guestfs_%s " name;
9470       generate_c_call_args ~handle:"g" style;
9471       pr ";\n";
9472
9473       List.iter (
9474         function
9475         | Pathname _ | Device _ | Dev_or_Path _ | String _
9476         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9477         | BufferIn _ -> ()
9478         | StringList n | DeviceList n ->
9479             pr "  free (%s);\n" n
9480       ) (snd style);
9481
9482       pr "  if (r == %s) {\n" error_code;
9483       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9484       pr "    return NULL;\n";
9485       pr "  }\n";
9486       pr "\n";
9487
9488       (match fst style with
9489        | RErr ->
9490            pr "  Py_INCREF (Py_None);\n";
9491            pr "  py_r = Py_None;\n"
9492        | RInt _
9493        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9494        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9495        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9496        | RConstOptString _ ->
9497            pr "  if (r)\n";
9498            pr "    py_r = PyString_FromString (r);\n";
9499            pr "  else {\n";
9500            pr "    Py_INCREF (Py_None);\n";
9501            pr "    py_r = Py_None;\n";
9502            pr "  }\n"
9503        | RString _ ->
9504            pr "  py_r = PyString_FromString (r);\n";
9505            pr "  free (r);\n"
9506        | RStringList _ ->
9507            pr "  py_r = put_string_list (r);\n";
9508            pr "  free_strings (r);\n"
9509        | RStruct (_, typ) ->
9510            pr "  py_r = put_%s (r);\n" typ;
9511            pr "  guestfs_free_%s (r);\n" typ
9512        | RStructList (_, typ) ->
9513            pr "  py_r = put_%s_list (r);\n" typ;
9514            pr "  guestfs_free_%s_list (r);\n" typ
9515        | RHashtable n ->
9516            pr "  py_r = put_table (r);\n";
9517            pr "  free_strings (r);\n"
9518        | RBufferOut _ ->
9519            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9520            pr "  free (r);\n"
9521       );
9522
9523       pr "  return py_r;\n";
9524       pr "}\n";
9525       pr "\n"
9526   ) all_functions;
9527
9528   (* Table of functions. *)
9529   pr "static PyMethodDef methods[] = {\n";
9530   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9531   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9532   List.iter (
9533     fun (name, _, _, _, _, _, _) ->
9534       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9535         name name
9536   ) all_functions;
9537   pr "  { NULL, NULL, 0, NULL }\n";
9538   pr "};\n";
9539   pr "\n";
9540
9541   (* Init function. *)
9542   pr "\
9543 void
9544 initlibguestfsmod (void)
9545 {
9546   static int initialized = 0;
9547
9548   if (initialized) return;
9549   Py_InitModule ((char *) \"libguestfsmod\", methods);
9550   initialized = 1;
9551 }
9552 "
9553
9554 (* Generate Python module. *)
9555 and generate_python_py () =
9556   generate_header HashStyle LGPLv2plus;
9557
9558   pr "\
9559 u\"\"\"Python bindings for libguestfs
9560
9561 import guestfs
9562 g = guestfs.GuestFS ()
9563 g.add_drive (\"guest.img\")
9564 g.launch ()
9565 parts = g.list_partitions ()
9566
9567 The guestfs module provides a Python binding to the libguestfs API
9568 for examining and modifying virtual machine disk images.
9569
9570 Amongst the things this is good for: making batch configuration
9571 changes to guests, getting disk used/free statistics (see also:
9572 virt-df), migrating between virtualization systems (see also:
9573 virt-p2v), performing partial backups, performing partial guest
9574 clones, cloning guests and changing registry/UUID/hostname info, and
9575 much else besides.
9576
9577 Libguestfs uses Linux kernel and qemu code, and can access any type of
9578 guest filesystem that Linux and qemu can, including but not limited
9579 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9580 schemes, qcow, qcow2, vmdk.
9581
9582 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9583 LVs, what filesystem is in each LV, etc.).  It can also run commands
9584 in the context of the guest.  Also you can access filesystems over
9585 FUSE.
9586
9587 Errors which happen while using the API are turned into Python
9588 RuntimeError exceptions.
9589
9590 To create a guestfs handle you usually have to perform the following
9591 sequence of calls:
9592
9593 # Create the handle, call add_drive at least once, and possibly
9594 # several times if the guest has multiple block devices:
9595 g = guestfs.GuestFS ()
9596 g.add_drive (\"guest.img\")
9597
9598 # Launch the qemu subprocess and wait for it to become ready:
9599 g.launch ()
9600
9601 # Now you can issue commands, for example:
9602 logvols = g.lvs ()
9603
9604 \"\"\"
9605
9606 import libguestfsmod
9607
9608 class GuestFS:
9609     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9610
9611     def __init__ (self):
9612         \"\"\"Create a new libguestfs handle.\"\"\"
9613         self._o = libguestfsmod.create ()
9614
9615     def __del__ (self):
9616         libguestfsmod.close (self._o)
9617
9618 ";
9619
9620   List.iter (
9621     fun (name, style, _, flags, _, _, longdesc) ->
9622       pr "    def %s " name;
9623       generate_py_call_args ~handle:"self" (snd style);
9624       pr ":\n";
9625
9626       if not (List.mem NotInDocs flags) then (
9627         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9628         let doc =
9629           match fst style with
9630           | RErr | RInt _ | RInt64 _ | RBool _
9631           | RConstOptString _ | RConstString _
9632           | RString _ | RBufferOut _ -> doc
9633           | RStringList _ ->
9634               doc ^ "\n\nThis function returns a list of strings."
9635           | RStruct (_, typ) ->
9636               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9637           | RStructList (_, typ) ->
9638               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9639           | RHashtable _ ->
9640               doc ^ "\n\nThis function returns a dictionary." in
9641         let doc =
9642           if List.mem ProtocolLimitWarning flags then
9643             doc ^ "\n\n" ^ protocol_limit_warning
9644           else doc in
9645         let doc =
9646           if List.mem DangerWillRobinson flags then
9647             doc ^ "\n\n" ^ danger_will_robinson
9648           else doc in
9649         let doc =
9650           match deprecation_notice flags with
9651           | None -> doc
9652           | Some txt -> doc ^ "\n\n" ^ txt in
9653         let doc = pod2text ~width:60 name doc in
9654         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9655         let doc = String.concat "\n        " doc in
9656         pr "        u\"\"\"%s\"\"\"\n" doc;
9657       );
9658       pr "        return libguestfsmod.%s " name;
9659       generate_py_call_args ~handle:"self._o" (snd style);
9660       pr "\n";
9661       pr "\n";
9662   ) all_functions
9663
9664 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9665 and generate_py_call_args ~handle args =
9666   pr "(%s" handle;
9667   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9668   pr ")"
9669
9670 (* Useful if you need the longdesc POD text as plain text.  Returns a
9671  * list of lines.
9672  *
9673  * Because this is very slow (the slowest part of autogeneration),
9674  * we memoize the results.
9675  *)
9676 and pod2text ~width name longdesc =
9677   let key = width, name, longdesc in
9678   try Hashtbl.find pod2text_memo key
9679   with Not_found ->
9680     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9681     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9682     close_out chan;
9683     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9684     let chan = open_process_in cmd in
9685     let lines = ref [] in
9686     let rec loop i =
9687       let line = input_line chan in
9688       if i = 1 then             (* discard the first line of output *)
9689         loop (i+1)
9690       else (
9691         let line = triml line in
9692         lines := line :: !lines;
9693         loop (i+1)
9694       ) in
9695     let lines = try loop 1 with End_of_file -> List.rev !lines in
9696     unlink filename;
9697     (match close_process_in chan with
9698      | WEXITED 0 -> ()
9699      | WEXITED i ->
9700          failwithf "pod2text: process exited with non-zero status (%d)" i
9701      | WSIGNALED i | WSTOPPED i ->
9702          failwithf "pod2text: process signalled or stopped by signal %d" i
9703     );
9704     Hashtbl.add pod2text_memo key lines;
9705     pod2text_memo_updated ();
9706     lines
9707
9708 (* Generate ruby bindings. *)
9709 and generate_ruby_c () =
9710   generate_header CStyle LGPLv2plus;
9711
9712   pr "\
9713 #include <stdio.h>
9714 #include <stdlib.h>
9715
9716 #include <ruby.h>
9717
9718 #include \"guestfs.h\"
9719
9720 #include \"extconf.h\"
9721
9722 /* For Ruby < 1.9 */
9723 #ifndef RARRAY_LEN
9724 #define RARRAY_LEN(r) (RARRAY((r))->len)
9725 #endif
9726
9727 static VALUE m_guestfs;                 /* guestfs module */
9728 static VALUE c_guestfs;                 /* guestfs_h handle */
9729 static VALUE e_Error;                   /* used for all errors */
9730
9731 static void ruby_guestfs_free (void *p)
9732 {
9733   if (!p) return;
9734   guestfs_close ((guestfs_h *) p);
9735 }
9736
9737 static VALUE ruby_guestfs_create (VALUE m)
9738 {
9739   guestfs_h *g;
9740
9741   g = guestfs_create ();
9742   if (!g)
9743     rb_raise (e_Error, \"failed to create guestfs handle\");
9744
9745   /* Don't print error messages to stderr by default. */
9746   guestfs_set_error_handler (g, NULL, NULL);
9747
9748   /* Wrap it, and make sure the close function is called when the
9749    * handle goes away.
9750    */
9751   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9752 }
9753
9754 static VALUE ruby_guestfs_close (VALUE gv)
9755 {
9756   guestfs_h *g;
9757   Data_Get_Struct (gv, guestfs_h, g);
9758
9759   ruby_guestfs_free (g);
9760   DATA_PTR (gv) = NULL;
9761
9762   return Qnil;
9763 }
9764
9765 ";
9766
9767   List.iter (
9768     fun (name, style, _, _, _, _, _) ->
9769       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9770       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9771       pr ")\n";
9772       pr "{\n";
9773       pr "  guestfs_h *g;\n";
9774       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9775       pr "  if (!g)\n";
9776       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9777         name;
9778       pr "\n";
9779
9780       List.iter (
9781         function
9782         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9783             pr "  Check_Type (%sv, T_STRING);\n" n;
9784             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9785             pr "  if (!%s)\n" n;
9786             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9787             pr "              \"%s\", \"%s\");\n" n name
9788         | BufferIn n ->
9789             pr "  Check_Type (%sv, T_STRING);\n" n;
9790             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9791             pr "  if (!%s)\n" n;
9792             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9793             pr "              \"%s\", \"%s\");\n" n name;
9794             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9795         | OptString n ->
9796             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9797         | StringList n | DeviceList n ->
9798             pr "  char **%s;\n" n;
9799             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9800             pr "  {\n";
9801             pr "    int i, len;\n";
9802             pr "    len = RARRAY_LEN (%sv);\n" n;
9803             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9804               n;
9805             pr "    for (i = 0; i < len; ++i) {\n";
9806             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9807             pr "      %s[i] = StringValueCStr (v);\n" n;
9808             pr "    }\n";
9809             pr "    %s[len] = NULL;\n" n;
9810             pr "  }\n";
9811         | Bool n ->
9812             pr "  int %s = RTEST (%sv);\n" n n
9813         | Int n ->
9814             pr "  int %s = NUM2INT (%sv);\n" n n
9815         | Int64 n ->
9816             pr "  long long %s = NUM2LL (%sv);\n" n n
9817       ) (snd style);
9818       pr "\n";
9819
9820       let error_code =
9821         match fst style with
9822         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9823         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9824         | RConstString _ | RConstOptString _ ->
9825             pr "  const char *r;\n"; "NULL"
9826         | RString _ -> pr "  char *r;\n"; "NULL"
9827         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9828         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9829         | RStructList (_, typ) ->
9830             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9831         | RBufferOut _ ->
9832             pr "  char *r;\n";
9833             pr "  size_t size;\n";
9834             "NULL" in
9835       pr "\n";
9836
9837       pr "  r = guestfs_%s " name;
9838       generate_c_call_args ~handle:"g" style;
9839       pr ";\n";
9840
9841       List.iter (
9842         function
9843         | Pathname _ | Device _ | Dev_or_Path _ | String _
9844         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9845         | BufferIn _ -> ()
9846         | StringList n | DeviceList n ->
9847             pr "  free (%s);\n" n
9848       ) (snd style);
9849
9850       pr "  if (r == %s)\n" error_code;
9851       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9852       pr "\n";
9853
9854       (match fst style with
9855        | RErr ->
9856            pr "  return Qnil;\n"
9857        | RInt _ | RBool _ ->
9858            pr "  return INT2NUM (r);\n"
9859        | RInt64 _ ->
9860            pr "  return ULL2NUM (r);\n"
9861        | RConstString _ ->
9862            pr "  return rb_str_new2 (r);\n";
9863        | RConstOptString _ ->
9864            pr "  if (r)\n";
9865            pr "    return rb_str_new2 (r);\n";
9866            pr "  else\n";
9867            pr "    return Qnil;\n";
9868        | RString _ ->
9869            pr "  VALUE rv = rb_str_new2 (r);\n";
9870            pr "  free (r);\n";
9871            pr "  return rv;\n";
9872        | RStringList _ ->
9873            pr "  int i, len = 0;\n";
9874            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9875            pr "  VALUE rv = rb_ary_new2 (len);\n";
9876            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9877            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9878            pr "    free (r[i]);\n";
9879            pr "  }\n";
9880            pr "  free (r);\n";
9881            pr "  return rv;\n"
9882        | RStruct (_, typ) ->
9883            let cols = cols_of_struct typ in
9884            generate_ruby_struct_code typ cols
9885        | RStructList (_, typ) ->
9886            let cols = cols_of_struct typ in
9887            generate_ruby_struct_list_code typ cols
9888        | RHashtable _ ->
9889            pr "  VALUE rv = rb_hash_new ();\n";
9890            pr "  int i;\n";
9891            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9892            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9893            pr "    free (r[i]);\n";
9894            pr "    free (r[i+1]);\n";
9895            pr "  }\n";
9896            pr "  free (r);\n";
9897            pr "  return rv;\n"
9898        | RBufferOut _ ->
9899            pr "  VALUE rv = rb_str_new (r, size);\n";
9900            pr "  free (r);\n";
9901            pr "  return rv;\n";
9902       );
9903
9904       pr "}\n";
9905       pr "\n"
9906   ) all_functions;
9907
9908   pr "\
9909 /* Initialize the module. */
9910 void Init__guestfs ()
9911 {
9912   m_guestfs = rb_define_module (\"Guestfs\");
9913   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9914   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9915
9916   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9917   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9918
9919 ";
9920   (* Define the rest of the methods. *)
9921   List.iter (
9922     fun (name, style, _, _, _, _, _) ->
9923       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9924       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9925   ) all_functions;
9926
9927   pr "}\n"
9928
9929 (* Ruby code to return a struct. *)
9930 and generate_ruby_struct_code typ cols =
9931   pr "  VALUE rv = rb_hash_new ();\n";
9932   List.iter (
9933     function
9934     | name, FString ->
9935         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9936     | name, FBuffer ->
9937         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9938     | name, FUUID ->
9939         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9940     | name, (FBytes|FUInt64) ->
9941         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9942     | name, FInt64 ->
9943         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9944     | name, FUInt32 ->
9945         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9946     | name, FInt32 ->
9947         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9948     | name, FOptPercent ->
9949         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9950     | name, FChar -> (* XXX wrong? *)
9951         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9952   ) cols;
9953   pr "  guestfs_free_%s (r);\n" typ;
9954   pr "  return rv;\n"
9955
9956 (* Ruby code to return a struct list. *)
9957 and generate_ruby_struct_list_code typ cols =
9958   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9959   pr "  int i;\n";
9960   pr "  for (i = 0; i < r->len; ++i) {\n";
9961   pr "    VALUE hv = rb_hash_new ();\n";
9962   List.iter (
9963     function
9964     | name, FString ->
9965         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9966     | name, FBuffer ->
9967         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
9968     | name, FUUID ->
9969         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9970     | name, (FBytes|FUInt64) ->
9971         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9972     | name, FInt64 ->
9973         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9974     | name, FUInt32 ->
9975         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9976     | name, FInt32 ->
9977         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9978     | name, FOptPercent ->
9979         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9980     | name, FChar -> (* XXX wrong? *)
9981         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9982   ) cols;
9983   pr "    rb_ary_push (rv, hv);\n";
9984   pr "  }\n";
9985   pr "  guestfs_free_%s_list (r);\n" typ;
9986   pr "  return rv;\n"
9987
9988 (* Generate Java bindings GuestFS.java file. *)
9989 and generate_java_java () =
9990   generate_header CStyle LGPLv2plus;
9991
9992   pr "\
9993 package com.redhat.et.libguestfs;
9994
9995 import java.util.HashMap;
9996 import com.redhat.et.libguestfs.LibGuestFSException;
9997 import com.redhat.et.libguestfs.PV;
9998 import com.redhat.et.libguestfs.VG;
9999 import com.redhat.et.libguestfs.LV;
10000 import com.redhat.et.libguestfs.Stat;
10001 import com.redhat.et.libguestfs.StatVFS;
10002 import com.redhat.et.libguestfs.IntBool;
10003 import com.redhat.et.libguestfs.Dirent;
10004
10005 /**
10006  * The GuestFS object is a libguestfs handle.
10007  *
10008  * @author rjones
10009  */
10010 public class GuestFS {
10011   // Load the native code.
10012   static {
10013     System.loadLibrary (\"guestfs_jni\");
10014   }
10015
10016   /**
10017    * The native guestfs_h pointer.
10018    */
10019   long g;
10020
10021   /**
10022    * Create a libguestfs handle.
10023    *
10024    * @throws LibGuestFSException
10025    */
10026   public GuestFS () throws LibGuestFSException
10027   {
10028     g = _create ();
10029   }
10030   private native long _create () throws LibGuestFSException;
10031
10032   /**
10033    * Close a libguestfs handle.
10034    *
10035    * You can also leave handles to be collected by the garbage
10036    * collector, but this method ensures that the resources used
10037    * by the handle are freed up immediately.  If you call any
10038    * other methods after closing the handle, you will get an
10039    * exception.
10040    *
10041    * @throws LibGuestFSException
10042    */
10043   public void close () throws LibGuestFSException
10044   {
10045     if (g != 0)
10046       _close (g);
10047     g = 0;
10048   }
10049   private native void _close (long g) throws LibGuestFSException;
10050
10051   public void finalize () throws LibGuestFSException
10052   {
10053     close ();
10054   }
10055
10056 ";
10057
10058   List.iter (
10059     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10060       if not (List.mem NotInDocs flags); then (
10061         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10062         let doc =
10063           if List.mem ProtocolLimitWarning flags then
10064             doc ^ "\n\n" ^ protocol_limit_warning
10065           else doc in
10066         let doc =
10067           if List.mem DangerWillRobinson flags then
10068             doc ^ "\n\n" ^ danger_will_robinson
10069           else doc in
10070         let doc =
10071           match deprecation_notice flags with
10072           | None -> doc
10073           | Some txt -> doc ^ "\n\n" ^ txt in
10074         let doc = pod2text ~width:60 name doc in
10075         let doc = List.map (            (* RHBZ#501883 *)
10076           function
10077           | "" -> "<p>"
10078           | nonempty -> nonempty
10079         ) doc in
10080         let doc = String.concat "\n   * " doc in
10081
10082         pr "  /**\n";
10083         pr "   * %s\n" shortdesc;
10084         pr "   * <p>\n";
10085         pr "   * %s\n" doc;
10086         pr "   * @throws LibGuestFSException\n";
10087         pr "   */\n";
10088         pr "  ";
10089       );
10090       generate_java_prototype ~public:true ~semicolon:false name style;
10091       pr "\n";
10092       pr "  {\n";
10093       pr "    if (g == 0)\n";
10094       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10095         name;
10096       pr "    ";
10097       if fst style <> RErr then pr "return ";
10098       pr "_%s " name;
10099       generate_java_call_args ~handle:"g" (snd style);
10100       pr ";\n";
10101       pr "  }\n";
10102       pr "  ";
10103       generate_java_prototype ~privat:true ~native:true name style;
10104       pr "\n";
10105       pr "\n";
10106   ) all_functions;
10107
10108   pr "}\n"
10109
10110 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10111 and generate_java_call_args ~handle args =
10112   pr "(%s" handle;
10113   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10114   pr ")"
10115
10116 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10117     ?(semicolon=true) name style =
10118   if privat then pr "private ";
10119   if public then pr "public ";
10120   if native then pr "native ";
10121
10122   (* return type *)
10123   (match fst style with
10124    | RErr -> pr "void ";
10125    | RInt _ -> pr "int ";
10126    | RInt64 _ -> pr "long ";
10127    | RBool _ -> pr "boolean ";
10128    | RConstString _ | RConstOptString _ | RString _
10129    | RBufferOut _ -> pr "String ";
10130    | RStringList _ -> pr "String[] ";
10131    | RStruct (_, typ) ->
10132        let name = java_name_of_struct typ in
10133        pr "%s " name;
10134    | RStructList (_, typ) ->
10135        let name = java_name_of_struct typ in
10136        pr "%s[] " name;
10137    | RHashtable _ -> pr "HashMap<String,String> ";
10138   );
10139
10140   if native then pr "_%s " name else pr "%s " name;
10141   pr "(";
10142   let needs_comma = ref false in
10143   if native then (
10144     pr "long g";
10145     needs_comma := true
10146   );
10147
10148   (* args *)
10149   List.iter (
10150     fun arg ->
10151       if !needs_comma then pr ", ";
10152       needs_comma := true;
10153
10154       match arg with
10155       | Pathname n
10156       | Device n | Dev_or_Path n
10157       | String n
10158       | OptString n
10159       | FileIn n
10160       | FileOut n ->
10161           pr "String %s" n
10162       | BufferIn n ->
10163           pr "byte[] %s" n
10164       | StringList n | DeviceList n ->
10165           pr "String[] %s" n
10166       | Bool n ->
10167           pr "boolean %s" n
10168       | Int n ->
10169           pr "int %s" n
10170       | Int64 n ->
10171           pr "long %s" n
10172   ) (snd style);
10173
10174   pr ")\n";
10175   pr "    throws LibGuestFSException";
10176   if semicolon then pr ";"
10177
10178 and generate_java_struct jtyp cols () =
10179   generate_header CStyle LGPLv2plus;
10180
10181   pr "\
10182 package com.redhat.et.libguestfs;
10183
10184 /**
10185  * Libguestfs %s structure.
10186  *
10187  * @author rjones
10188  * @see GuestFS
10189  */
10190 public class %s {
10191 " jtyp jtyp;
10192
10193   List.iter (
10194     function
10195     | name, FString
10196     | name, FUUID
10197     | name, FBuffer -> pr "  public String %s;\n" name
10198     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10199     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10200     | name, FChar -> pr "  public char %s;\n" name
10201     | name, FOptPercent ->
10202         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10203         pr "  public float %s;\n" name
10204   ) cols;
10205
10206   pr "}\n"
10207
10208 and generate_java_c () =
10209   generate_header CStyle LGPLv2plus;
10210
10211   pr "\
10212 #include <stdio.h>
10213 #include <stdlib.h>
10214 #include <string.h>
10215
10216 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10217 #include \"guestfs.h\"
10218
10219 /* Note that this function returns.  The exception is not thrown
10220  * until after the wrapper function returns.
10221  */
10222 static void
10223 throw_exception (JNIEnv *env, const char *msg)
10224 {
10225   jclass cl;
10226   cl = (*env)->FindClass (env,
10227                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10228   (*env)->ThrowNew (env, cl, msg);
10229 }
10230
10231 JNIEXPORT jlong JNICALL
10232 Java_com_redhat_et_libguestfs_GuestFS__1create
10233   (JNIEnv *env, jobject obj)
10234 {
10235   guestfs_h *g;
10236
10237   g = guestfs_create ();
10238   if (g == NULL) {
10239     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10240     return 0;
10241   }
10242   guestfs_set_error_handler (g, NULL, NULL);
10243   return (jlong) (long) g;
10244 }
10245
10246 JNIEXPORT void JNICALL
10247 Java_com_redhat_et_libguestfs_GuestFS__1close
10248   (JNIEnv *env, jobject obj, jlong jg)
10249 {
10250   guestfs_h *g = (guestfs_h *) (long) jg;
10251   guestfs_close (g);
10252 }
10253
10254 ";
10255
10256   List.iter (
10257     fun (name, style, _, _, _, _, _) ->
10258       pr "JNIEXPORT ";
10259       (match fst style with
10260        | RErr -> pr "void ";
10261        | RInt _ -> pr "jint ";
10262        | RInt64 _ -> pr "jlong ";
10263        | RBool _ -> pr "jboolean ";
10264        | RConstString _ | RConstOptString _ | RString _
10265        | RBufferOut _ -> pr "jstring ";
10266        | RStruct _ | RHashtable _ ->
10267            pr "jobject ";
10268        | RStringList _ | RStructList _ ->
10269            pr "jobjectArray ";
10270       );
10271       pr "JNICALL\n";
10272       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10273       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10274       pr "\n";
10275       pr "  (JNIEnv *env, jobject obj, jlong jg";
10276       List.iter (
10277         function
10278         | Pathname n
10279         | Device n | Dev_or_Path n
10280         | String n
10281         | OptString n
10282         | FileIn n
10283         | FileOut n ->
10284             pr ", jstring j%s" n
10285         | BufferIn n ->
10286             pr ", jbyteArray j%s" n
10287         | StringList n | DeviceList n ->
10288             pr ", jobjectArray j%s" n
10289         | Bool n ->
10290             pr ", jboolean j%s" n
10291         | Int n ->
10292             pr ", jint j%s" n
10293         | Int64 n ->
10294             pr ", jlong j%s" n
10295       ) (snd style);
10296       pr ")\n";
10297       pr "{\n";
10298       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10299       let error_code, no_ret =
10300         match fst style with
10301         | RErr -> pr "  int r;\n"; "-1", ""
10302         | RBool _
10303         | RInt _ -> pr "  int r;\n"; "-1", "0"
10304         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10305         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10306         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10307         | RString _ ->
10308             pr "  jstring jr;\n";
10309             pr "  char *r;\n"; "NULL", "NULL"
10310         | RStringList _ ->
10311             pr "  jobjectArray jr;\n";
10312             pr "  int r_len;\n";
10313             pr "  jclass cl;\n";
10314             pr "  jstring jstr;\n";
10315             pr "  char **r;\n"; "NULL", "NULL"
10316         | RStruct (_, typ) ->
10317             pr "  jobject jr;\n";
10318             pr "  jclass cl;\n";
10319             pr "  jfieldID fl;\n";
10320             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10321         | RStructList (_, typ) ->
10322             pr "  jobjectArray jr;\n";
10323             pr "  jclass cl;\n";
10324             pr "  jfieldID fl;\n";
10325             pr "  jobject jfl;\n";
10326             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10327         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10328         | RBufferOut _ ->
10329             pr "  jstring jr;\n";
10330             pr "  char *r;\n";
10331             pr "  size_t size;\n";
10332             "NULL", "NULL" in
10333       List.iter (
10334         function
10335         | Pathname n
10336         | Device n | Dev_or_Path n
10337         | String n
10338         | OptString n
10339         | FileIn n
10340         | FileOut n ->
10341             pr "  const char *%s;\n" n
10342         | BufferIn n ->
10343             pr "  jbyte *%s;\n" n;
10344             pr "  size_t %s_size;\n" n
10345         | StringList n | DeviceList n ->
10346             pr "  int %s_len;\n" n;
10347             pr "  const char **%s;\n" n
10348         | Bool n
10349         | Int n ->
10350             pr "  int %s;\n" n
10351         | Int64 n ->
10352             pr "  int64_t %s;\n" n
10353       ) (snd style);
10354
10355       let needs_i =
10356         (match fst style with
10357          | RStringList _ | RStructList _ -> true
10358          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10359          | RConstOptString _
10360          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10361           List.exists (function
10362                        | StringList _ -> true
10363                        | DeviceList _ -> true
10364                        | _ -> false) (snd style) in
10365       if needs_i then
10366         pr "  int i;\n";
10367
10368       pr "\n";
10369
10370       (* Get the parameters. *)
10371       List.iter (
10372         function
10373         | Pathname n
10374         | Device n | Dev_or_Path n
10375         | String n
10376         | FileIn n
10377         | FileOut n ->
10378             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10379         | OptString n ->
10380             (* This is completely undocumented, but Java null becomes
10381              * a NULL parameter.
10382              *)
10383             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10384         | BufferIn n ->
10385             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10386             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10387         | StringList n | DeviceList n ->
10388             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10389             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10390             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10391             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10392               n;
10393             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10394             pr "  }\n";
10395             pr "  %s[%s_len] = NULL;\n" n n;
10396         | Bool n
10397         | Int n
10398         | Int64 n ->
10399             pr "  %s = j%s;\n" n n
10400       ) (snd style);
10401
10402       (* Make the call. *)
10403       pr "  r = guestfs_%s " name;
10404       generate_c_call_args ~handle:"g" style;
10405       pr ";\n";
10406
10407       (* Release the parameters. *)
10408       List.iter (
10409         function
10410         | Pathname n
10411         | Device n | Dev_or_Path n
10412         | String n
10413         | FileIn n
10414         | FileOut n ->
10415             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10416         | OptString n ->
10417             pr "  if (j%s)\n" n;
10418             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10419         | BufferIn n ->
10420             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10421         | StringList n | DeviceList n ->
10422             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10423             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10424               n;
10425             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10426             pr "  }\n";
10427             pr "  free (%s);\n" n
10428         | Bool n
10429         | Int n
10430         | Int64 n -> ()
10431       ) (snd style);
10432
10433       (* Check for errors. *)
10434       pr "  if (r == %s) {\n" error_code;
10435       pr "    throw_exception (env, guestfs_last_error (g));\n";
10436       pr "    return %s;\n" no_ret;
10437       pr "  }\n";
10438
10439       (* Return value. *)
10440       (match fst style with
10441        | RErr -> ()
10442        | RInt _ -> pr "  return (jint) r;\n"
10443        | RBool _ -> pr "  return (jboolean) r;\n"
10444        | RInt64 _ -> pr "  return (jlong) r;\n"
10445        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10446        | RConstOptString _ ->
10447            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10448        | RString _ ->
10449            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10450            pr "  free (r);\n";
10451            pr "  return jr;\n"
10452        | RStringList _ ->
10453            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10454            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10455            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10456            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10457            pr "  for (i = 0; i < r_len; ++i) {\n";
10458            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10459            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10460            pr "    free (r[i]);\n";
10461            pr "  }\n";
10462            pr "  free (r);\n";
10463            pr "  return jr;\n"
10464        | RStruct (_, typ) ->
10465            let jtyp = java_name_of_struct typ in
10466            let cols = cols_of_struct typ in
10467            generate_java_struct_return typ jtyp cols
10468        | RStructList (_, typ) ->
10469            let jtyp = java_name_of_struct typ in
10470            let cols = cols_of_struct typ in
10471            generate_java_struct_list_return typ jtyp cols
10472        | RHashtable _ ->
10473            (* XXX *)
10474            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10475            pr "  return NULL;\n"
10476        | RBufferOut _ ->
10477            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10478            pr "  free (r);\n";
10479            pr "  return jr;\n"
10480       );
10481
10482       pr "}\n";
10483       pr "\n"
10484   ) all_functions
10485
10486 and generate_java_struct_return typ jtyp cols =
10487   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10488   pr "  jr = (*env)->AllocObject (env, cl);\n";
10489   List.iter (
10490     function
10491     | name, FString ->
10492         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10493         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10494     | name, FUUID ->
10495         pr "  {\n";
10496         pr "    char s[33];\n";
10497         pr "    memcpy (s, r->%s, 32);\n" name;
10498         pr "    s[32] = 0;\n";
10499         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10500         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10501         pr "  }\n";
10502     | name, FBuffer ->
10503         pr "  {\n";
10504         pr "    int len = r->%s_len;\n" name;
10505         pr "    char s[len+1];\n";
10506         pr "    memcpy (s, r->%s, len);\n" name;
10507         pr "    s[len] = 0;\n";
10508         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10509         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10510         pr "  }\n";
10511     | name, (FBytes|FUInt64|FInt64) ->
10512         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10513         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10514     | name, (FUInt32|FInt32) ->
10515         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10516         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10517     | name, FOptPercent ->
10518         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10519         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10520     | name, FChar ->
10521         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10522         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10523   ) cols;
10524   pr "  free (r);\n";
10525   pr "  return jr;\n"
10526
10527 and generate_java_struct_list_return typ jtyp cols =
10528   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10529   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10530   pr "  for (i = 0; i < r->len; ++i) {\n";
10531   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10532   List.iter (
10533     function
10534     | name, FString ->
10535         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10536         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10537     | name, FUUID ->
10538         pr "    {\n";
10539         pr "      char s[33];\n";
10540         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10541         pr "      s[32] = 0;\n";
10542         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10543         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10544         pr "    }\n";
10545     | name, FBuffer ->
10546         pr "    {\n";
10547         pr "      int len = r->val[i].%s_len;\n" name;
10548         pr "      char s[len+1];\n";
10549         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10550         pr "      s[len] = 0;\n";
10551         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10552         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10553         pr "    }\n";
10554     | name, (FBytes|FUInt64|FInt64) ->
10555         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10556         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10557     | name, (FUInt32|FInt32) ->
10558         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10559         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10560     | name, FOptPercent ->
10561         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10562         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10563     | name, FChar ->
10564         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10565         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10566   ) cols;
10567   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10568   pr "  }\n";
10569   pr "  guestfs_free_%s_list (r);\n" typ;
10570   pr "  return jr;\n"
10571
10572 and generate_java_makefile_inc () =
10573   generate_header HashStyle GPLv2plus;
10574
10575   pr "java_built_sources = \\\n";
10576   List.iter (
10577     fun (typ, jtyp) ->
10578         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10579   ) java_structs;
10580   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10581
10582 and generate_haskell_hs () =
10583   generate_header HaskellStyle LGPLv2plus;
10584
10585   (* XXX We only know how to generate partial FFI for Haskell
10586    * at the moment.  Please help out!
10587    *)
10588   let can_generate style =
10589     match style with
10590     | RErr, _
10591     | RInt _, _
10592     | RInt64 _, _ -> true
10593     | RBool _, _
10594     | RConstString _, _
10595     | RConstOptString _, _
10596     | RString _, _
10597     | RStringList _, _
10598     | RStruct _, _
10599     | RStructList _, _
10600     | RHashtable _, _
10601     | RBufferOut _, _ -> false in
10602
10603   pr "\
10604 {-# INCLUDE <guestfs.h> #-}
10605 {-# LANGUAGE ForeignFunctionInterface #-}
10606
10607 module Guestfs (
10608   create";
10609
10610   (* List out the names of the actions we want to export. *)
10611   List.iter (
10612     fun (name, style, _, _, _, _, _) ->
10613       if can_generate style then pr ",\n  %s" name
10614   ) all_functions;
10615
10616   pr "
10617   ) where
10618
10619 -- Unfortunately some symbols duplicate ones already present
10620 -- in Prelude.  We don't know which, so we hard-code a list
10621 -- here.
10622 import Prelude hiding (truncate)
10623
10624 import Foreign
10625 import Foreign.C
10626 import Foreign.C.Types
10627 import IO
10628 import Control.Exception
10629 import Data.Typeable
10630
10631 data GuestfsS = GuestfsS            -- represents the opaque C struct
10632 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10633 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10634
10635 -- XXX define properly later XXX
10636 data PV = PV
10637 data VG = VG
10638 data LV = LV
10639 data IntBool = IntBool
10640 data Stat = Stat
10641 data StatVFS = StatVFS
10642 data Hashtable = Hashtable
10643
10644 foreign import ccall unsafe \"guestfs_create\" c_create
10645   :: IO GuestfsP
10646 foreign import ccall unsafe \"&guestfs_close\" c_close
10647   :: FunPtr (GuestfsP -> IO ())
10648 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10649   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10650
10651 create :: IO GuestfsH
10652 create = do
10653   p <- c_create
10654   c_set_error_handler p nullPtr nullPtr
10655   h <- newForeignPtr c_close p
10656   return h
10657
10658 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10659   :: GuestfsP -> IO CString
10660
10661 -- last_error :: GuestfsH -> IO (Maybe String)
10662 -- last_error h = do
10663 --   str <- withForeignPtr h (\\p -> c_last_error p)
10664 --   maybePeek peekCString str
10665
10666 last_error :: GuestfsH -> IO (String)
10667 last_error h = do
10668   str <- withForeignPtr h (\\p -> c_last_error p)
10669   if (str == nullPtr)
10670     then return \"no error\"
10671     else peekCString str
10672
10673 ";
10674
10675   (* Generate wrappers for each foreign function. *)
10676   List.iter (
10677     fun (name, style, _, _, _, _, _) ->
10678       if can_generate style then (
10679         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10680         pr "  :: ";
10681         generate_haskell_prototype ~handle:"GuestfsP" style;
10682         pr "\n";
10683         pr "\n";
10684         pr "%s :: " name;
10685         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10686         pr "\n";
10687         pr "%s %s = do\n" name
10688           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10689         pr "  r <- ";
10690         (* Convert pointer arguments using with* functions. *)
10691         List.iter (
10692           function
10693           | FileIn n
10694           | FileOut n
10695           | Pathname n | Device n | Dev_or_Path n | String n ->
10696               pr "withCString %s $ \\%s -> " n n
10697           | BufferIn n ->
10698               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10699           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10700           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10701           | Bool _ | Int _ | Int64 _ -> ()
10702         ) (snd style);
10703         (* Convert integer arguments. *)
10704         let args =
10705           List.map (
10706             function
10707             | Bool n -> sprintf "(fromBool %s)" n
10708             | Int n -> sprintf "(fromIntegral %s)" n
10709             | Int64 n -> sprintf "(fromIntegral %s)" n
10710             | FileIn n | FileOut n
10711             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10712             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10713           ) (snd style) in
10714         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10715           (String.concat " " ("p" :: args));
10716         (match fst style with
10717          | RErr | RInt _ | RInt64 _ | RBool _ ->
10718              pr "  if (r == -1)\n";
10719              pr "    then do\n";
10720              pr "      err <- last_error h\n";
10721              pr "      fail err\n";
10722          | RConstString _ | RConstOptString _ | RString _
10723          | RStringList _ | RStruct _
10724          | RStructList _ | RHashtable _ | RBufferOut _ ->
10725              pr "  if (r == nullPtr)\n";
10726              pr "    then do\n";
10727              pr "      err <- last_error h\n";
10728              pr "      fail err\n";
10729         );
10730         (match fst style with
10731          | RErr ->
10732              pr "    else return ()\n"
10733          | RInt _ ->
10734              pr "    else return (fromIntegral r)\n"
10735          | RInt64 _ ->
10736              pr "    else return (fromIntegral r)\n"
10737          | RBool _ ->
10738              pr "    else return (toBool r)\n"
10739          | RConstString _
10740          | RConstOptString _
10741          | RString _
10742          | RStringList _
10743          | RStruct _
10744          | RStructList _
10745          | RHashtable _
10746          | RBufferOut _ ->
10747              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10748         );
10749         pr "\n";
10750       )
10751   ) all_functions
10752
10753 and generate_haskell_prototype ~handle ?(hs = false) style =
10754   pr "%s -> " handle;
10755   let string = if hs then "String" else "CString" in
10756   let int = if hs then "Int" else "CInt" in
10757   let bool = if hs then "Bool" else "CInt" in
10758   let int64 = if hs then "Integer" else "Int64" in
10759   List.iter (
10760     fun arg ->
10761       (match arg with
10762        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10763        | BufferIn _ ->
10764            if hs then pr "String"
10765            else pr "CString -> CInt"
10766        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10767        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10768        | Bool _ -> pr "%s" bool
10769        | Int _ -> pr "%s" int
10770        | Int64 _ -> pr "%s" int
10771        | FileIn _ -> pr "%s" string
10772        | FileOut _ -> pr "%s" string
10773       );
10774       pr " -> ";
10775   ) (snd style);
10776   pr "IO (";
10777   (match fst style with
10778    | RErr -> if not hs then pr "CInt"
10779    | RInt _ -> pr "%s" int
10780    | RInt64 _ -> pr "%s" int64
10781    | RBool _ -> pr "%s" bool
10782    | RConstString _ -> pr "%s" string
10783    | RConstOptString _ -> pr "Maybe %s" string
10784    | RString _ -> pr "%s" string
10785    | RStringList _ -> pr "[%s]" string
10786    | RStruct (_, typ) ->
10787        let name = java_name_of_struct typ in
10788        pr "%s" name
10789    | RStructList (_, typ) ->
10790        let name = java_name_of_struct typ in
10791        pr "[%s]" name
10792    | RHashtable _ -> pr "Hashtable"
10793    | RBufferOut _ -> pr "%s" string
10794   );
10795   pr ")"
10796
10797 and generate_csharp () =
10798   generate_header CPlusPlusStyle LGPLv2plus;
10799
10800   (* XXX Make this configurable by the C# assembly users. *)
10801   let library = "libguestfs.so.0" in
10802
10803   pr "\
10804 // These C# bindings are highly experimental at present.
10805 //
10806 // Firstly they only work on Linux (ie. Mono).  In order to get them
10807 // to work on Windows (ie. .Net) you would need to port the library
10808 // itself to Windows first.
10809 //
10810 // The second issue is that some calls are known to be incorrect and
10811 // can cause Mono to segfault.  Particularly: calls which pass or
10812 // return string[], or return any structure value.  This is because
10813 // we haven't worked out the correct way to do this from C#.
10814 //
10815 // The third issue is that when compiling you get a lot of warnings.
10816 // We are not sure whether the warnings are important or not.
10817 //
10818 // Fourthly we do not routinely build or test these bindings as part
10819 // of the make && make check cycle, which means that regressions might
10820 // go unnoticed.
10821 //
10822 // Suggestions and patches are welcome.
10823
10824 // To compile:
10825 //
10826 // gmcs Libguestfs.cs
10827 // mono Libguestfs.exe
10828 //
10829 // (You'll probably want to add a Test class / static main function
10830 // otherwise this won't do anything useful).
10831
10832 using System;
10833 using System.IO;
10834 using System.Runtime.InteropServices;
10835 using System.Runtime.Serialization;
10836 using System.Collections;
10837
10838 namespace Guestfs
10839 {
10840   class Error : System.ApplicationException
10841   {
10842     public Error (string message) : base (message) {}
10843     protected Error (SerializationInfo info, StreamingContext context) {}
10844   }
10845
10846   class Guestfs
10847   {
10848     IntPtr _handle;
10849
10850     [DllImport (\"%s\")]
10851     static extern IntPtr guestfs_create ();
10852
10853     public Guestfs ()
10854     {
10855       _handle = guestfs_create ();
10856       if (_handle == IntPtr.Zero)
10857         throw new Error (\"could not create guestfs handle\");
10858     }
10859
10860     [DllImport (\"%s\")]
10861     static extern void guestfs_close (IntPtr h);
10862
10863     ~Guestfs ()
10864     {
10865       guestfs_close (_handle);
10866     }
10867
10868     [DllImport (\"%s\")]
10869     static extern string guestfs_last_error (IntPtr h);
10870
10871 " library library library;
10872
10873   (* Generate C# structure bindings.  We prefix struct names with
10874    * underscore because C# cannot have conflicting struct names and
10875    * method names (eg. "class stat" and "stat").
10876    *)
10877   List.iter (
10878     fun (typ, cols) ->
10879       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10880       pr "    public class _%s {\n" typ;
10881       List.iter (
10882         function
10883         | name, FChar -> pr "      char %s;\n" name
10884         | name, FString -> pr "      string %s;\n" name
10885         | name, FBuffer ->
10886             pr "      uint %s_len;\n" name;
10887             pr "      string %s;\n" name
10888         | name, FUUID ->
10889             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10890             pr "      string %s;\n" name
10891         | name, FUInt32 -> pr "      uint %s;\n" name
10892         | name, FInt32 -> pr "      int %s;\n" name
10893         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10894         | name, FInt64 -> pr "      long %s;\n" name
10895         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10896       ) cols;
10897       pr "    }\n";
10898       pr "\n"
10899   ) structs;
10900
10901   (* Generate C# function bindings. *)
10902   List.iter (
10903     fun (name, style, _, _, _, shortdesc, _) ->
10904       let rec csharp_return_type () =
10905         match fst style with
10906         | RErr -> "void"
10907         | RBool n -> "bool"
10908         | RInt n -> "int"
10909         | RInt64 n -> "long"
10910         | RConstString n
10911         | RConstOptString n
10912         | RString n
10913         | RBufferOut n -> "string"
10914         | RStruct (_,n) -> "_" ^ n
10915         | RHashtable n -> "Hashtable"
10916         | RStringList n -> "string[]"
10917         | RStructList (_,n) -> sprintf "_%s[]" n
10918
10919       and c_return_type () =
10920         match fst style with
10921         | RErr
10922         | RBool _
10923         | RInt _ -> "int"
10924         | RInt64 _ -> "long"
10925         | RConstString _
10926         | RConstOptString _
10927         | RString _
10928         | RBufferOut _ -> "string"
10929         | RStruct (_,n) -> "_" ^ n
10930         | RHashtable _
10931         | RStringList _ -> "string[]"
10932         | RStructList (_,n) -> sprintf "_%s[]" n
10933
10934       and c_error_comparison () =
10935         match fst style with
10936         | RErr
10937         | RBool _
10938         | RInt _
10939         | RInt64 _ -> "== -1"
10940         | RConstString _
10941         | RConstOptString _
10942         | RString _
10943         | RBufferOut _
10944         | RStruct (_,_)
10945         | RHashtable _
10946         | RStringList _
10947         | RStructList (_,_) -> "== null"
10948
10949       and generate_extern_prototype () =
10950         pr "    static extern %s guestfs_%s (IntPtr h"
10951           (c_return_type ()) name;
10952         List.iter (
10953           function
10954           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10955           | FileIn n | FileOut n
10956           | BufferIn n ->
10957               pr ", [In] string %s" n
10958           | StringList n | DeviceList n ->
10959               pr ", [In] string[] %s" n
10960           | Bool n ->
10961               pr ", bool %s" n
10962           | Int n ->
10963               pr ", int %s" n
10964           | Int64 n ->
10965               pr ", long %s" n
10966         ) (snd style);
10967         pr ");\n"
10968
10969       and generate_public_prototype () =
10970         pr "    public %s %s (" (csharp_return_type ()) name;
10971         let comma = ref false in
10972         let next () =
10973           if !comma then pr ", ";
10974           comma := true
10975         in
10976         List.iter (
10977           function
10978           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10979           | FileIn n | FileOut n
10980           | BufferIn n ->
10981               next (); pr "string %s" n
10982           | StringList n | DeviceList n ->
10983               next (); pr "string[] %s" n
10984           | Bool n ->
10985               next (); pr "bool %s" n
10986           | Int n ->
10987               next (); pr "int %s" n
10988           | Int64 n ->
10989               next (); pr "long %s" n
10990         ) (snd style);
10991         pr ")\n"
10992
10993       and generate_call () =
10994         pr "guestfs_%s (_handle" name;
10995         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10996         pr ");\n";
10997       in
10998
10999       pr "    [DllImport (\"%s\")]\n" library;
11000       generate_extern_prototype ();
11001       pr "\n";
11002       pr "    /// <summary>\n";
11003       pr "    /// %s\n" shortdesc;
11004       pr "    /// </summary>\n";
11005       generate_public_prototype ();
11006       pr "    {\n";
11007       pr "      %s r;\n" (c_return_type ());
11008       pr "      r = ";
11009       generate_call ();
11010       pr "      if (r %s)\n" (c_error_comparison ());
11011       pr "        throw new Error (guestfs_last_error (_handle));\n";
11012       (match fst style with
11013        | RErr -> ()
11014        | RBool _ ->
11015            pr "      return r != 0 ? true : false;\n"
11016        | RHashtable _ ->
11017            pr "      Hashtable rr = new Hashtable ();\n";
11018            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11019            pr "        rr.Add (r[i], r[i+1]);\n";
11020            pr "      return rr;\n"
11021        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11022        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11023        | RStructList _ ->
11024            pr "      return r;\n"
11025       );
11026       pr "    }\n";
11027       pr "\n";
11028   ) all_functions_sorted;
11029
11030   pr "  }
11031 }
11032 "
11033
11034 and generate_bindtests () =
11035   generate_header CStyle LGPLv2plus;
11036
11037   pr "\
11038 #include <stdio.h>
11039 #include <stdlib.h>
11040 #include <inttypes.h>
11041 #include <string.h>
11042
11043 #include \"guestfs.h\"
11044 #include \"guestfs-internal.h\"
11045 #include \"guestfs-internal-actions.h\"
11046 #include \"guestfs_protocol.h\"
11047
11048 #define error guestfs_error
11049 #define safe_calloc guestfs_safe_calloc
11050 #define safe_malloc guestfs_safe_malloc
11051
11052 static void
11053 print_strings (char *const *argv)
11054 {
11055   int argc;
11056
11057   printf (\"[\");
11058   for (argc = 0; argv[argc] != NULL; ++argc) {
11059     if (argc > 0) printf (\", \");
11060     printf (\"\\\"%%s\\\"\", argv[argc]);
11061   }
11062   printf (\"]\\n\");
11063 }
11064
11065 /* The test0 function prints its parameters to stdout. */
11066 ";
11067
11068   let test0, tests =
11069     match test_functions with
11070     | [] -> assert false
11071     | test0 :: tests -> test0, tests in
11072
11073   let () =
11074     let (name, style, _, _, _, _, _) = test0 in
11075     generate_prototype ~extern:false ~semicolon:false ~newline:true
11076       ~handle:"g" ~prefix:"guestfs__" name style;
11077     pr "{\n";
11078     List.iter (
11079       function
11080       | Pathname n
11081       | Device n | Dev_or_Path n
11082       | String n
11083       | FileIn n
11084       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11085       | BufferIn n ->
11086           pr "  {\n";
11087           pr "    size_t i;\n";
11088           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11089           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11090           pr "    printf (\"\\n\");\n";
11091           pr "  }\n";
11092       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11093       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11094       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11095       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11096       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11097     ) (snd style);
11098     pr "  /* Java changes stdout line buffering so we need this: */\n";
11099     pr "  fflush (stdout);\n";
11100     pr "  return 0;\n";
11101     pr "}\n";
11102     pr "\n" in
11103
11104   List.iter (
11105     fun (name, style, _, _, _, _, _) ->
11106       if String.sub name (String.length name - 3) 3 <> "err" then (
11107         pr "/* Test normal return. */\n";
11108         generate_prototype ~extern:false ~semicolon:false ~newline:true
11109           ~handle:"g" ~prefix:"guestfs__" name style;
11110         pr "{\n";
11111         (match fst style with
11112          | RErr ->
11113              pr "  return 0;\n"
11114          | RInt _ ->
11115              pr "  int r;\n";
11116              pr "  sscanf (val, \"%%d\", &r);\n";
11117              pr "  return r;\n"
11118          | RInt64 _ ->
11119              pr "  int64_t r;\n";
11120              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11121              pr "  return r;\n"
11122          | RBool _ ->
11123              pr "  return STREQ (val, \"true\");\n"
11124          | RConstString _
11125          | RConstOptString _ ->
11126              (* Can't return the input string here.  Return a static
11127               * string so we ensure we get a segfault if the caller
11128               * tries to free it.
11129               *)
11130              pr "  return \"static string\";\n"
11131          | RString _ ->
11132              pr "  return strdup (val);\n"
11133          | RStringList _ ->
11134              pr "  char **strs;\n";
11135              pr "  int n, i;\n";
11136              pr "  sscanf (val, \"%%d\", &n);\n";
11137              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11138              pr "  for (i = 0; i < n; ++i) {\n";
11139              pr "    strs[i] = safe_malloc (g, 16);\n";
11140              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11141              pr "  }\n";
11142              pr "  strs[n] = NULL;\n";
11143              pr "  return strs;\n"
11144          | RStruct (_, typ) ->
11145              pr "  struct guestfs_%s *r;\n" typ;
11146              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11147              pr "  return r;\n"
11148          | RStructList (_, typ) ->
11149              pr "  struct guestfs_%s_list *r;\n" typ;
11150              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11151              pr "  sscanf (val, \"%%d\", &r->len);\n";
11152              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11153              pr "  return r;\n"
11154          | RHashtable _ ->
11155              pr "  char **strs;\n";
11156              pr "  int n, i;\n";
11157              pr "  sscanf (val, \"%%d\", &n);\n";
11158              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11159              pr "  for (i = 0; i < n; ++i) {\n";
11160              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11161              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11162              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11163              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11164              pr "  }\n";
11165              pr "  strs[n*2] = NULL;\n";
11166              pr "  return strs;\n"
11167          | RBufferOut _ ->
11168              pr "  return strdup (val);\n"
11169         );
11170         pr "}\n";
11171         pr "\n"
11172       ) else (
11173         pr "/* Test error return. */\n";
11174         generate_prototype ~extern:false ~semicolon:false ~newline:true
11175           ~handle:"g" ~prefix:"guestfs__" name style;
11176         pr "{\n";
11177         pr "  error (g, \"error\");\n";
11178         (match fst style with
11179          | RErr | RInt _ | RInt64 _ | RBool _ ->
11180              pr "  return -1;\n"
11181          | RConstString _ | RConstOptString _
11182          | RString _ | RStringList _ | RStruct _
11183          | RStructList _
11184          | RHashtable _
11185          | RBufferOut _ ->
11186              pr "  return NULL;\n"
11187         );
11188         pr "}\n";
11189         pr "\n"
11190       )
11191   ) tests
11192
11193 and generate_ocaml_bindtests () =
11194   generate_header OCamlStyle GPLv2plus;
11195
11196   pr "\
11197 let () =
11198   let g = Guestfs.create () in
11199 ";
11200
11201   let mkargs args =
11202     String.concat " " (
11203       List.map (
11204         function
11205         | CallString s -> "\"" ^ s ^ "\""
11206         | CallOptString None -> "None"
11207         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11208         | CallStringList xs ->
11209             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11210         | CallInt i when i >= 0 -> string_of_int i
11211         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11212         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11213         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11214         | CallBool b -> string_of_bool b
11215         | CallBuffer s -> sprintf "%S" s
11216       ) args
11217     )
11218   in
11219
11220   generate_lang_bindtests (
11221     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11222   );
11223
11224   pr "print_endline \"EOF\"\n"
11225
11226 and generate_perl_bindtests () =
11227   pr "#!/usr/bin/perl -w\n";
11228   generate_header HashStyle GPLv2plus;
11229
11230   pr "\
11231 use strict;
11232
11233 use Sys::Guestfs;
11234
11235 my $g = Sys::Guestfs->new ();
11236 ";
11237
11238   let mkargs args =
11239     String.concat ", " (
11240       List.map (
11241         function
11242         | CallString s -> "\"" ^ s ^ "\""
11243         | CallOptString None -> "undef"
11244         | CallOptString (Some s) -> sprintf "\"%s\"" s
11245         | CallStringList xs ->
11246             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11247         | CallInt i -> string_of_int i
11248         | CallInt64 i -> Int64.to_string i
11249         | CallBool b -> if b then "1" else "0"
11250         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11251       ) args
11252     )
11253   in
11254
11255   generate_lang_bindtests (
11256     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11257   );
11258
11259   pr "print \"EOF\\n\"\n"
11260
11261 and generate_python_bindtests () =
11262   generate_header HashStyle GPLv2plus;
11263
11264   pr "\
11265 import guestfs
11266
11267 g = guestfs.GuestFS ()
11268 ";
11269
11270   let mkargs args =
11271     String.concat ", " (
11272       List.map (
11273         function
11274         | CallString s -> "\"" ^ s ^ "\""
11275         | CallOptString None -> "None"
11276         | CallOptString (Some s) -> sprintf "\"%s\"" s
11277         | CallStringList xs ->
11278             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11279         | CallInt i -> string_of_int i
11280         | CallInt64 i -> Int64.to_string i
11281         | CallBool b -> if b then "1" else "0"
11282         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11283       ) args
11284     )
11285   in
11286
11287   generate_lang_bindtests (
11288     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11289   );
11290
11291   pr "print \"EOF\"\n"
11292
11293 and generate_ruby_bindtests () =
11294   generate_header HashStyle GPLv2plus;
11295
11296   pr "\
11297 require 'guestfs'
11298
11299 g = Guestfs::create()
11300 ";
11301
11302   let mkargs args =
11303     String.concat ", " (
11304       List.map (
11305         function
11306         | CallString s -> "\"" ^ s ^ "\""
11307         | CallOptString None -> "nil"
11308         | CallOptString (Some s) -> sprintf "\"%s\"" s
11309         | CallStringList xs ->
11310             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11311         | CallInt i -> string_of_int i
11312         | CallInt64 i -> Int64.to_string i
11313         | CallBool b -> string_of_bool b
11314         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11315       ) args
11316     )
11317   in
11318
11319   generate_lang_bindtests (
11320     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11321   );
11322
11323   pr "print \"EOF\\n\"\n"
11324
11325 and generate_java_bindtests () =
11326   generate_header CStyle GPLv2plus;
11327
11328   pr "\
11329 import com.redhat.et.libguestfs.*;
11330
11331 public class Bindtests {
11332     public static void main (String[] argv)
11333     {
11334         try {
11335             GuestFS g = new GuestFS ();
11336 ";
11337
11338   let mkargs args =
11339     String.concat ", " (
11340       List.map (
11341         function
11342         | CallString s -> "\"" ^ s ^ "\""
11343         | CallOptString None -> "null"
11344         | CallOptString (Some s) -> sprintf "\"%s\"" s
11345         | CallStringList xs ->
11346             "new String[]{" ^
11347               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11348         | CallInt i -> string_of_int i
11349         | CallInt64 i -> Int64.to_string i
11350         | CallBool b -> string_of_bool b
11351         | CallBuffer s ->
11352             "new byte[] { " ^ String.concat "," (
11353               map_chars (fun c -> string_of_int (Char.code c)) s
11354             ) ^ " }"
11355       ) args
11356     )
11357   in
11358
11359   generate_lang_bindtests (
11360     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11361   );
11362
11363   pr "
11364             System.out.println (\"EOF\");
11365         }
11366         catch (Exception exn) {
11367             System.err.println (exn);
11368             System.exit (1);
11369         }
11370     }
11371 }
11372 "
11373
11374 and generate_haskell_bindtests () =
11375   generate_header HaskellStyle GPLv2plus;
11376
11377   pr "\
11378 module Bindtests where
11379 import qualified Guestfs
11380
11381 main = do
11382   g <- Guestfs.create
11383 ";
11384
11385   let mkargs args =
11386     String.concat " " (
11387       List.map (
11388         function
11389         | CallString s -> "\"" ^ s ^ "\""
11390         | CallOptString None -> "Nothing"
11391         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11392         | CallStringList xs ->
11393             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11394         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11395         | CallInt i -> string_of_int i
11396         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11397         | CallInt64 i -> Int64.to_string i
11398         | CallBool true -> "True"
11399         | CallBool false -> "False"
11400         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11401       ) args
11402     )
11403   in
11404
11405   generate_lang_bindtests (
11406     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11407   );
11408
11409   pr "  putStrLn \"EOF\"\n"
11410
11411 (* Language-independent bindings tests - we do it this way to
11412  * ensure there is parity in testing bindings across all languages.
11413  *)
11414 and generate_lang_bindtests call =
11415   call "test0" [CallString "abc"; CallOptString (Some "def");
11416                 CallStringList []; CallBool false;
11417                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11418                 CallBuffer "abc\000abc"];
11419   call "test0" [CallString "abc"; CallOptString None;
11420                 CallStringList []; CallBool false;
11421                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11422                 CallBuffer "abc\000abc"];
11423   call "test0" [CallString ""; CallOptString (Some "def");
11424                 CallStringList []; CallBool false;
11425                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11426                 CallBuffer "abc\000abc"];
11427   call "test0" [CallString ""; CallOptString (Some "");
11428                 CallStringList []; CallBool false;
11429                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11430                 CallBuffer "abc\000abc"];
11431   call "test0" [CallString "abc"; CallOptString (Some "def");
11432                 CallStringList ["1"]; CallBool false;
11433                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11434                 CallBuffer "abc\000abc"];
11435   call "test0" [CallString "abc"; CallOptString (Some "def");
11436                 CallStringList ["1"; "2"]; CallBool false;
11437                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11438                 CallBuffer "abc\000abc"];
11439   call "test0" [CallString "abc"; CallOptString (Some "def");
11440                 CallStringList ["1"]; CallBool true;
11441                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11442                 CallBuffer "abc\000abc"];
11443   call "test0" [CallString "abc"; CallOptString (Some "def");
11444                 CallStringList ["1"]; CallBool false;
11445                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11446                 CallBuffer "abc\000abc"];
11447   call "test0" [CallString "abc"; CallOptString (Some "def");
11448                 CallStringList ["1"]; CallBool false;
11449                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11450                 CallBuffer "abc\000abc"];
11451   call "test0" [CallString "abc"; CallOptString (Some "def");
11452                 CallStringList ["1"]; CallBool false;
11453                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11454                 CallBuffer "abc\000abc"];
11455   call "test0" [CallString "abc"; CallOptString (Some "def");
11456                 CallStringList ["1"]; CallBool false;
11457                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11458                 CallBuffer "abc\000abc"];
11459   call "test0" [CallString "abc"; CallOptString (Some "def");
11460                 CallStringList ["1"]; CallBool false;
11461                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11462                 CallBuffer "abc\000abc"];
11463   call "test0" [CallString "abc"; CallOptString (Some "def");
11464                 CallStringList ["1"]; CallBool false;
11465                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11466                 CallBuffer "abc\000abc"]
11467
11468 (* XXX Add here tests of the return and error functions. *)
11469
11470 (* Code to generator bindings for virt-inspector.  Currently only
11471  * implemented for OCaml code (for virt-p2v 2.0).
11472  *)
11473 let rng_input = "inspector/virt-inspector.rng"
11474
11475 (* Read the input file and parse it into internal structures.  This is
11476  * by no means a complete RELAX NG parser, but is just enough to be
11477  * able to parse the specific input file.
11478  *)
11479 type rng =
11480   | Element of string * rng list        (* <element name=name/> *)
11481   | Attribute of string * rng list        (* <attribute name=name/> *)
11482   | Interleave of rng list                (* <interleave/> *)
11483   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11484   | OneOrMore of rng                        (* <oneOrMore/> *)
11485   | Optional of rng                        (* <optional/> *)
11486   | Choice of string list                (* <choice><value/>*</choice> *)
11487   | Value of string                        (* <value>str</value> *)
11488   | Text                                (* <text/> *)
11489
11490 let rec string_of_rng = function
11491   | Element (name, xs) ->
11492       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11493   | Attribute (name, xs) ->
11494       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11495   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11496   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11497   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11498   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11499   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11500   | Value value -> "Value \"" ^ value ^ "\""
11501   | Text -> "Text"
11502
11503 and string_of_rng_list xs =
11504   String.concat ", " (List.map string_of_rng xs)
11505
11506 let rec parse_rng ?defines context = function
11507   | [] -> []
11508   | Xml.Element ("element", ["name", name], children) :: rest ->
11509       Element (name, parse_rng ?defines context children)
11510       :: parse_rng ?defines context rest
11511   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11512       Attribute (name, parse_rng ?defines context children)
11513       :: parse_rng ?defines context rest
11514   | Xml.Element ("interleave", [], children) :: rest ->
11515       Interleave (parse_rng ?defines context children)
11516       :: parse_rng ?defines context rest
11517   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11518       let rng = parse_rng ?defines context [child] in
11519       (match rng with
11520        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11521        | _ ->
11522            failwithf "%s: <zeroOrMore> contains more than one child element"
11523              context
11524       )
11525   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11526       let rng = parse_rng ?defines context [child] in
11527       (match rng with
11528        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11529        | _ ->
11530            failwithf "%s: <oneOrMore> contains more than one child element"
11531              context
11532       )
11533   | Xml.Element ("optional", [], [child]) :: rest ->
11534       let rng = parse_rng ?defines context [child] in
11535       (match rng with
11536        | [child] -> Optional child :: parse_rng ?defines context rest
11537        | _ ->
11538            failwithf "%s: <optional> contains more than one child element"
11539              context
11540       )
11541   | Xml.Element ("choice", [], children) :: rest ->
11542       let values = List.map (
11543         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11544         | _ ->
11545             failwithf "%s: can't handle anything except <value> in <choice>"
11546               context
11547       ) children in
11548       Choice values
11549       :: parse_rng ?defines context rest
11550   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11551       Value value :: parse_rng ?defines context rest
11552   | Xml.Element ("text", [], []) :: rest ->
11553       Text :: parse_rng ?defines context rest
11554   | Xml.Element ("ref", ["name", name], []) :: rest ->
11555       (* Look up the reference.  Because of limitations in this parser,
11556        * we can't handle arbitrarily nested <ref> yet.  You can only
11557        * use <ref> from inside <start>.
11558        *)
11559       (match defines with
11560        | None ->
11561            failwithf "%s: contains <ref>, but no refs are defined yet" context
11562        | Some map ->
11563            let rng = StringMap.find name map in
11564            rng @ parse_rng ?defines context rest
11565       )
11566   | x :: _ ->
11567       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11568
11569 let grammar =
11570   let xml = Xml.parse_file rng_input in
11571   match xml with
11572   | Xml.Element ("grammar", _,
11573                  Xml.Element ("start", _, gram) :: defines) ->
11574       (* The <define/> elements are referenced in the <start> section,
11575        * so build a map of those first.
11576        *)
11577       let defines = List.fold_left (
11578         fun map ->
11579           function Xml.Element ("define", ["name", name], defn) ->
11580             StringMap.add name defn map
11581           | _ ->
11582               failwithf "%s: expected <define name=name/>" rng_input
11583       ) StringMap.empty defines in
11584       let defines = StringMap.mapi parse_rng defines in
11585
11586       (* Parse the <start> clause, passing the defines. *)
11587       parse_rng ~defines "<start>" gram
11588   | _ ->
11589       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11590         rng_input
11591
11592 let name_of_field = function
11593   | Element (name, _) | Attribute (name, _)
11594   | ZeroOrMore (Element (name, _))
11595   | OneOrMore (Element (name, _))
11596   | Optional (Element (name, _)) -> name
11597   | Optional (Attribute (name, _)) -> name
11598   | Text -> (* an unnamed field in an element *)
11599       "data"
11600   | rng ->
11601       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11602
11603 (* At the moment this function only generates OCaml types.  However we
11604  * should parameterize it later so it can generate types/structs in a
11605  * variety of languages.
11606  *)
11607 let generate_types xs =
11608   (* A simple type is one that can be printed out directly, eg.
11609    * "string option".  A complex type is one which has a name and has
11610    * to be defined via another toplevel definition, eg. a struct.
11611    *
11612    * generate_type generates code for either simple or complex types.
11613    * In the simple case, it returns the string ("string option").  In
11614    * the complex case, it returns the name ("mountpoint").  In the
11615    * complex case it has to print out the definition before returning,
11616    * so it should only be called when we are at the beginning of a
11617    * new line (BOL context).
11618    *)
11619   let rec generate_type = function
11620     | Text ->                                (* string *)
11621         "string", true
11622     | Choice values ->                        (* [`val1|`val2|...] *)
11623         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11624     | ZeroOrMore rng ->                        (* <rng> list *)
11625         let t, is_simple = generate_type rng in
11626         t ^ " list (* 0 or more *)", is_simple
11627     | OneOrMore rng ->                        (* <rng> list *)
11628         let t, is_simple = generate_type rng in
11629         t ^ " list (* 1 or more *)", is_simple
11630                                         (* virt-inspector hack: bool *)
11631     | Optional (Attribute (name, [Value "1"])) ->
11632         "bool", true
11633     | Optional rng ->                        (* <rng> list *)
11634         let t, is_simple = generate_type rng in
11635         t ^ " option", is_simple
11636                                         (* type name = { fields ... } *)
11637     | Element (name, fields) when is_attrs_interleave fields ->
11638         generate_type_struct name (get_attrs_interleave fields)
11639     | Element (name, [field])                (* type name = field *)
11640     | Attribute (name, [field]) ->
11641         let t, is_simple = generate_type field in
11642         if is_simple then (t, true)
11643         else (
11644           pr "type %s = %s\n" name t;
11645           name, false
11646         )
11647     | Element (name, fields) ->              (* type name = { fields ... } *)
11648         generate_type_struct name fields
11649     | rng ->
11650         failwithf "generate_type failed at: %s" (string_of_rng rng)
11651
11652   and is_attrs_interleave = function
11653     | [Interleave _] -> true
11654     | Attribute _ :: fields -> is_attrs_interleave fields
11655     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11656     | _ -> false
11657
11658   and get_attrs_interleave = function
11659     | [Interleave fields] -> fields
11660     | ((Attribute _) as field) :: fields
11661     | ((Optional (Attribute _)) as field) :: fields ->
11662         field :: get_attrs_interleave fields
11663     | _ -> assert false
11664
11665   and generate_types xs =
11666     List.iter (fun x -> ignore (generate_type x)) xs
11667
11668   and generate_type_struct name fields =
11669     (* Calculate the types of the fields first.  We have to do this
11670      * before printing anything so we are still in BOL context.
11671      *)
11672     let types = List.map fst (List.map generate_type fields) in
11673
11674     (* Special case of a struct containing just a string and another
11675      * field.  Turn it into an assoc list.
11676      *)
11677     match types with
11678     | ["string"; other] ->
11679         let fname1, fname2 =
11680           match fields with
11681           | [f1; f2] -> name_of_field f1, name_of_field f2
11682           | _ -> assert false in
11683         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11684         name, false
11685
11686     | types ->
11687         pr "type %s = {\n" name;
11688         List.iter (
11689           fun (field, ftype) ->
11690             let fname = name_of_field field in
11691             pr "  %s_%s : %s;\n" name fname ftype
11692         ) (List.combine fields types);
11693         pr "}\n";
11694         (* Return the name of this type, and
11695          * false because it's not a simple type.
11696          *)
11697         name, false
11698   in
11699
11700   generate_types xs
11701
11702 let generate_parsers xs =
11703   (* As for generate_type above, generate_parser makes a parser for
11704    * some type, and returns the name of the parser it has generated.
11705    * Because it (may) need to print something, it should always be
11706    * called in BOL context.
11707    *)
11708   let rec generate_parser = function
11709     | Text ->                                (* string *)
11710         "string_child_or_empty"
11711     | Choice values ->                        (* [`val1|`val2|...] *)
11712         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11713           (String.concat "|"
11714              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11715     | ZeroOrMore rng ->                        (* <rng> list *)
11716         let pa = generate_parser rng in
11717         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11718     | OneOrMore rng ->                        (* <rng> list *)
11719         let pa = generate_parser rng in
11720         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11721                                         (* virt-inspector hack: bool *)
11722     | Optional (Attribute (name, [Value "1"])) ->
11723         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11724     | Optional rng ->                        (* <rng> list *)
11725         let pa = generate_parser rng in
11726         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11727                                         (* type name = { fields ... } *)
11728     | Element (name, fields) when is_attrs_interleave fields ->
11729         generate_parser_struct name (get_attrs_interleave fields)
11730     | Element (name, [field]) ->        (* type name = field *)
11731         let pa = generate_parser field in
11732         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11733         pr "let %s =\n" parser_name;
11734         pr "  %s\n" pa;
11735         pr "let parse_%s = %s\n" name parser_name;
11736         parser_name
11737     | Attribute (name, [field]) ->
11738         let pa = generate_parser field in
11739         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11740         pr "let %s =\n" parser_name;
11741         pr "  %s\n" pa;
11742         pr "let parse_%s = %s\n" name parser_name;
11743         parser_name
11744     | Element (name, fields) ->              (* type name = { fields ... } *)
11745         generate_parser_struct name ([], fields)
11746     | rng ->
11747         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11748
11749   and is_attrs_interleave = function
11750     | [Interleave _] -> true
11751     | Attribute _ :: fields -> is_attrs_interleave fields
11752     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11753     | _ -> false
11754
11755   and get_attrs_interleave = function
11756     | [Interleave fields] -> [], fields
11757     | ((Attribute _) as field) :: fields
11758     | ((Optional (Attribute _)) as field) :: fields ->
11759         let attrs, interleaves = get_attrs_interleave fields in
11760         (field :: attrs), interleaves
11761     | _ -> assert false
11762
11763   and generate_parsers xs =
11764     List.iter (fun x -> ignore (generate_parser x)) xs
11765
11766   and generate_parser_struct name (attrs, interleaves) =
11767     (* Generate parsers for the fields first.  We have to do this
11768      * before printing anything so we are still in BOL context.
11769      *)
11770     let fields = attrs @ interleaves in
11771     let pas = List.map generate_parser fields in
11772
11773     (* Generate an intermediate tuple from all the fields first.
11774      * If the type is just a string + another field, then we will
11775      * return this directly, otherwise it is turned into a record.
11776      *
11777      * RELAX NG note: This code treats <interleave> and plain lists of
11778      * fields the same.  In other words, it doesn't bother enforcing
11779      * any ordering of fields in the XML.
11780      *)
11781     pr "let parse_%s x =\n" name;
11782     pr "  let t = (\n    ";
11783     let comma = ref false in
11784     List.iter (
11785       fun x ->
11786         if !comma then pr ",\n    ";
11787         comma := true;
11788         match x with
11789         | Optional (Attribute (fname, [field])), pa ->
11790             pr "%s x" pa
11791         | Optional (Element (fname, [field])), pa ->
11792             pr "%s (optional_child %S x)" pa fname
11793         | Attribute (fname, [Text]), _ ->
11794             pr "attribute %S x" fname
11795         | (ZeroOrMore _ | OneOrMore _), pa ->
11796             pr "%s x" pa
11797         | Text, pa ->
11798             pr "%s x" pa
11799         | (field, pa) ->
11800             let fname = name_of_field field in
11801             pr "%s (child %S x)" pa fname
11802     ) (List.combine fields pas);
11803     pr "\n  ) in\n";
11804
11805     (match fields with
11806      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11807          pr "  t\n"
11808
11809      | _ ->
11810          pr "  (Obj.magic t : %s)\n" name
11811 (*
11812          List.iter (
11813            function
11814            | (Optional (Attribute (fname, [field])), pa) ->
11815                pr "  %s_%s =\n" name fname;
11816                pr "    %s x;\n" pa
11817            | (Optional (Element (fname, [field])), pa) ->
11818                pr "  %s_%s =\n" name fname;
11819                pr "    (let x = optional_child %S x in\n" fname;
11820                pr "     %s x);\n" pa
11821            | (field, pa) ->
11822                let fname = name_of_field field in
11823                pr "  %s_%s =\n" name fname;
11824                pr "    (let x = child %S x in\n" fname;
11825                pr "     %s x);\n" pa
11826          ) (List.combine fields pas);
11827          pr "}\n"
11828 *)
11829     );
11830     sprintf "parse_%s" name
11831   in
11832
11833   generate_parsers xs
11834
11835 (* Generate ocaml/guestfs_inspector.mli. *)
11836 let generate_ocaml_inspector_mli () =
11837   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11838
11839   pr "\
11840 (** This is an OCaml language binding to the external [virt-inspector]
11841     program.
11842
11843     For more information, please read the man page [virt-inspector(1)].
11844 *)
11845
11846 ";
11847
11848   generate_types grammar;
11849   pr "(** The nested information returned from the {!inspect} function. *)\n";
11850   pr "\n";
11851
11852   pr "\
11853 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11854 (** To inspect a libvirt domain called [name], pass a singleton
11855     list: [inspect [name]].  When using libvirt only, you may
11856     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11857
11858     To inspect a disk image or images, pass a list of the filenames
11859     of the disk images: [inspect filenames]
11860
11861     This function inspects the given guest or disk images and
11862     returns a list of operating system(s) found and a large amount
11863     of information about them.  In the vast majority of cases,
11864     a virtual machine only contains a single operating system.
11865
11866     If the optional [~xml] parameter is given, then this function
11867     skips running the external virt-inspector program and just
11868     parses the given XML directly (which is expected to be XML
11869     produced from a previous run of virt-inspector).  The list of
11870     names and connect URI are ignored in this case.
11871
11872     This function can throw a wide variety of exceptions, for example
11873     if the external virt-inspector program cannot be found, or if
11874     it doesn't generate valid XML.
11875 *)
11876 "
11877
11878 (* Generate ocaml/guestfs_inspector.ml. *)
11879 let generate_ocaml_inspector_ml () =
11880   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11881
11882   pr "open Unix\n";
11883   pr "\n";
11884
11885   generate_types grammar;
11886   pr "\n";
11887
11888   pr "\
11889 (* Misc functions which are used by the parser code below. *)
11890 let first_child = function
11891   | Xml.Element (_, _, c::_) -> c
11892   | Xml.Element (name, _, []) ->
11893       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11894   | Xml.PCData str ->
11895       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11896
11897 let string_child_or_empty = function
11898   | Xml.Element (_, _, [Xml.PCData s]) -> s
11899   | Xml.Element (_, _, []) -> \"\"
11900   | Xml.Element (x, _, _) ->
11901       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11902                 x ^ \" instead\")
11903   | Xml.PCData str ->
11904       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11905
11906 let optional_child name xml =
11907   let children = Xml.children xml in
11908   try
11909     Some (List.find (function
11910                      | Xml.Element (n, _, _) when n = name -> true
11911                      | _ -> false) children)
11912   with
11913     Not_found -> None
11914
11915 let child name xml =
11916   match optional_child name xml with
11917   | Some c -> c
11918   | None ->
11919       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11920
11921 let attribute name xml =
11922   try Xml.attrib xml name
11923   with Xml.No_attribute _ ->
11924     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11925
11926 ";
11927
11928   generate_parsers grammar;
11929   pr "\n";
11930
11931   pr "\
11932 (* Run external virt-inspector, then use parser to parse the XML. *)
11933 let inspect ?connect ?xml names =
11934   let xml =
11935     match xml with
11936     | None ->
11937         if names = [] then invalid_arg \"inspect: no names given\";
11938         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11939           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11940           names in
11941         let cmd = List.map Filename.quote cmd in
11942         let cmd = String.concat \" \" cmd in
11943         let chan = open_process_in cmd in
11944         let xml = Xml.parse_in chan in
11945         (match close_process_in chan with
11946          | WEXITED 0 -> ()
11947          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11948          | WSIGNALED i | WSTOPPED i ->
11949              failwith (\"external virt-inspector command died or stopped on sig \" ^
11950                        string_of_int i)
11951         );
11952         xml
11953     | Some doc ->
11954         Xml.parse_string doc in
11955   parse_operatingsystems xml
11956 "
11957
11958 and generate_max_proc_nr () =
11959   pr "%d\n" max_proc_nr
11960
11961 let output_to filename k =
11962   let filename_new = filename ^ ".new" in
11963   chan := open_out filename_new;
11964   k ();
11965   close_out !chan;
11966   chan := Pervasives.stdout;
11967
11968   (* Is the new file different from the current file? *)
11969   if Sys.file_exists filename && files_equal filename filename_new then
11970     unlink filename_new                 (* same, so skip it *)
11971   else (
11972     (* different, overwrite old one *)
11973     (try chmod filename 0o644 with Unix_error _ -> ());
11974     rename filename_new filename;
11975     chmod filename 0o444;
11976     printf "written %s\n%!" filename;
11977   )
11978
11979 let perror msg = function
11980   | Unix_error (err, _, _) ->
11981       eprintf "%s: %s\n" msg (error_message err)
11982   | exn ->
11983       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11984
11985 (* Main program. *)
11986 let () =
11987   let lock_fd =
11988     try openfile "HACKING" [O_RDWR] 0
11989     with
11990     | Unix_error (ENOENT, _, _) ->
11991         eprintf "\
11992 You are probably running this from the wrong directory.
11993 Run it from the top source directory using the command
11994   src/generator.ml
11995 ";
11996         exit 1
11997     | exn ->
11998         perror "open: HACKING" exn;
11999         exit 1 in
12000
12001   (* Acquire a lock so parallel builds won't try to run the generator
12002    * twice at the same time.  Subsequent builds will wait for the first
12003    * one to finish.  Note the lock is released implicitly when the
12004    * program exits.
12005    *)
12006   (try lockf lock_fd F_LOCK 1
12007    with exn ->
12008      perror "lock: HACKING" exn;
12009      exit 1);
12010
12011   check_functions ();
12012
12013   output_to "src/guestfs_protocol.x" generate_xdr;
12014   output_to "src/guestfs-structs.h" generate_structs_h;
12015   output_to "src/guestfs-actions.h" generate_actions_h;
12016   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12017   output_to "src/guestfs-actions.c" generate_client_actions;
12018   output_to "src/guestfs-bindtests.c" generate_bindtests;
12019   output_to "src/guestfs-structs.pod" generate_structs_pod;
12020   output_to "src/guestfs-actions.pod" generate_actions_pod;
12021   output_to "src/guestfs-availability.pod" generate_availability_pod;
12022   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12023   output_to "src/libguestfs.syms" generate_linker_script;
12024   output_to "daemon/actions.h" generate_daemon_actions_h;
12025   output_to "daemon/stubs.c" generate_daemon_actions;
12026   output_to "daemon/names.c" generate_daemon_names;
12027   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12028   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12029   output_to "capitests/tests.c" generate_tests;
12030   output_to "fish/cmds.c" generate_fish_cmds;
12031   output_to "fish/completion.c" generate_fish_completion;
12032   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12033   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12034   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12035   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12036   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12037   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12038   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12039   output_to "perl/Guestfs.xs" generate_perl_xs;
12040   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12041   output_to "perl/bindtests.pl" generate_perl_bindtests;
12042   output_to "python/guestfs-py.c" generate_python_c;
12043   output_to "python/guestfs.py" generate_python_py;
12044   output_to "python/bindtests.py" generate_python_bindtests;
12045   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12046   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12047   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12048
12049   List.iter (
12050     fun (typ, jtyp) ->
12051       let cols = cols_of_struct typ in
12052       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12053       output_to filename (generate_java_struct jtyp cols);
12054   ) java_structs;
12055
12056   output_to "java/Makefile.inc" generate_java_makefile_inc;
12057   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12058   output_to "java/Bindtests.java" generate_java_bindtests;
12059   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12060   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12061   output_to "csharp/Libguestfs.cs" generate_csharp;
12062
12063   (* Always generate this file last, and unconditionally.  It's used
12064    * by the Makefile to know when we must re-run the generator.
12065    *)
12066   let chan = open_out "src/stamp-generator" in
12067   fprintf chan "1\n";
12068   close_out chan;
12069
12070   printf "generated %d lines of code\n" !lines